Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / view / viewfun6.cxx
blobb65eaf3b758666acac2b16247d205a75e32257d7
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 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svx/svdundo.hxx>
22 #include <svx/svdocapt.hxx>
23 #include <sfx2/bindings.hxx>
24 #include <sfx2/dispatch.hxx>
25 #include <vcl/msgbox.hxx>
26 #include <svl/zforlist.hxx>
27 #include <svl/zformat.hxx>
28 #include <editeng/editview.hxx>
30 #include "viewfunc.hxx"
31 #include "detfunc.hxx"
32 #include "detdata.hxx"
33 #include "viewdata.hxx"
34 #include "drwlayer.hxx"
35 #include "docsh.hxx"
36 #include "undocell.hxx"
37 #include "futext.hxx"
38 #include "docfunc.hxx"
39 #include "globstr.hrc"
40 #include "sc.hrc"
41 #include "fusel.hxx"
42 #include "reftokenhelper.hxx"
43 #include "externalrefmgr.hxx"
44 #include "formulacell.hxx"
45 #include "markdata.hxx"
46 #include "drawview.hxx"
47 #include "globalnames.hxx"
48 #include "inputhdl.hxx"
50 #include <vector>
52 using ::std::vector;
54 void ScViewFunc::DetectiveAddPred()
56 ScDocShell* pDocSh = GetViewData()->GetDocShell();
57 pDocSh->GetDocFunc().DetectiveAddPred( GetViewData()->GetCurPos() );
58 RecalcPPT(); //! use broadcast in DocFunc instead?
61 void ScViewFunc::DetectiveDelPred()
63 ScDocShell* pDocSh = GetViewData()->GetDocShell();
64 pDocSh->GetDocFunc().DetectiveDelPred( GetViewData()->GetCurPos() );
65 RecalcPPT();
68 void ScViewFunc::DetectiveAddSucc()
70 ScDocShell* pDocSh = GetViewData()->GetDocShell();
71 pDocSh->GetDocFunc().DetectiveAddSucc( GetViewData()->GetCurPos() );
72 RecalcPPT();
75 void ScViewFunc::DetectiveDelSucc()
77 ScDocShell* pDocSh = GetViewData()->GetDocShell();
78 pDocSh->GetDocFunc().DetectiveDelSucc( GetViewData()->GetCurPos() );
79 RecalcPPT();
82 void ScViewFunc::DetectiveAddError()
84 ScDocShell* pDocSh = GetViewData()->GetDocShell();
85 pDocSh->GetDocFunc().DetectiveAddError( GetViewData()->GetCurPos() );
86 RecalcPPT();
89 void ScViewFunc::DetectiveDelAll()
91 ScDocShell* pDocSh = GetViewData()->GetDocShell();
92 pDocSh->GetDocFunc().DetectiveDelAll( GetViewData()->GetTabNo() );
93 RecalcPPT();
96 void ScViewFunc::DetectiveMarkInvalid()
98 ScDocShell* pDocSh = GetViewData()->GetDocShell();
99 pDocSh->GetDocFunc().DetectiveMarkInvalid( GetViewData()->GetTabNo() );
100 RecalcPPT();
103 void ScViewFunc::DetectiveRefresh()
105 ScDocShell* pDocSh = GetViewData()->GetDocShell();
106 pDocSh->GetDocFunc().DetectiveRefresh();
107 RecalcPPT();
110 static void lcl_jumpToRange(const ScRange& rRange, ScViewData* pView, ScDocument* pDoc)
112 OUString aAddrText(rRange.Format(SCR_ABS_3D, pDoc));
113 SfxStringItem aPosItem(SID_CURRENTCELL, aAddrText);
114 SfxBoolItem aUnmarkItem(FN_PARAM_1, true); // remove existing selection
115 pView->GetDispatcher().Execute(
116 SID_CURRENTCELL, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD,
117 &aPosItem, &aUnmarkItem, 0L);
120 void ScViewFunc::MarkAndJumpToRanges(const ScRangeList& rRanges)
122 ScViewData* pView = GetViewData();
123 ScDocShell* pDocSh = pView->GetDocShell();
125 ScRangeList aRanges(rRanges);
126 ScRangeList aRangesToMark;
127 ScAddress aCurPos = pView->GetCurPos();
128 size_t ListSize = aRanges.size();
129 for ( size_t i = 0; i < ListSize; ++i )
131 const ScRange* p = aRanges[i];
132 // Collect only those ranges that are on the same sheet as the current
133 // cursor.
134 if (p->aStart.Tab() == aCurPos.Tab())
135 aRangesToMark.Append(*p);
138 if (aRangesToMark.empty())
139 return;
141 // Jump to the first range of all precedent ranges.
142 const ScRange* p = aRangesToMark.front();
143 lcl_jumpToRange(*p, pView, pDocSh->GetDocument());
145 ListSize = aRangesToMark.size();
146 for ( size_t i = 0; i < ListSize; ++i )
148 p = aRangesToMark[i];
149 MarkRange(*p, false, true);
153 void ScViewFunc::DetectiveMarkPred()
155 ScViewData* pView = GetViewData();
156 ScDocShell* pDocSh = pView->GetDocShell();
157 ScDocument* pDoc = pDocSh->GetDocument();
158 ScMarkData& rMarkData = pView->GetMarkData();
159 ScAddress aCurPos = pView->GetCurPos();
160 ScRangeList aRanges;
161 if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
162 rMarkData.FillRangeListWithMarks(&aRanges, false);
163 else
164 aRanges.Append(aCurPos);
166 vector<ScTokenRef> aRefTokens;
167 pDocSh->GetDocFunc().DetectiveCollectAllPreds(aRanges, aRefTokens);
169 if (aRefTokens.empty())
170 // No precedents found. Nothing to do.
171 return;
173 ScTokenRef p = aRefTokens.front();
174 if (ScRefTokenHelper::isExternalRef(p))
176 // This is external. Open the external document if available, and
177 // jump to the destination.
179 sal_uInt16 nFileId = p->GetIndex();
180 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
181 const OUString* pPath = pRefMgr->getExternalFileName(nFileId);
183 ScRange aRange;
184 if (pPath && ScRefTokenHelper::getRangeFromToken(aRange, p, aCurPos, true))
186 OUString aTabName = p->GetString().getString();
187 OUStringBuffer aBuf;
188 aBuf.append(*pPath);
189 aBuf.append('#');
190 aBuf.append(aTabName);
191 aBuf.append('.');
193 OUString aRangeStr(aRange.Format(SCA_VALID));
194 aBuf.append(aRangeStr);
196 ScGlobal::OpenURL(aBuf.makeStringAndClear(), OUString());
198 return;
200 else
202 ScRange aRange;
203 ScRefTokenHelper::getRangeFromToken(aRange, p, aCurPos, false);
204 if (aRange.aStart.Tab() != aCurPos.Tab())
206 // The first precedent range is on a different sheet. Jump to it
207 // immediately and forget the rest.
208 lcl_jumpToRange(aRange, pView, pDoc);
209 return;
213 ScRangeList aDestRanges;
214 ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens, aCurPos);
215 MarkAndJumpToRanges(aDestRanges);
218 void ScViewFunc::DetectiveMarkSucc()
220 ScViewData* pView = GetViewData();
221 ScDocShell* pDocSh = pView->GetDocShell();
222 ScMarkData& rMarkData = pView->GetMarkData();
223 ScAddress aCurPos = pView->GetCurPos();
224 ScRangeList aRanges;
225 if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
226 rMarkData.FillRangeListWithMarks(&aRanges, false);
227 else
228 aRanges.Append(aCurPos);
230 vector<ScTokenRef> aRefTokens;
231 pDocSh->GetDocFunc().DetectiveCollectAllSuccs(aRanges, aRefTokens);
233 if (aRefTokens.empty())
234 // No dependents found. Nothing to do.
235 return;
237 ScRangeList aDestRanges;
238 ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens, aCurPos);
239 MarkAndJumpToRanges(aDestRanges);
242 /** Insert date or time into current cell.
244 If cell is in input or edit mode, insert date/time at cursor position, else
245 create a date or time or date+time cell as follows:
247 - key date on time cell => current date + time of cell => date+time formatted cell
248 - unless time cell was empty or 00:00 time => current date => date formatted cell
249 - key date on date+time cell => current date + 00:00 time => date+time formatted cell
250 - unless date was current date => current date => date formatted cell
251 - key date on other cell => current date => date formatted cell
252 - key time on date cell => date of cell + current time => date+time formatted cell
253 - unless date cell was empty => current time => time formatted cell
254 - key time on date+time cell => current time => time formatted cell
255 - unless cell was empty => current date+time => date+time formatted cell
256 - key time on other cell => current time => time formatted cell
258 void ScViewFunc::InsertCurrentTime(short nReqFmt, const OUString& rUndoStr)
260 ScViewData& rViewData = *GetViewData();
262 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl( rViewData.GetViewShell());
263 bool bInputMode = (pInputHdl && pInputHdl->IsInputMode());
265 ScDocShell* pDocSh = rViewData.GetDocShell();
266 ScDocument& rDoc = *pDocSh->GetDocument();
267 ScAddress aCurPos = rViewData.GetCurPos();
268 const sal_uInt32 nCurNumFormat = rDoc.GetNumberFormat(aCurPos);
269 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
270 const SvNumberformat* pCurNumFormatEntry = pFormatter->GetEntry(nCurNumFormat);
271 const short nCurNumFormatType = (pCurNumFormatEntry ?
272 (pCurNumFormatEntry->GetType() & ~NUMBERFORMAT_DEFINED) : NUMBERFORMAT_UNDEFINED);
274 if (bInputMode)
276 double fVal = 0.0;
277 sal_uInt32 nFormat = 0;
278 switch (nReqFmt)
280 case NUMBERFORMAT_DATE:
282 Date aActDate( Date::SYSTEM );
283 fVal = aActDate - *pFormatter->GetNullDate();
284 if (nCurNumFormatType == NUMBERFORMAT_DATE)
285 nFormat = nCurNumFormat;
287 break;
288 case NUMBERFORMAT_TIME:
290 Time aActTime( Time::SYSTEM );
291 fVal = aActTime.GetTimeInDays();
292 if (nCurNumFormatType == NUMBERFORMAT_TIME)
293 nFormat = nCurNumFormat;
295 break;
296 default:
297 assert(!"unhandled current date/time request");
298 nReqFmt = NUMBERFORMAT_DATETIME;
299 // fallthru
300 case NUMBERFORMAT_DATETIME:
302 DateTime aActDateTime( DateTime::SYSTEM );
303 fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
304 if (nCurNumFormatType == NUMBERFORMAT_DATETIME)
305 nFormat = nCurNumFormat;
307 break;
310 if (!nFormat)
312 const LanguageType nLang = (pCurNumFormatEntry ? pCurNumFormatEntry->GetLanguage() : ScGlobal::eLnge);
313 nFormat = pFormatter->GetStandardFormat( nReqFmt, nLang);
314 // This would return a more precise format with seconds and 100th
315 // seconds for a time request.
316 //nFormat = pFormatter->GetStandardFormat( fVal, nFormat, nReqFmt, nLang);
318 OUString aString;
319 Color* pColor;
320 pFormatter->GetOutputString( fVal, nFormat, aString, &pColor);
322 pInputHdl->DataChanging();
323 EditView* pTopView = pInputHdl->GetTopView();
324 if (pTopView)
325 pTopView->InsertText( aString);
326 EditView* pTableView = pInputHdl->GetTableView();
327 if (pTableView)
328 pTableView->InsertText( aString);
329 pInputHdl->DataChanged( false, true);
331 else
333 bool bForceReqFmt = false;
334 const double fCell = rDoc.GetValue( aCurPos);
335 // Combine requested date/time stamp with existing cell time/date, if any.
336 switch (nReqFmt)
338 case NUMBERFORMAT_DATE:
339 switch (nCurNumFormatType)
341 case NUMBERFORMAT_TIME:
342 // An empty cell formatted as time (or 00:00 time) shall
343 // not result in the current date with 00:00 time, but only
344 // in current date.
345 if (fCell != 0.0)
346 nReqFmt = NUMBERFORMAT_DATETIME;
347 break;
348 case NUMBERFORMAT_DATETIME:
350 // Force to only date if the existing date+time is the
351 // current date. This way inserting current date twice
352 // on an existing date+time cell can be used to force
353 // date, which otherwise would only be possible by
354 // applying a date format.
355 double fDate = rtl::math::approxFloor( fCell);
356 if (fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
357 bForceReqFmt = true;
359 break;
361 break;
362 case NUMBERFORMAT_TIME:
363 switch (nCurNumFormatType)
365 case NUMBERFORMAT_DATE:
366 // An empty cell formatted as date shall not result in the
367 // null date and current time, but only in current time.
368 if (fCell != 0.0)
369 nReqFmt = NUMBERFORMAT_DATETIME;
370 break;
371 case NUMBERFORMAT_DATETIME:
372 // Requesting current time on an empty date+time cell
373 // inserts both current date+time.
374 if (fCell == 0.0)
375 nReqFmt = NUMBERFORMAT_DATETIME;
376 else
378 // Add current time to an existing date+time where time is
379 // zero and date is current date, else force time only.
380 double fDate = rtl::math::approxFloor( fCell);
381 double fTime = fCell - fDate;
382 if (fTime == 0.0 && fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
383 nReqFmt = NUMBERFORMAT_DATETIME;
384 else
385 bForceReqFmt = true;
387 break;
389 break;
390 default:
391 assert(!"unhandled current date/time request");
392 nReqFmt = NUMBERFORMAT_DATETIME;
393 // fallthru
394 case NUMBERFORMAT_DATETIME:
395 break;
397 double fVal = 0.0;
398 switch (nReqFmt)
400 case NUMBERFORMAT_DATE:
402 Date aActDate( Date::SYSTEM );
403 fVal = aActDate - *pFormatter->GetNullDate();
405 break;
406 case NUMBERFORMAT_TIME:
408 Time aActTime( Time::SYSTEM );
409 fVal = aActTime.GetTimeInDays();
411 break;
412 case NUMBERFORMAT_DATETIME:
413 switch (nCurNumFormatType)
415 case NUMBERFORMAT_DATE:
417 double fDate = rtl::math::approxFloor( fCell);
418 Time aActTime( Time::SYSTEM );
419 fVal = fDate + aActTime.GetTimeInDays();
421 break;
422 case NUMBERFORMAT_TIME:
424 double fTime = fCell - rtl::math::approxFloor( fCell);
425 Date aActDate( Date::SYSTEM );
426 fVal = (aActDate - *pFormatter->GetNullDate()) + fTime;
428 break;
429 default:
431 DateTime aActDateTime( DateTime::SYSTEM );
432 // Converting the null date to DateTime forces the
433 // correct operator-() to be used, resulting in a
434 // fractional date+time instead of only date value.
435 fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
438 break;
441 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
442 pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
444 pDocSh->GetDocFunc().SetValueCell(aCurPos, fVal, true);
446 // Set the new cell format only when it differs from the current cell
447 // format type. Preserve a date+time format unless we force a format
448 // through.
449 if (bForceReqFmt || (nReqFmt != nCurNumFormatType && nCurNumFormatType != NUMBERFORMAT_DATETIME))
450 SetNumberFormat(nReqFmt);
451 else
452 rViewData.UpdateInputHandler(); // update input bar with new value
454 pUndoMgr->LeaveListAction();
458 void ScViewFunc::ShowNote( bool bShow )
460 if( bShow )
461 HideNoteMarker();
462 const ScViewData& rViewData = *GetViewData();
463 ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
464 // show note moved to ScDocFunc, to be able to use it in notesuno.cxx
465 rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow );
468 void ScViewFunc::EditNote()
470 // for editing display and activate
472 ScDocShell* pDocSh = GetViewData()->GetDocShell();
473 ScDocument* pDoc = pDocSh->GetDocument();
474 SCCOL nCol = GetViewData()->GetCurX();
475 SCROW nRow = GetViewData()->GetCurY();
476 SCTAB nTab = GetViewData()->GetTabNo();
477 ScAddress aPos( nCol, nRow, nTab );
479 // start drawing undo to catch undo action for insertion of the caption object
480 pDocSh->MakeDrawLayer();
481 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
482 pDrawLayer->BeginCalcUndo(true);
483 // generated undo action is processed in FuText::StopEditMode
485 // get existing note or create a new note (including caption drawing object)
486 if( ScPostIt* pNote = pDoc->GetOrCreateNote( aPos ) )
488 // hide temporary note caption
489 HideNoteMarker();
490 // show caption object without changing internal visibility state
491 pNote->ShowCaptionTemp( aPos );
493 /* Drawing object has been created in ScDocument::GetOrCreateNote() or
494 in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
495 return a caption object. */
496 if( SdrCaptionObj* pCaption = pNote->GetCaption() )
498 if ( ScDrawView* pScDrawView = GetScDrawView() )
499 pScDrawView->SyncForGrid( pCaption );
500 // #i33764# enable the resize handles before starting edit mode
501 if( FuPoor* pDraw = GetDrawFuncPtr() )
502 static_cast< FuSelection* >( pDraw )->ActivateNoteHandles( pCaption );
504 // activate object (as in FuSelection::TestComment)
505 GetViewData()->GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD );
506 // now get the created FuText and set into EditMode
507 FuPoor* pPoor = GetDrawFuncPtr();
508 if ( pPoor && (pPoor->GetSlotID() == SID_DRAW_NOTEEDIT) ) // has no RTTI
510 ScrollToObject( pCaption ); // make object fully visible
511 static_cast< FuText* >( pPoor )->SetInEditMode( pCaption );
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */