Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include <vcl/dialog.hxx>
23 : #include <vcl/layout.hxx>
24 : #include <vcl/wrkwin.hxx>
25 : #include <vcl/settings.hxx>
26 : #include <viewopt.hxx>
27 : #include <frmtool.hxx>
28 : #include <viscrs.hxx>
29 : #include <crsrsh.hxx>
30 : #include <doc.hxx>
31 : #include <swtable.hxx>
32 : #include <viewimp.hxx>
33 : #include <dview.hxx>
34 : #include <rootfrm.hxx>
35 : #include <txtfrm.hxx>
36 : #include <docary.hxx>
37 : #include <extinput.hxx>
38 : #include <ndtxt.hxx>
39 : #include <txtfld.hxx>
40 : #include <scriptinfo.hxx>
41 : #include <mdiexp.hxx>
42 : #include <wrtsh.hxx>
43 : #include <comcore.hrc>
44 : #include <view.hxx>
45 : #include <IDocumentLayoutAccess.hxx>
46 :
47 : #include <svx/sdr/overlay/overlaymanager.hxx>
48 : #include <svx/sdrpaintwindow.hxx>
49 : #include <svx/srchdlg.hxx>
50 : #include <vcl/svapp.hxx>
51 : #include <svx/sdr/overlay/overlayselection.hxx>
52 : #include <overlayrangesoutline.hxx>
53 :
54 : #include <boost/scoped_ptr.hpp>
55 :
56 : #include <LibreOfficeKit/LibreOfficeKitEnums.h>
57 : #include <paintfrm.hxx>
58 :
59 : // Here static members are defined. They will get changed on alteration of the
60 : // MapMode. This is done so that on ShowCrsr the same size does not have to be
61 : // expensively determined again and again.
62 :
63 : long SwSelPaintRects::s_nPixPtX = 0;
64 : long SwSelPaintRects::s_nPixPtY = 0;
65 : MapMode* SwSelPaintRects::s_pMapMode = 0;
66 :
67 : // Starting from here: classes / methods for the non-text-cursor
68 2761 : SwVisCrsr::SwVisCrsr( const SwCrsrShell * pCShell )
69 2761 : : m_pCrsrShell( pCShell )
70 : {
71 2761 : pCShell->GetWin()->SetCursor( &m_aTextCrsr );
72 2761 : m_bIsVisible = m_aTextCrsr.IsVisible();
73 2761 : m_bIsDragCrsr = false;
74 2761 : m_aTextCrsr.SetWidth( 0 );
75 2761 : }
76 :
77 5514 : SwVisCrsr::~SwVisCrsr()
78 : {
79 2757 : if( m_bIsVisible && m_aTextCrsr.IsVisible() )
80 7 : m_aTextCrsr.Hide();
81 :
82 2757 : m_pCrsrShell->GetWin()->SetCursor( 0 );
83 2757 : }
84 :
85 118239 : void SwVisCrsr::Show()
86 : {
87 118239 : if( !m_bIsVisible )
88 : {
89 56752 : m_bIsVisible = true;
90 :
91 : // display at all?
92 56752 : if( m_pCrsrShell->VisArea().IsOver( m_pCrsrShell->m_aCharRect ) || m_pCrsrShell->isTiledRendering() )
93 53456 : _SetPosAndShow();
94 : }
95 118239 : }
96 :
97 64418 : void SwVisCrsr::Hide()
98 : {
99 64418 : if( m_bIsVisible )
100 : {
101 56656 : m_bIsVisible = false;
102 :
103 56656 : if( m_aTextCrsr.IsVisible() ) // Shouldn't the flags be in effect?
104 53433 : m_aTextCrsr.Hide();
105 : }
106 64418 : }
107 :
108 53456 : void SwVisCrsr::_SetPosAndShow()
109 : {
110 53456 : SwRect aRect;
111 53456 : long nTmpY = m_pCrsrShell->m_aCrsrHeight.getY();
112 53456 : if( 0 > nTmpY )
113 : {
114 0 : nTmpY = -nTmpY;
115 0 : m_aTextCrsr.SetOrientation( 900 );
116 0 : aRect = SwRect( m_pCrsrShell->m_aCharRect.Pos(),
117 0 : Size( m_pCrsrShell->m_aCharRect.Height(), nTmpY ) );
118 0 : aRect.Pos().setX(aRect.Pos().getX() + m_pCrsrShell->m_aCrsrHeight.getX());
119 0 : if( m_pCrsrShell->IsOverwriteCrsr() )
120 0 : aRect.Pos().setY(aRect.Pos().getY() + aRect.Width());
121 : }
122 : else
123 : {
124 53456 : m_aTextCrsr.SetOrientation( 0 );
125 106912 : aRect = SwRect( m_pCrsrShell->m_aCharRect.Pos(),
126 53456 : Size( m_pCrsrShell->m_aCharRect.Width(), nTmpY ) );
127 53456 : aRect.Pos().setY(aRect.Pos().getY() + m_pCrsrShell->m_aCrsrHeight.getX());
128 : }
129 :
130 : // check if cursor should show the current cursor bidi level
131 53456 : m_aTextCrsr.SetDirection( CursorDirection::NONE );
132 53456 : const SwCursor* pTmpCrsr = m_pCrsrShell->_GetCrsr();
133 :
134 53456 : if ( pTmpCrsr && !m_pCrsrShell->IsOverwriteCrsr() )
135 : {
136 53456 : SwNode& rNode = pTmpCrsr->GetPoint()->nNode.GetNode();
137 53456 : if( rNode.IsTextNode() )
138 : {
139 53456 : const SwTextNode& rTNd = *rNode.GetTextNode();
140 53456 : const SwFrm* pFrm = rTNd.getLayoutFrm( m_pCrsrShell->GetLayout(), 0, 0, false );
141 53456 : if ( pFrm )
142 : {
143 53456 : const SwScriptInfo* pSI = static_cast<const SwTextFrm*>(pFrm)->GetScriptInfo();
144 : // cursor level has to be shown
145 53456 : if ( pSI && pSI->CountDirChg() > 1 )
146 : {
147 : m_aTextCrsr.SetDirection(
148 19 : ( pTmpCrsr->GetCrsrBidiLevel() % 2 ) ?
149 : CursorDirection::RTL :
150 19 : CursorDirection::LTR );
151 : }
152 53456 : if ( pFrm->IsRightToLeft() )
153 : {
154 138 : const OutputDevice *pOut = m_pCrsrShell->GetOut();
155 138 : if ( pOut )
156 : {
157 138 : long nSize = pOut->GetSettings().GetStyleSettings().GetCursorSize();
158 138 : Size aSize( nSize, nSize );
159 138 : aSize = pOut->PixelToLogic( aSize );
160 138 : aRect.Left( aRect.Left() - aSize.Width() );
161 : }
162 : }
163 : }
164 : }
165 : }
166 :
167 53456 : if( aRect.Height() )
168 : {
169 53378 : ::SwCalcPixStatics( m_pCrsrShell->GetOut() );
170 53378 : ::SwAlignRect( aRect, static_cast<SwViewShell const *>(m_pCrsrShell) );
171 : }
172 53456 : if( !m_pCrsrShell->IsOverwriteCrsr() || m_bIsDragCrsr ||
173 0 : m_pCrsrShell->IsSelection() )
174 53456 : aRect.Width( 0 );
175 :
176 53456 : m_aTextCrsr.SetSize( aRect.SSize() );
177 :
178 53456 : m_aTextCrsr.SetPos( aRect.Pos() );
179 :
180 53456 : if (m_pCrsrShell->isTiledRendering())
181 : {
182 65 : Rectangle aSVRect(aRect.Pos().getX(), aRect.Pos().getY(), aRect.Pos().getX() + aRect.SSize().Width(), aRect.Pos().getY() + aRect.SSize().Height());
183 65 : OString sRect = aSVRect.toString();
184 65 : m_pCrsrShell->libreOfficeKitCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, sRect.getStr());
185 : }
186 :
187 53456 : if ( !m_pCrsrShell->IsCrsrReadonly() || m_pCrsrShell->GetViewOptions()->IsSelectionInReadonly() )
188 : {
189 53441 : if ( m_pCrsrShell->GetDrawView() )
190 53441 : const_cast<SwDrawView*>(static_cast<const SwDrawView*>(m_pCrsrShell->GetDrawView()))->SetAnimationEnabled(
191 106882 : !m_pCrsrShell->IsSelection() );
192 :
193 53441 : sal_uInt16 nStyle = m_bIsDragCrsr ? CURSOR_SHADOW : 0;
194 53441 : if( nStyle != m_aTextCrsr.GetStyle() )
195 : {
196 0 : m_aTextCrsr.SetStyle( nStyle );
197 0 : m_aTextCrsr.SetWindow( m_bIsDragCrsr ? m_pCrsrShell->GetWin() : 0 );
198 : }
199 :
200 53441 : m_aTextCrsr.Show();
201 : }
202 53456 : }
203 :
204 4576 : SwSelPaintRects::SwSelPaintRects( const SwCrsrShell& rCSh )
205 : : SwRects()
206 : , m_pCursorShell( &rCSh )
207 : #if HAVE_FEATURE_DESKTOP
208 : , m_pCursorOverlay(nullptr)
209 : , m_bShowTextInputFieldOverlay(true)
210 4576 : , m_pTextInputFieldOverlay(nullptr)
211 : #endif
212 : {
213 4576 : }
214 :
215 9144 : SwSelPaintRects::~SwSelPaintRects()
216 : {
217 4572 : Hide();
218 4572 : }
219 :
220 0 : void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap)
221 : {
222 0 : SwRects::swap(rSwap);
223 :
224 : #if HAVE_FEATURE_DESKTOP
225 : // #i75172# also swap m_pCursorOverlay
226 0 : sdr::overlay::OverlayObject* pTempOverlay = getCursorOverlay();
227 0 : setCursorOverlay(rSwap.getCursorOverlay());
228 0 : rSwap.setCursorOverlay(pTempOverlay);
229 :
230 0 : const bool bTempShowTextInputFieldOverlay = m_bShowTextInputFieldOverlay;
231 0 : m_bShowTextInputFieldOverlay = rSwap.m_bShowTextInputFieldOverlay;
232 0 : rSwap.m_bShowTextInputFieldOverlay = bTempShowTextInputFieldOverlay;
233 :
234 0 : sw::overlay::OverlayRangesOutline* pTempTextInputFieldOverlay = m_pTextInputFieldOverlay;
235 0 : m_pTextInputFieldOverlay = rSwap.m_pTextInputFieldOverlay;
236 0 : rSwap.m_pTextInputFieldOverlay = pTempTextInputFieldOverlay;
237 : #endif
238 0 : }
239 :
240 11284 : void SwSelPaintRects::Hide()
241 : {
242 : #if HAVE_FEATURE_DESKTOP
243 11284 : if (m_pCursorOverlay)
244 : {
245 96 : delete m_pCursorOverlay;
246 96 : m_pCursorOverlay = nullptr;
247 : }
248 :
249 11284 : if (m_pTextInputFieldOverlay != nullptr)
250 : {
251 0 : delete m_pTextInputFieldOverlay;
252 0 : m_pTextInputFieldOverlay = nullptr;
253 : }
254 : #endif
255 :
256 11284 : SwRects::clear();
257 11284 : }
258 :
259 : /**
260 : * Return a layout rectangle (typically with minimal width) that represents a
261 : * cursor at rPosition.
262 : *
263 : * @param rPoint layout position as a hint about what layout frame contains
264 : * rPosition (there might be multiple frames for a single node)
265 : * @param rPosition the doc model position (paragraph / character index)
266 : */
267 62 : static SwRect lcl_getLayoutRect(const Point& rPoint, const SwPosition& rPosition)
268 : {
269 62 : const SwContentNode* pNode = rPosition.nNode.GetNode().GetContentNode();
270 62 : const SwContentFrm* pFrm = pNode->getLayoutFrm(pNode->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &rPoint, &rPosition);
271 62 : SwRect aRect;
272 62 : pFrm->GetCharRect(aRect, rPosition);
273 62 : return aRect;
274 : }
275 :
276 31 : void SwShellCrsr::FillStartEnd(SwRect& rStart, SwRect& rEnd) const
277 : {
278 31 : const SwShellCrsr* pCursor = GetShell()->getShellCrsr(false);
279 31 : rStart = lcl_getLayoutRect(pCursor->GetSttPos(), *pCursor->Start());
280 31 : rEnd = lcl_getLayoutRect(pCursor->GetEndPos(), *pCursor->End());
281 31 : }
282 :
283 91593 : void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles)
284 : {
285 91593 : SdrView *const pView = const_cast<SdrView*>(m_pCursorShell->GetDrawView());
286 :
287 91593 : if(pView && pView->PaintWindowCount())
288 : {
289 : // reset rects
290 91593 : SwRects::clear();
291 91593 : FillRects();
292 :
293 : #if HAVE_FEATURE_DESKTOP
294 : // get new rects
295 91593 : std::vector< basegfx::B2DRange > aNewRanges;
296 :
297 92148 : for(size_type a = 0; a < size(); ++a)
298 : {
299 555 : const SwRect aNextRect((*this)[a]);
300 555 : const Rectangle aPntRect(aNextRect.SVRect());
301 :
302 : aNewRanges.push_back(basegfx::B2DRange(
303 1110 : aPntRect.Left(), aPntRect.Top(),
304 1665 : aPntRect.Right() + 1, aPntRect.Bottom() + 1));
305 : }
306 :
307 91593 : if (m_pCursorOverlay)
308 : {
309 286 : if(!aNewRanges.empty())
310 : {
311 266 : static_cast<sdr::overlay::OverlaySelection*>(m_pCursorOverlay)->setRanges(aNewRanges);
312 : }
313 : else
314 : {
315 20 : delete m_pCursorOverlay;
316 20 : m_pCursorOverlay = nullptr;
317 : }
318 : }
319 91307 : else if(!empty())
320 : {
321 116 : SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
322 116 : rtl::Reference< sdr::overlay::OverlayManager > xTargetOverlay = pCandidate->GetOverlayManager();
323 :
324 116 : if (xTargetOverlay.is())
325 : {
326 : // get the system's highlight color
327 116 : const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
328 116 : const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
329 :
330 : // create correct selection
331 : m_pCursorOverlay = new sdr::overlay::OverlaySelection(
332 : sdr::overlay::OVERLAY_TRANSPARENT,
333 : aHighlight,
334 : aNewRanges,
335 116 : true);
336 :
337 116 : xTargetOverlay->add(*m_pCursorOverlay);
338 116 : }
339 : }
340 :
341 91593 : HighlightInputField();
342 : #endif
343 :
344 : // Tiled editing does not expose the draw and writer cursor, it just
345 : // talks about "the" cursor at the moment. As long as that's true,
346 : // don't say anything about the Writer cursor till a draw object is
347 : // being edited.
348 91593 : if (GetShell()->isTiledRendering() && !pView->GetTextEditObject())
349 : {
350 151 : if (!empty())
351 : {
352 : // The selection may be a complex polygon, emit the logical
353 : // start/end cursor rectangle of the selection as separate
354 : // events, if there is a real selection.
355 : // This can be used to easily show selection handles on the
356 : // client side.
357 31 : SwRect aStartRect;
358 31 : SwRect aEndRect;
359 31 : FillStartEnd(aStartRect, aEndRect);
360 :
361 31 : if (aStartRect.HasArea())
362 : {
363 31 : OString sRect = aStartRect.SVRect().toString();
364 31 : GetShell()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_START, sRect.getStr());
365 : }
366 31 : if (aEndRect.HasArea())
367 : {
368 31 : OString sRect = aEndRect.SVRect().toString();
369 31 : GetShell()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_END, sRect.getStr());
370 : }
371 : }
372 :
373 151 : std::stringstream ss;
374 182 : for (size_type i = 0; i < size(); ++i)
375 : {
376 31 : const SwRect& rRect = (*this)[i];
377 31 : if (i)
378 0 : ss << "; ";
379 31 : ss << rRect.SVRect().toString().getStr();
380 : }
381 302 : OString sRect = ss.str().c_str();
382 151 : if (!pSelectionRectangles)
383 81 : GetShell()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr());
384 : else
385 221 : pSelectionRectangles->push_back(sRect);
386 91593 : }
387 : }
388 91593 : }
389 :
390 91593 : void SwSelPaintRects::HighlightInputField()
391 : {
392 91593 : std::vector< basegfx::B2DRange > aInputFieldRanges;
393 :
394 91593 : if (m_bShowTextInputFieldOverlay)
395 : {
396 : SwTextInputField* pCurTextInputFieldAtCrsr =
397 90226 : dynamic_cast<SwTextInputField*>(SwCrsrShell::GetTextFieldAtPos( GetShell()->GetCrsr()->Start(), false ));
398 90226 : if ( pCurTextInputFieldAtCrsr != NULL )
399 : {
400 0 : SwTextNode* pTextNode = pCurTextInputFieldAtCrsr->GetpTextNode();
401 : ::boost::scoped_ptr<SwShellCrsr> pCrsrForInputTextField(
402 0 : new SwShellCrsr( *GetShell(), SwPosition( *pTextNode, pCurTextInputFieldAtCrsr->GetStart() ) ) );
403 0 : pCrsrForInputTextField->SetMark();
404 0 : pCrsrForInputTextField->GetMark()->nNode = *pTextNode;
405 0 : pCrsrForInputTextField->GetMark()->nContent.Assign( pTextNode, *(pCurTextInputFieldAtCrsr->End()) );
406 :
407 0 : pCrsrForInputTextField->FillRects();
408 0 : SwRects* pRects = static_cast<SwRects*>(pCrsrForInputTextField.get());
409 0 : for (size_t a(0); a < pRects->size(); ++a)
410 : {
411 0 : const SwRect aNextRect((*pRects)[a]);
412 0 : const Rectangle aPntRect(aNextRect.SVRect());
413 :
414 : aInputFieldRanges.push_back(basegfx::B2DRange(
415 0 : aPntRect.Left(), aPntRect.Top(),
416 0 : aPntRect.Right() + 1, aPntRect.Bottom() + 1));
417 0 : }
418 : }
419 : }
420 :
421 91593 : if ( aInputFieldRanges.size() > 0 )
422 : {
423 0 : if (m_pTextInputFieldOverlay != nullptr)
424 : {
425 0 : m_pTextInputFieldOverlay->setRanges( aInputFieldRanges );
426 : }
427 : else
428 : {
429 0 : SdrView* pView = const_cast<SdrView*>(GetShell()->GetDrawView());
430 0 : SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
431 0 : rtl::Reference<sdr::overlay::OverlayManager> xTargetOverlay = pCandidate->GetOverlayManager();
432 :
433 0 : if (xTargetOverlay.is())
434 : {
435 : // use system's highlight color with decreased luminance as highlight color
436 0 : const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
437 0 : Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor());
438 0 : aHighlight.DecreaseLuminance( 128 );
439 :
440 : m_pTextInputFieldOverlay = new sw::overlay::OverlayRangesOutline(
441 0 : aHighlight, aInputFieldRanges );
442 0 : xTargetOverlay->add( *m_pTextInputFieldOverlay );
443 0 : }
444 : }
445 : }
446 : else
447 : {
448 91593 : if (m_pTextInputFieldOverlay != nullptr)
449 : {
450 0 : delete m_pTextInputFieldOverlay;
451 0 : m_pTextInputFieldOverlay = nullptr;
452 : }
453 91593 : }
454 91593 : }
455 :
456 6019 : void SwSelPaintRects::Invalidate( const SwRect& rRect )
457 : {
458 6019 : size_type nSz = size();
459 6019 : if( !nSz )
460 12022 : return;
461 :
462 16 : SwRegionRects aReg( GetShell()->VisArea() );
463 16 : aReg.assign( begin(), end() );
464 16 : aReg -= rRect;
465 16 : SwRects::erase( begin(), begin() + nSz );
466 16 : SwRects::insert( begin(), aReg.begin(), aReg.end() );
467 :
468 : // If the selection is to the right or at the bottom, outside the
469 : // visible area, it is never aligned on one pixel at the right/bottom.
470 : // This has to be determined here and if that is the case the
471 : // rectangle has to be expanded.
472 16 : if( GetShell()->m_bVisPortChgd && 0 != ( nSz = size()) )
473 : {
474 0 : SwSelPaintRects::Get1PixelInLogic( *GetShell() );
475 0 : iterator it = begin();
476 0 : for( ; nSz--; ++it )
477 : {
478 0 : SwRect& rRectIt = *it;
479 0 : if( rRectIt.Right() == GetShell()->m_aOldRBPos.X() )
480 0 : rRectIt.Right( rRectIt.Right() + s_nPixPtX );
481 0 : if( rRectIt.Bottom() == GetShell()->m_aOldRBPos.Y() )
482 0 : rRectIt.Bottom( rRectIt.Bottom() + s_nPixPtY );
483 : }
484 16 : }
485 : }
486 :
487 : // check current MapMode of the shell and set possibly the static members.
488 : // Optional set the parameters pX, pY
489 7 : void SwSelPaintRects::Get1PixelInLogic( const SwViewShell& rSh,
490 : long* pX, long* pY )
491 : {
492 7 : const OutputDevice* pOut = rSh.GetWin();
493 7 : if ( ! pOut )
494 0 : pOut = rSh.GetOut();
495 :
496 7 : const MapMode& rMM = pOut->GetMapMode();
497 19 : if (s_pMapMode->GetMapUnit() != rMM.GetMapUnit() ||
498 12 : s_pMapMode->GetScaleX() != rMM.GetScaleX() ||
499 5 : s_pMapMode->GetScaleY() != rMM.GetScaleY())
500 : {
501 2 : *s_pMapMode = rMM;
502 2 : Size aTmp( 1, 1 );
503 2 : aTmp = pOut->PixelToLogic( aTmp );
504 2 : s_nPixPtX = aTmp.Width();
505 2 : s_nPixPtY = aTmp.Height();
506 : }
507 7 : if( pX )
508 7 : *pX = s_nPixPtX;
509 7 : if( pY )
510 7 : *pY = s_nPixPtY;
511 7 : }
512 :
513 3378 : SwShellCrsr::SwShellCrsr(
514 : const SwCrsrShell& rCShell,
515 : const SwPosition &rPos )
516 : : SwCursor(rPos,0,false)
517 : , SwSelPaintRects(rCShell)
518 3378 : , m_pInitialPoint(SwPaM::GetPoint())
519 3378 : {}
520 :
521 1198 : SwShellCrsr::SwShellCrsr(
522 : const SwCrsrShell& rCShell,
523 : const SwPosition &rPos,
524 : const Point& rPtPos,
525 : SwPaM* pRing )
526 : : SwCursor(rPos, pRing, false)
527 : , SwSelPaintRects(rCShell)
528 : , m_MarkPt(rPtPos)
529 : , m_PointPt(rPtPos)
530 1198 : , m_pInitialPoint(SwPaM::GetPoint())
531 1198 : {}
532 :
533 0 : SwShellCrsr::SwShellCrsr( SwShellCrsr& rICrsr )
534 : : SwCursor(rICrsr, &rICrsr)
535 0 : , SwSelPaintRects(*rICrsr.GetShell())
536 0 : , m_MarkPt(rICrsr.GetMkPos())
537 0 : , m_PointPt(rICrsr.GetPtPos())
538 0 : , m_pInitialPoint(SwPaM::GetPoint())
539 0 : {}
540 :
541 13692 : SwShellCrsr::~SwShellCrsr()
542 13692 : {}
543 :
544 472 : bool SwShellCrsr::IsReadOnlyAvailable() const
545 : {
546 472 : return GetShell()->IsReadOnlyAvailable();
547 : }
548 :
549 914 : void SwShellCrsr::SetMark()
550 : {
551 914 : if (SwPaM::GetPoint() == m_pInitialPoint)
552 854 : m_MarkPt = m_PointPt;
553 : else
554 60 : m_PointPt = m_MarkPt;
555 914 : SwPaM::SetMark();
556 914 : }
557 :
558 92170 : void SwShellCrsr::FillRects()
559 : {
560 : // calculate the new rectangles
561 185321 : if( HasMark() &&
562 1962 : GetPoint()->nNode.GetNode().IsContentNode() &&
563 95113 : GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrm( GetShell()->GetLayout() ) &&
564 1140 : (GetMark()->nNode == GetPoint()->nNode ||
565 318 : (GetMark()->nNode.GetNode().IsContentNode() &&
566 159 : GetMark()->nNode.GetNode().GetContentNode()->getLayoutFrm( GetShell()->GetLayout() ) ) ))
567 981 : GetShell()->GetLayout()->CalcFrmRects( *this );
568 92170 : }
569 :
570 50719 : void SwShellCrsr::Show()
571 : {
572 50719 : std::vector<OString> aSelectionRectangles;
573 101445 : for(SwPaM& rPaM : GetRingContainer())
574 : {
575 50726 : SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rPaM);
576 50726 : if(pShCrsr)
577 50726 : pShCrsr->SwSelPaintRects::Show(&aSelectionRectangles);
578 : }
579 :
580 50719 : if (GetShell()->isTiledRendering())
581 : {
582 67 : std::stringstream ss;
583 67 : bool bFirst = true;
584 137 : for (size_t i = 0; i < aSelectionRectangles.size(); ++i)
585 : {
586 70 : const OString& rSelectionRectangle = aSelectionRectangles[i];
587 70 : if (rSelectionRectangle.isEmpty())
588 55 : continue;
589 15 : if (bFirst)
590 15 : bFirst = false;
591 : else
592 0 : ss << "; ";
593 15 : ss << rSelectionRectangle.getStr();
594 : }
595 134 : OString sRect = ss.str().c_str();
596 134 : GetShell()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr());
597 50719 : }
598 50719 : }
599 :
600 : // This rectangle gets painted anew, therefore the SSelection in this
601 : // area is invalid.
602 6015 : void SwShellCrsr::Invalidate( const SwRect& rRect )
603 : {
604 12034 : for(SwPaM& rPaM : GetRingContainer())
605 : {
606 6019 : SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rPaM);
607 : // skip any non SwShellCrsr objects in the ring
608 : // see also: SwAutoFormat::DeleteSel()
609 6019 : if(pShCrsr)
610 6019 : pShCrsr->SwSelPaintRects::Invalidate(rRect);
611 : }
612 6015 : }
613 :
614 6696 : void SwShellCrsr::Hide()
615 : {
616 13396 : for(SwPaM& rPaM : GetRingContainer())
617 : {
618 6700 : SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rPaM);
619 6700 : if(pShCrsr)
620 6700 : pShCrsr->SwSelPaintRects::Hide();
621 : }
622 6696 : }
623 :
624 33 : SwCursor* SwShellCrsr::Create( SwPaM* pRing ) const
625 : {
626 33 : return new SwShellCrsr( *GetShell(), *GetPoint(), GetPtPos(), pRing );
627 : }
628 :
629 0 : short SwShellCrsr::MaxReplaceArived()
630 : {
631 0 : short nRet = RET_YES;
632 0 : vcl::Window* pDlg = SwView::GetSearchDialog();
633 0 : if( pDlg )
634 : {
635 : // Terminate old actions. The table-frames get constructed and
636 : // a SSelection can be created.
637 0 : std::vector<sal_uInt16> vActionCounts;
638 0 : for(SwViewShell& rShell : const_cast< SwCrsrShell* >( GetShell() )->GetRingContainer())
639 : {
640 0 : sal_uInt16 nActCnt = 0;
641 0 : while(rShell.ActionPend())
642 : {
643 0 : rShell.EndAction();
644 0 : ++nActCnt;
645 : }
646 0 : vActionCounts.push_back(nActCnt);
647 : }
648 : nRet = ScopedVclPtrInstance<MessageDialog>::Create(pDlg, "AskSearchDialog",
649 0 : "modules/swriter/ui/asksearchdialog.ui")->Execute();
650 0 : auto pActionCount = vActionCounts.begin();
651 0 : for(SwViewShell& rShell : const_cast< SwCrsrShell* >( GetShell() )->GetRingContainer())
652 : {
653 0 : while(*pActionCount)
654 : {
655 0 : rShell.StartAction();
656 0 : --(*pActionCount);
657 : }
658 0 : ++pActionCount;
659 0 : }
660 : }
661 : else
662 : // otherwise from the Basic, and than switch to RET_YES
663 0 : nRet = RET_YES;
664 :
665 0 : return nRet;
666 : }
667 :
668 0 : void SwShellCrsr::SaveTableBoxContent( const SwPosition* pPos )
669 : {
670 0 : const_cast<SwCrsrShell*>(GetShell())->SaveTableBoxContent( pPos );
671 0 : }
672 :
673 6 : bool SwShellCrsr::UpDown( bool bUp, sal_uInt16 nCnt )
674 : {
675 : return SwCursor::UpDown( bUp, nCnt,
676 6 : &GetPtPos(), GetShell()->GetUpDownX() );
677 : }
678 :
679 : // if <true> than the cursor can be set to the position.
680 46 : bool SwShellCrsr::IsAtValidPos( bool bPoint ) const
681 : {
682 96 : if( GetShell() && ( GetShell()->IsAllProtect() ||
683 92 : GetShell()->GetViewOptions()->IsReadonly() ||
684 92 : ( GetShell()->Imp()->GetDrawView() &&
685 46 : GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )))
686 4 : return true;
687 :
688 42 : return SwCursor::IsAtValidPos( bPoint );
689 : }
690 :
691 9 : SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
692 : const SwPosition& rPos )
693 9 : : SwCursor(rPos,0,false), SwShellCrsr(rCrsrSh, rPos), SwTableCursor(rPos)
694 : {
695 9 : }
696 :
697 3 : SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
698 : const SwPosition& rMkPos, const Point& rMkPt,
699 : const SwPosition& rPtPos, const Point& rPtPt )
700 3 : : SwCursor(rPtPos,0,false), SwShellCrsr(rCrsrSh, rPtPos), SwTableCursor(rPtPos)
701 : {
702 3 : SetMark();
703 3 : *GetMark() = rMkPos;
704 3 : GetMkPos() = rMkPt;
705 3 : GetPtPos() = rPtPt;
706 3 : }
707 :
708 24 : SwShellTableCrsr::~SwShellTableCrsr() {}
709 :
710 12 : void SwShellTableCrsr::SetMark() { SwShellCrsr::SetMark(); }
711 :
712 0 : SwCursor* SwShellTableCrsr::Create( SwPaM* pRing ) const
713 : {
714 0 : return SwShellCrsr::Create( pRing );
715 : }
716 :
717 0 : short SwShellTableCrsr::MaxReplaceArived()
718 : {
719 0 : return SwShellCrsr::MaxReplaceArived();
720 : }
721 :
722 0 : void SwShellTableCrsr::SaveTableBoxContent( const SwPosition* pPos )
723 : {
724 0 : SwShellCrsr::SaveTableBoxContent( pPos );
725 0 : }
726 :
727 28 : void SwShellTableCrsr::FillRects()
728 : {
729 : // Calculate the new rectangles. If the cursor is still "parked" do nothing
730 28 : if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex())
731 29 : return;
732 :
733 27 : bool bStart = true;
734 27 : SwRegionRects aReg( GetShell()->VisArea() );
735 27 : if (GetShell()->isTiledRendering())
736 0 : aReg = GetShell()->getIDocumentLayoutAccess()->GetCurrentLayout()->Frm();
737 27 : SwNodes& rNds = GetDoc()->GetNodes();
738 27 : SwFrm* pEndFrm = 0;
739 102 : for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
740 : {
741 75 : const SwStartNode* pSttNd = m_SelectedBoxes[n]->GetSttNd();
742 75 : const SwTableNode* pSelTableNd = pSttNd->FindTableNode();
743 :
744 75 : SwNodeIndex aIdx( *pSttNd );
745 75 : SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false );
746 :
747 : // table in table
748 : // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different
749 : // version to do this)
750 75 : const SwTableNode* pCurTableNd = pCNd ? pCNd->FindTableNode() : NULL;
751 150 : while ( pSelTableNd != pCurTableNd && pCurTableNd )
752 : {
753 0 : aIdx = pCurTableNd->EndOfSectionIndex();
754 0 : pCNd = rNds.GoNextSection( &aIdx, true, false );
755 0 : pCurTableNd = pCNd->FindTableNode();
756 : }
757 :
758 75 : if( !pCNd )
759 0 : continue;
760 :
761 75 : SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetSttPos() );
762 225 : while( pFrm && !pFrm->IsCellFrm() )
763 75 : pFrm = pFrm->GetUpper();
764 :
765 : OSL_ENSURE( pFrm, "Node not in a table" );
766 :
767 225 : while ( pFrm )
768 : {
769 75 : if( aReg.GetOrigin().IsOver( pFrm->Frm() ) )
770 : {
771 74 : aReg -= pFrm->Frm();
772 74 : if (bStart)
773 : {
774 27 : bStart = false;
775 27 : m_aStart = SwRect(pFrm->Frm().Left(), pFrm->Frm().Top(), 1, pFrm->Frm().Height());
776 : }
777 : }
778 :
779 75 : pEndFrm = pFrm;
780 75 : pFrm = pFrm->GetNextCellLeaf( MAKEPAGE_NONE );
781 : }
782 75 : }
783 27 : if (pEndFrm)
784 27 : m_aEnd = SwRect(pEndFrm->Frm().Right(), pEndFrm->Frm().Top(), 1, pEndFrm->Frm().Height());
785 27 : aReg.Invert();
786 27 : insert( begin(), aReg.begin(), aReg.end() );
787 : }
788 :
789 0 : void SwShellTableCrsr::FillStartEnd(SwRect& rStart, SwRect& rEnd) const
790 : {
791 0 : rStart = m_aStart;
792 0 : rEnd = m_aEnd;
793 0 : }
794 :
795 : // Check if the SPoint is within the Table-SSelection.
796 0 : bool SwShellTableCrsr::IsInside( const Point& rPt ) const
797 : {
798 : // Calculate the new rectangles. If the cursor is still "parked" do nothing
799 0 : if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex())
800 0 : return false;
801 :
802 0 : SwNodes& rNds = GetDoc()->GetNodes();
803 0 : for (size_t n = 0; n < m_SelectedBoxes.size(); ++n)
804 : {
805 0 : SwNodeIndex aIdx( *m_SelectedBoxes[n]->GetSttNd() );
806 0 : SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false );
807 0 : if( !pCNd )
808 0 : continue;
809 :
810 0 : SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetPtPos() );
811 0 : while( pFrm && !pFrm->IsCellFrm() )
812 0 : pFrm = pFrm->GetUpper();
813 : OSL_ENSURE( pFrm, "Node not in a table" );
814 0 : if( pFrm && pFrm->Frm().IsInside( rPt ) )
815 0 : return true;
816 0 : }
817 0 : return false;
818 : }
819 :
820 8 : bool SwShellTableCrsr::IsAtValidPos( bool bPoint ) const
821 : {
822 8 : return SwShellCrsr::IsAtValidPos( bPoint );
823 177 : }
824 :
825 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|