fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / viewfun6.cxx
blob20db7b000d5211b615fd8e60342b8351d3d88120
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 .
20 #include <svx/svdundo.hxx>
21 #include <svx/svdocapt.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <vcl/msgbox.hxx>
25 #include <svl/zforlist.hxx>
26 #include <svl/zformat.hxx>
27 #include <editeng/editview.hxx>
29 #include "viewfunc.hxx"
30 #include "detfunc.hxx"
31 #include "detdata.hxx"
32 #include "viewdata.hxx"
33 #include "drwlayer.hxx"
34 #include "docsh.hxx"
35 #include "undocell.hxx"
36 #include "futext.hxx"
37 #include "docfunc.hxx"
38 #include "globstr.hrc"
39 #include "sc.hrc"
40 #include "fusel.hxx"
41 #include "reftokenhelper.hxx"
42 #include "externalrefmgr.hxx"
43 #include "formulacell.hxx"
44 #include "markdata.hxx"
45 #include "drawview.hxx"
46 #include "globalnames.hxx"
47 #include "inputhdl.hxx"
49 #include <vector>
51 using ::std::vector;
53 void ScViewFunc::DetectiveAddPred()
55 ScDocShell* pDocSh = GetViewData().GetDocShell();
56 pDocSh->GetDocFunc().DetectiveAddPred( GetViewData().GetCurPos() );
57 RecalcPPT(); //! use broadcast in DocFunc instead?
60 void ScViewFunc::DetectiveDelPred()
62 ScDocShell* pDocSh = GetViewData().GetDocShell();
63 pDocSh->GetDocFunc().DetectiveDelPred( GetViewData().GetCurPos() );
64 RecalcPPT();
67 void ScViewFunc::DetectiveAddSucc()
69 ScDocShell* pDocSh = GetViewData().GetDocShell();
70 pDocSh->GetDocFunc().DetectiveAddSucc( GetViewData().GetCurPos() );
71 RecalcPPT();
74 void ScViewFunc::DetectiveDelSucc()
76 ScDocShell* pDocSh = GetViewData().GetDocShell();
77 pDocSh->GetDocFunc().DetectiveDelSucc( GetViewData().GetCurPos() );
78 RecalcPPT();
81 void ScViewFunc::DetectiveAddError()
83 ScDocShell* pDocSh = GetViewData().GetDocShell();
84 pDocSh->GetDocFunc().DetectiveAddError( GetViewData().GetCurPos() );
85 RecalcPPT();
88 void ScViewFunc::DetectiveDelAll()
90 ScDocShell* pDocSh = GetViewData().GetDocShell();
91 pDocSh->GetDocFunc().DetectiveDelAll( GetViewData().GetTabNo() );
92 RecalcPPT();
95 void ScViewFunc::DetectiveMarkInvalid()
97 ScDocShell* pDocSh = GetViewData().GetDocShell();
98 pDocSh->GetDocFunc().DetectiveMarkInvalid( GetViewData().GetTabNo() );
99 RecalcPPT();
102 void ScViewFunc::DetectiveRefresh()
104 ScDocShell* pDocSh = GetViewData().GetDocShell();
105 pDocSh->GetDocFunc().DetectiveRefresh();
106 RecalcPPT();
109 static void lcl_jumpToRange(const ScRange& rRange, ScViewData* pView, ScDocument* pDoc)
111 OUString aAddrText(rRange.Format(SCR_ABS_3D, pDoc));
112 SfxStringItem aPosItem(SID_CURRENTCELL, aAddrText);
113 SfxBoolItem aUnmarkItem(FN_PARAM_1, true); // remove existing selection
114 pView->GetDispatcher().Execute(
115 SID_CURRENTCELL, SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
116 &aPosItem, &aUnmarkItem, 0L);
119 void ScViewFunc::MarkAndJumpToRanges(const ScRangeList& rRanges)
121 ScViewData& rView = GetViewData();
122 ScDocShell* pDocSh = rView.GetDocShell();
124 ScRangeList aRanges(rRanges);
125 ScRangeList aRangesToMark;
126 ScAddress aCurPos = rView.GetCurPos();
127 size_t ListSize = aRanges.size();
128 for ( size_t i = 0; i < ListSize; ++i )
130 const ScRange* p = aRanges[i];
131 // Collect only those ranges that are on the same sheet as the current
132 // cursor.
133 if (p->aStart.Tab() == aCurPos.Tab())
134 aRangesToMark.Append(*p);
137 if (aRangesToMark.empty())
138 return;
140 // Jump to the first range of all precedent ranges.
141 const ScRange* p = aRangesToMark.front();
142 lcl_jumpToRange(*p, &rView, &pDocSh->GetDocument());
144 ListSize = aRangesToMark.size();
145 for ( size_t i = 0; i < ListSize; ++i )
147 p = aRangesToMark[i];
148 MarkRange(*p, false, true);
152 void ScViewFunc::DetectiveMarkPred()
154 ScViewData& rView = GetViewData();
155 ScDocShell* pDocSh = rView.GetDocShell();
156 ScDocument& rDoc = pDocSh->GetDocument();
157 ScMarkData& rMarkData = rView.GetMarkData();
158 ScAddress aCurPos = rView.GetCurPos();
159 ScRangeList aRanges;
160 if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
161 rMarkData.FillRangeListWithMarks(&aRanges, false);
162 else
163 aRanges.Append(aCurPos);
165 vector<ScTokenRef> aRefTokens;
166 pDocSh->GetDocFunc().DetectiveCollectAllPreds(aRanges, aRefTokens);
168 if (aRefTokens.empty())
169 // No precedents found. Nothing to do.
170 return;
172 ScTokenRef p = aRefTokens.front();
173 if (ScRefTokenHelper::isExternalRef(p))
175 // This is external. Open the external document if available, and
176 // jump to the destination.
178 sal_uInt16 nFileId = p->GetIndex();
179 ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
180 const OUString* pPath = pRefMgr->getExternalFileName(nFileId);
182 ScRange aRange;
183 if (pPath && ScRefTokenHelper::getRangeFromToken(aRange, p, aCurPos, true))
185 OUString aTabName = p->GetString().getString();
186 OUStringBuffer aBuf;
187 aBuf.append(*pPath);
188 aBuf.append('#');
189 aBuf.append(aTabName);
190 aBuf.append('.');
192 OUString aRangeStr(aRange.Format(SCA_VALID));
193 aBuf.append(aRangeStr);
195 ScGlobal::OpenURL(aBuf.makeStringAndClear(), OUString());
197 return;
199 else
201 ScRange aRange;
202 ScRefTokenHelper::getRangeFromToken(aRange, p, aCurPos, false);
203 if (aRange.aStart.Tab() != aCurPos.Tab())
205 // The first precedent range is on a different sheet. Jump to it
206 // immediately and forget the rest.
207 lcl_jumpToRange(aRange, &rView, &rDoc);
208 return;
212 ScRangeList aDestRanges;
213 ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens, aCurPos);
214 MarkAndJumpToRanges(aDestRanges);
217 void ScViewFunc::DetectiveMarkSucc()
219 ScViewData& rView = GetViewData();
220 ScDocShell* pDocSh = rView.GetDocShell();
221 ScMarkData& rMarkData = rView.GetMarkData();
222 ScAddress aCurPos = rView.GetCurPos();
223 ScRangeList aRanges;
224 if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
225 rMarkData.FillRangeListWithMarks(&aRanges, false);
226 else
227 aRanges.Append(aCurPos);
229 vector<ScTokenRef> aRefTokens;
230 pDocSh->GetDocFunc().DetectiveCollectAllSuccs(aRanges, aRefTokens);
232 if (aRefTokens.empty())
233 // No dependents found. Nothing to do.
234 return;
236 ScRangeList aDestRanges;
237 ScRefTokenHelper::getRangeListFromTokens(aDestRanges, aRefTokens, aCurPos);
238 MarkAndJumpToRanges(aDestRanges);
241 /** Insert date or time into current cell.
243 If cell is in input or edit mode, insert date/time at cursor position, else
244 create a date or time or date+time cell as follows:
246 - key date on time cell => current date + time of cell => date+time formatted cell
247 - unless time cell was empty or 00:00 time => current date => date formatted cell
248 - key date on date+time cell => current date + 00:00 time => date+time formatted cell
249 - unless date was current date => current date => date formatted cell
250 - key date on other cell => current date => date formatted cell
251 - key time on date cell => date of cell + current time => date+time formatted cell
252 - unless date cell was empty => current time => time formatted cell
253 - key time on date+time cell => current time => time formatted cell
254 - unless cell was empty => current date+time => date+time formatted cell
255 - key time on other cell => current time => time formatted cell
257 void ScViewFunc::InsertCurrentTime(short nReqFmt, const OUString& rUndoStr)
259 ScViewData& rViewData = GetViewData();
261 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl( rViewData.GetViewShell());
262 bool bInputMode = (pInputHdl && pInputHdl->IsInputMode());
264 ScDocShell* pDocSh = rViewData.GetDocShell();
265 ScDocument& rDoc = pDocSh->GetDocument();
266 ScAddress aCurPos = rViewData.GetCurPos();
267 const sal_uInt32 nCurNumFormat = rDoc.GetNumberFormat(aCurPos);
268 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
269 const SvNumberformat* pCurNumFormatEntry = pFormatter->GetEntry(nCurNumFormat);
270 const short nCurNumFormatType = (pCurNumFormatEntry ?
271 (pCurNumFormatEntry->GetType() & ~css::util::NumberFormat::DEFINED) : css::util::NumberFormat::UNDEFINED);
273 if (bInputMode)
275 double fVal = 0.0;
276 sal_uInt32 nFormat = 0;
277 switch (nReqFmt)
279 case css::util::NumberFormat::DATE:
281 Date aActDate( Date::SYSTEM );
282 fVal = aActDate - *pFormatter->GetNullDate();
283 if (nCurNumFormatType == css::util::NumberFormat::DATE)
284 nFormat = nCurNumFormat;
286 break;
287 case css::util::NumberFormat::TIME:
289 tools::Time aActTime( tools::Time::SYSTEM );
290 fVal = aActTime.GetTimeInDays();
291 if (nCurNumFormatType == css::util::NumberFormat::TIME)
292 nFormat = nCurNumFormat;
294 break;
295 default:
296 assert(!"unhandled current date/time request");
297 nReqFmt = css::util::NumberFormat::DATETIME;
298 // fallthru
299 case css::util::NumberFormat::DATETIME:
301 DateTime aActDateTime( DateTime::SYSTEM );
302 fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
303 if (nCurNumFormatType == css::util::NumberFormat::DATETIME)
304 nFormat = nCurNumFormat;
306 break;
309 if (!nFormat)
311 const LanguageType nLang = (pCurNumFormatEntry ? pCurNumFormatEntry->GetLanguage() : ScGlobal::eLnge);
312 nFormat = pFormatter->GetStandardFormat( nReqFmt, nLang);
313 // This would return a more precise format with seconds and 100th
314 // seconds for a time request.
315 //nFormat = pFormatter->GetStandardFormat( fVal, nFormat, nReqFmt, nLang);
317 OUString aString;
318 Color* pColor;
319 pFormatter->GetOutputString( fVal, nFormat, aString, &pColor);
321 pInputHdl->DataChanging();
322 EditView* pTopView = pInputHdl->GetTopView();
323 if (pTopView)
324 pTopView->InsertText( aString);
325 EditView* pTableView = pInputHdl->GetTableView();
326 if (pTableView)
327 pTableView->InsertText( aString);
328 pInputHdl->DataChanged( false, true);
330 else
332 bool bForceReqFmt = false;
333 const double fCell = rDoc.GetValue( aCurPos);
334 // Combine requested date/time stamp with existing cell time/date, if any.
335 switch (nReqFmt)
337 case css::util::NumberFormat::DATE:
338 switch (nCurNumFormatType)
340 case css::util::NumberFormat::TIME:
341 // An empty cell formatted as time (or 00:00 time) shall
342 // not result in the current date with 00:00 time, but only
343 // in current date.
344 if (fCell != 0.0)
345 nReqFmt = css::util::NumberFormat::DATETIME;
346 break;
347 case css::util::NumberFormat::DATETIME:
349 // Force to only date if the existing date+time is the
350 // current date. This way inserting current date twice
351 // on an existing date+time cell can be used to force
352 // date, which otherwise would only be possible by
353 // applying a date format.
354 double fDate = rtl::math::approxFloor( fCell);
355 if (fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
356 bForceReqFmt = true;
358 break;
360 break;
361 case css::util::NumberFormat::TIME:
362 switch (nCurNumFormatType)
364 case css::util::NumberFormat::DATE:
365 // An empty cell formatted as date shall not result in the
366 // null date and current time, but only in current time.
367 if (fCell != 0.0)
368 nReqFmt = css::util::NumberFormat::DATETIME;
369 break;
370 case css::util::NumberFormat::DATETIME:
371 // Requesting current time on an empty date+time cell
372 // inserts both current date+time.
373 if (fCell == 0.0)
374 nReqFmt = css::util::NumberFormat::DATETIME;
375 else
377 // Add current time to an existing date+time where time is
378 // zero and date is current date, else force time only.
379 double fDate = rtl::math::approxFloor( fCell);
380 double fTime = fCell - fDate;
381 if (fTime == 0.0 && fDate == (Date( Date::SYSTEM) - *pFormatter->GetNullDate()))
382 nReqFmt = css::util::NumberFormat::DATETIME;
383 else
384 bForceReqFmt = true;
386 break;
388 break;
389 default:
390 assert(!"unhandled current date/time request");
391 nReqFmt = css::util::NumberFormat::DATETIME;
392 // fallthru
393 case css::util::NumberFormat::DATETIME:
394 break;
396 double fVal = 0.0;
397 switch (nReqFmt)
399 case css::util::NumberFormat::DATE:
401 Date aActDate( Date::SYSTEM );
402 fVal = aActDate - *pFormatter->GetNullDate();
404 break;
405 case css::util::NumberFormat::TIME:
407 tools::Time aActTime( tools::Time::SYSTEM );
408 fVal = aActTime.GetTimeInDays();
410 break;
411 case css::util::NumberFormat::DATETIME:
412 switch (nCurNumFormatType)
414 case css::util::NumberFormat::DATE:
416 double fDate = rtl::math::approxFloor( fCell);
417 tools::Time aActTime( tools::Time::SYSTEM );
418 fVal = fDate + aActTime.GetTimeInDays();
420 break;
421 case css::util::NumberFormat::TIME:
423 double fTime = fCell - rtl::math::approxFloor( fCell);
424 Date aActDate( Date::SYSTEM );
425 fVal = (aActDate - *pFormatter->GetNullDate()) + fTime;
427 break;
428 default:
430 DateTime aActDateTime( DateTime::SYSTEM );
431 // Converting the null date to DateTime forces the
432 // correct operator-() to be used, resulting in a
433 // fractional date+time instead of only date value.
434 fVal = aActDateTime - DateTime( *pFormatter->GetNullDate());
437 break;
440 ::svl::IUndoManager* pUndoMgr = pDocSh->GetUndoManager();
441 pUndoMgr->EnterListAction(rUndoStr, rUndoStr);
443 pDocSh->GetDocFunc().SetValueCell(aCurPos, fVal, true);
445 // Set the new cell format only when it differs from the current cell
446 // format type. Preserve a date+time format unless we force a format
447 // through.
448 if (bForceReqFmt || (nReqFmt != nCurNumFormatType && nCurNumFormatType != css::util::NumberFormat::DATETIME))
449 SetNumberFormat(nReqFmt);
450 else
451 rViewData.UpdateInputHandler(); // update input bar with new value
453 pUndoMgr->LeaveListAction();
457 void ScViewFunc::ShowNote( bool bShow )
459 if( bShow )
460 HideNoteMarker();
461 const ScViewData& rViewData = GetViewData();
462 ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
463 // show note moved to ScDocFunc, to be able to use it in notesuno.cxx
464 rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow );
467 void ScViewFunc::EditNote()
469 // for editing display and activate
471 ScDocShell* pDocSh = GetViewData().GetDocShell();
472 ScDocument& rDoc = pDocSh->GetDocument();
473 SCCOL nCol = GetViewData().GetCurX();
474 SCROW nRow = GetViewData().GetCurY();
475 SCTAB nTab = GetViewData().GetTabNo();
476 ScAddress aPos( nCol, nRow, nTab );
478 // start drawing undo to catch undo action for insertion of the caption object
479 pDocSh->MakeDrawLayer();
480 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
481 pDrawLayer->BeginCalcUndo(true);
482 // generated undo action is processed in FuText::StopEditMode
484 // get existing note or create a new note (including caption drawing object)
485 if( ScPostIt* pNote = rDoc.GetOrCreateNote( aPos ) )
487 // hide temporary note caption
488 HideNoteMarker();
489 // show caption object without changing internal visibility state
490 pNote->ShowCaptionTemp( aPos );
492 /* Drawing object has been created in ScDocument::GetOrCreateNote() or
493 in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
494 return a caption object. */
495 if( SdrCaptionObj* pCaption = pNote->GetCaption() )
497 if ( ScDrawView* pScDrawView = GetScDrawView() )
498 pScDrawView->SyncForGrid( pCaption );
499 // #i33764# enable the resize handles before starting edit mode
500 if( FuPoor* pDraw = GetDrawFuncPtr() )
501 static_cast< FuSelection* >( pDraw )->ActivateNoteHandles( pCaption );
503 // activate object (as in FuSelection::TestComment)
504 GetViewData().GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
505 // now get the created FuText and set into EditMode
506 FuPoor* pPoor = GetDrawFuncPtr();
507 if ( pPoor && (pPoor->GetSlotID() == SID_DRAW_NOTEEDIT) ) // has no RTTI
509 ScrollToObject( pCaption ); // make object fully visible
510 static_cast< FuText* >( pPoor )->SetInEditMode( pCaption );
516 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */