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 <futext.hxx> 21 #include <editeng/eeitem.hxx> 22 #include <svx/sdrpagewindow.hxx> 23 #include <svx/sdrpaintwindow.hxx> 24 #include <tools/urlobj.hxx> 25 #include <vcl/help.hxx> 26 #include <editeng/fhgtitem.hxx> 27 #include <svl/intitem.hxx> 28 #include <svl/stritem.hxx> 29 #include <svx/svdotext.hxx> 30 #include <editeng/flditem.hxx> 31 #include <svl/style.hxx> 32 #include <svx/svdpagv.hxx> 33 #include <svx/sdtmfitm.hxx> 34 #include <svx/sdtagitm.hxx> 35 #include <svx/sdtfsitm.hxx> 36 #include <sfx2/viewfrm.hxx> 37 #include <sfx2/dispatch.hxx> 38 #include <sfx2/bindings.hxx> 39 #include <sfx2/request.hxx> 40 #include <editeng/editeng.hxx> 41 #include <svx/svdoutl.hxx> 42 #include <svx/svxids.hrc> 43 #include <svx/sdr/overlay/overlaymanager.hxx> 44 #include <sfx2/docfile.hxx> 45 #include <editeng/outlobj.hxx> 46 #include <osl/diagnose.h> 47 48 #include <editeng/frmdiritem.hxx> 49 50 #include <svx/svdetc.hxx> 51 #include <editeng/editview.hxx> 52 53 #include <sdresid.hxx> 54 #include <app.hrc> 55 56 #include <ViewShell.hxx> 57 #include <ViewShellBase.hxx> 58 #include <View.hxx> 59 #include <Window.hxx> 60 #include <drawdoc.hxx> 61 #include <sdpage.hxx> 62 #include <FrameView.hxx> 63 #include <ToolBarManager.hxx> 64 #include <DrawDocShell.hxx> 65 #include <strings.hrc> 66 #include <pres.hxx> 67 68 using namespace ::com::sun::star; 69 using namespace ::com::sun::star::uno; 70 using namespace ::com::sun::star::lang; 71 using namespace ::com::sun::star::linguistic2; 72 73 namespace sd { 74 75 const sal_uInt16 SidArray[] = { 76 SID_STYLE_FAMILY2, // 5542 77 SID_STYLE_FAMILY5, // 5545 78 SID_REDO, // 5700 79 SID_UNDO, // 5701 80 SID_CUT, // 5710 81 SID_COPY, // 5711 82 SID_ATTR_TABSTOP, // 10002 83 SID_ATTR_CHAR_FONT, // 10007 84 SID_ATTR_CHAR_POSTURE, // 10008 85 SID_ATTR_CHAR_WEIGHT, // 10009 86 SID_ATTR_CHAR_SHADOWED, // 10010 87 SID_ATTR_CHAR_STRIKEOUT, // 10013 88 SID_ATTR_CHAR_UNDERLINE, // 10014 89 SID_ATTR_CHAR_FONTHEIGHT, // 10015 90 SID_ATTR_CHAR_COLOR, // 10017 91 SID_ATTR_CHAR_KERNING, // 10018 92 SID_ATTR_CHAR_CASEMAP, // 10019 93 SID_ATTR_PARA_ADJUST_LEFT, // 10028 94 SID_ATTR_PARA_ADJUST_RIGHT, // 10029 95 SID_ATTR_PARA_ADJUST_CENTER, // 10030 96 SID_ATTR_PARA_ADJUST_BLOCK, // 10031 97 SID_ATTR_PARA_LINESPACE_10, // 10034 98 SID_ATTR_PARA_LINESPACE_15, // 10035 99 SID_ATTR_PARA_LINESPACE_20, // 10036 100 SID_ATTR_PARA_ULSPACE, // 10042 101 SID_ATTR_PARA_LRSPACE, // 10043 102 SID_ATTR_TRANSFORM_POS_X, // 10088 103 SID_ATTR_TRANSFORM_POS_Y, // 10089 104 SID_ATTR_TRANSFORM_WIDTH, // 10090 105 SID_ATTR_TRANSFORM_HEIGHT, // 10091 106 SID_ATTR_TRANSFORM_ROT_X, // 10093 107 SID_ATTR_TRANSFORM_ROT_Y, // 10094 108 SID_ATTR_TRANSFORM_ANGLE, // 10095 //Added 109 SID_OUTLINE_UP, // 10150 110 SID_OUTLINE_DOWN, // 10151 111 SID_OUTLINE_LEFT, // 10152 112 SID_OUTLINE_RIGHT, // 10153 113 SID_ATTR_TRANSFORM_PROTECT_POS, // 10236 114 SID_ATTR_TRANSFORM_PROTECT_SIZE, // 10237 //Added 115 SID_FORMTEXT_STYLE, // 10257 116 SID_SET_SUPER_SCRIPT, // 10294 117 SID_SET_SUB_SCRIPT, // 10295 118 SID_ATTR_TRANSFORM_AUTOWIDTH, // 10310 119 SID_ATTR_TRANSFORM_AUTOHEIGHT, // 10311 //Added 120 SID_HYPERLINK_GETLINK, // 10361 121 SID_DEC_INDENT, // 10461 122 SID_INC_INDENT, // 10462 123 SID_CHARMAP, // 10503 124 SID_TEXTDIRECTION_LEFT_TO_RIGHT, // 10907 125 SID_TEXTDIRECTION_TOP_TO_BOTTOM, // 10908 126 SID_ATTR_PARA_LEFT_TO_RIGHT, // 10950 127 SID_ATTR_PARA_RIGHT_TO_LEFT, // 10951 128 SID_PARASPACE_INCREASE, // 11145 129 SID_PARASPACE_DECREASE, // 11146 130 FN_NUM_BULLET_ON, // 20138 131 0 }; 132 133 134 /** 135 * base class for text functions 136 */ 137 FuText::FuText( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) 138 : FuConstruct(pViewSh, pWin, pView, pDoc, rReq) 139 , bFirstObjCreated(false) 140 , bJustEndedEdit(false) 141 , rRequest (rReq) 142 { 143 } 144 145 rtl::Reference<FuPoor> FuText::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) 146 { 147 rtl::Reference<FuPoor> xFunc( new FuText( pViewSh, pWin, pView, pDoc, rReq ) ); 148 return xFunc; 149 } 150 151 void FuText::disposing() 152 { 153 if(mpView) 154 { 155 if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) 156 mxTextObj.reset(nullptr); 157 158 // reset the RequestHandler of the used Outliner to the handler of the document 159 ::Outliner* pOutliner = mpView->GetTextEditOutliner(); 160 161 if (pOutliner) 162 pOutliner->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mpDoc->GetStyleSheetPool())); 163 } 164 } 165 166 /************************************************************************* 167 |* 168 |* Execute functionality of this class: 169 |* 170 |* #71422: Start the functionality of this class in this method 171 |* and not in the ctor. 172 |* If you construct an object of this class and you put the 173 |* address of this object to pFuActual you've got a problem, 174 |* because some methods inside DoExecute use the pFuActual-Pointer. 175 |* If the code inside DoExecute is executed inside the ctor, 176 |* the value of pFuActual is not right. And the value will not 177 |* be right until the ctor finished !!! 178 |* 179 \************************************************************************/ 180 void FuText::DoExecute( SfxRequest& ) 181 { 182 mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBarShell( 183 ToolBarManager::ToolBarGroup::Function, 184 ToolbarId::Draw_Text_Toolbox_Sd); 185 186 mpView->SetCurrentObj(OBJ_TEXT); 187 mpView->SetEditMode(SdrViewEditMode::Edit); 188 189 MouseEvent aMEvt(mpWindow->GetPointerPosPixel()); 190 191 if (nSlotId == SID_TEXTEDIT) 192 { 193 // Try to select an object 194 SdrPageView* pPV = mpView->GetSdrPageView(); 195 SdrViewEvent aVEvt; 196 mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 197 mpView->MarkObj(aVEvt.pRootObj, pPV); 198 199 mxTextObj.reset( dynamic_cast< SdrTextObj* >( aVEvt.pObj ) ); 200 } 201 else if (mpView->AreObjectsMarked()) 202 { 203 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 204 205 if (rMarkList.GetMarkCount() == 1) 206 { 207 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 208 mxTextObj.reset( dynamic_cast< SdrTextObj* >( pObj ) ); 209 } 210 } 211 212 // check for table 213 if (mpView->AreObjectsMarked()) 214 { 215 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 216 217 if (rMarkList.GetMarkCount() == 1) 218 { 219 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 220 if( pObj && (pObj->GetObjInventor() == SdrInventor::Default ) && (pObj->GetObjIdentifier() == OBJ_TABLE) ) 221 { 222 mpViewShell->GetViewShellBase().GetToolBarManager()->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Table_Toolbox); 223 } 224 } 225 } 226 227 bool bQuickDrag = true; 228 229 const SfxItemSet* pArgs = rRequest.GetArgs(); 230 231 if (pArgs 232 233 // test for type before using 234 && SID_TEXTEDIT == nSlotId 235 && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT) 236 237 && static_cast<const SfxUInt16Item&>(pArgs->Get(SID_TEXTEDIT)).GetValue() == 2) 238 { 239 // Selection by doubleclick -> don't allow QuickDrag 240 bQuickDrag = false; 241 } 242 243 SetInEditMode(aMEvt, bQuickDrag); 244 } 245 246 bool FuText::MouseButtonDown(const MouseEvent& rMEvt) 247 { 248 bMBDown = true; 249 bJustEndedEdit = false; 250 251 bool bReturn = FuDraw::MouseButtonDown(rMEvt); 252 253 SdrViewEvent aVEvt; 254 SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 255 256 // handle URL also during the text editing 257 if (rMEvt.GetClicks() == 1 && rMEvt.IsLeft() && rMEvt.IsMod1()) 258 { 259 OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); 260 261 if (mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer()) 262 { 263 const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer(); 264 if (pFieldItem) 265 { 266 const SvxFieldData* pField = pFieldItem->GetField(); 267 268 if (auto pURLField = dynamic_cast< const SvxURLField *>( pField )) 269 { 270 eHit = SdrHitKind::MarkedObject; 271 aVEvt.eEvent = SdrEventKind::ExecuteUrl; 272 aVEvt.pURLField = pURLField; 273 } 274 } 275 } 276 } 277 278 if (eHit == SdrHitKind::TextEdit) 279 { 280 // hit text -> SdrView handles event 281 if (mpView->MouseButtonDown(rMEvt, mpWindow->GetOutDev())) 282 return true; 283 } 284 285 if (rMEvt.GetClicks() == 1) 286 { 287 if (mpView->IsTextEdit() && eHit != SdrHitKind::MarkedObject && eHit != SdrHitKind::Handle) 288 { 289 // finish text input 290 if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) 291 { 292 /* Bugfix from MBA: during a double click onto the unused? area 293 in text mode, we get with the second click eHit = 294 SdrHitKind::TextEditObj since it goes to the TextObject which was 295 created with the first click. But this is removed by 296 SdrEndTextEdit since it is empty. But it is still in the mark 297 list. The call MarkObj further below accesses then the dead 298 object. As a simple fix, we determine eHit after 299 SdrEndTextEdit again, this returns then SdrHitKind::NONE. */ 300 mxTextObj.reset(nullptr); 301 eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 302 } 303 304 mpView->SetCurrentObj(OBJ_TEXT); 305 mpView->SetEditMode(SdrViewEditMode::Edit); 306 } 307 308 if (rMEvt.IsLeft() || rMEvt.IsRight()) 309 { 310 mpWindow->CaptureMouse(); 311 SdrPageView* pPV = mpView->GetSdrPageView(); 312 313 if (eHit == SdrHitKind::TextEdit) 314 { 315 SetInEditMode(rMEvt, false); 316 } 317 else 318 { 319 // Don't remark table when clicking in it, mark change triggers a lot of updating 320 bool bMarkChanges = true; 321 rtl::Reference< sdr::SelectionController > xSelectionController(mpView->getSelectionController()); 322 if (eHit == SdrHitKind::TextEditObj && xSelectionController.is()) 323 { 324 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 325 if (rMarkList.GetMarkCount() == 1 && rMarkList.GetMark(0)->GetMarkedSdrObj() == aVEvt.pRootObj) 326 bMarkChanges = false; 327 } 328 329 if (eHit != SdrHitKind::Handle) 330 { 331 // deselect selection 332 if (!rMEvt.IsShift() && eHit == SdrHitKind::TextEditObj) 333 { 334 if(bMarkChanges) 335 { 336 mpView->UnmarkAll(); 337 mpView->SetDragMode(SdrDragMode::Move); 338 } 339 } 340 } 341 342 if ( aVEvt.eEvent == SdrEventKind::ExecuteUrl || 343 eHit == SdrHitKind::Handle || 344 eHit == SdrHitKind::MarkedObject || 345 eHit == SdrHitKind::TextEditObj || 346 ( eHit == SdrHitKind::UnmarkedObject && bFirstObjCreated && 347 !bPermanent ) ) 348 { 349 // Handle, hit marked or unmarked object 350 if (eHit == SdrHitKind::TextEditObj) 351 { 352 /* hit text of unmarked object: 353 select object and set to EditMode */ 354 if (bMarkChanges) 355 mpView->MarkObj(aVEvt.pRootObj, pPV); 356 357 if (auto pSdrTextObj = dynamic_cast<SdrTextObj *>( aVEvt.pObj )) 358 { 359 mxTextObj.reset( pSdrTextObj ); 360 } 361 362 SetInEditMode(rMEvt, true); 363 } 364 else if (aVEvt.eEvent == SdrEventKind::ExecuteUrl && !rMEvt.IsMod2()) 365 { 366 // execute URL 367 mpWindow->ReleaseMouse(); 368 SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.pURLField->GetURL()); 369 SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); 370 SfxBoolItem aBrowseItem( SID_BROWSE, true ); 371 SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); 372 mpWindow->ReleaseMouse(); 373 374 if (rMEvt.IsMod1()) 375 { 376 // open in new frame 377 pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, 378 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, 379 { &aStrItem, &aBrowseItem, &aReferer }); 380 } 381 else 382 { 383 // open in current frame 384 SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); 385 pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC, 386 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, 387 { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer }); 388 } 389 } 390 else 391 { 392 // drag object or handle 393 394 // #i78748# 395 // do the EndTextEdit first, it will delete the handles and force a 396 // recreation. This will make aVEvt.pHdl to point to a deleted handle, 397 // thus it is necessary to reset it and to get it again. 398 399 // #i112855# 400 // cl: I'm not sure why we checked here also for mxTextObj->GetOutlinerParaObject 401 // this caused SdrEndTextEdit() to be called also when not in text editing and 402 // this does not make sense and caused troubles. (see issue 112855) 403 404 if( mpView->IsTextEdit() ) 405 { 406 mpView->SdrEndTextEdit(); 407 bJustEndedEdit = true; 408 409 if(aVEvt.pHdl) 410 { 411 // force new handle identification, the pointer will be dead here 412 // since SdrEndTextEdit has reset (deleted) the handles. 413 aVEvt.pHdl = nullptr; 414 mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 415 } 416 } 417 418 if (!aVEvt.pHdl) 419 { 420 if( eHit == SdrHitKind::UnmarkedObject ) 421 { 422 if ( !rMEvt.IsShift() ) 423 mpView->UnmarkAll(); 424 425 mpView->MarkObj(aVEvt.pRootObj, pPV); 426 } 427 428 // Drag object 429 bFirstMouseMove = true; 430 aDragTimer.Start(); 431 } 432 433 if ( ! rMEvt.IsRight()) 434 { 435 // we need to pick again since SdrEndTextEdit can rebuild the handles list 436 eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 437 if( (eHit == SdrHitKind::Handle) || (eHit == SdrHitKind::MarkedObject) ) 438 { 439 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 440 mpView->BegDragObj(aMDPos, nullptr, aVEvt.pHdl, nDrgLog); 441 } 442 } 443 bReturn = true; 444 } 445 } 446 else if ( nSlotId != SID_TEXTEDIT && 447 (bPermanent || !bFirstObjCreated) ) 448 { 449 // create object 450 mpView->SetCurrentObj(OBJ_TEXT); 451 mpView->SetEditMode(SdrViewEditMode::Create); 452 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 453 mpView->BegCreateObj(aMDPos, nullptr, nDrgLog); 454 } 455 else 456 { 457 // select 458 if( !rMEvt.IsShift() ) 459 mpView->UnmarkAll(); 460 461 mpView->BegMarkObj( aMDPos ); 462 } 463 } 464 } 465 } 466 else if ( rMEvt.GetClicks() == 2 && !mpView->IsTextEdit() ) 467 { 468 MouseEvent aMEvt( mpWindow->GetPointerPosPixel() ); 469 SetInEditMode( aMEvt, false ); 470 } 471 472 if (!bIsInDragMode) 473 { 474 ForcePointer(&rMEvt); 475 mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray); 476 } 477 478 return bReturn; 479 } 480 481 bool FuText::MouseMove(const MouseEvent& rMEvt) 482 { 483 bool bReturn = FuDraw::MouseMove(rMEvt); 484 485 if (aDragTimer.IsActive() ) 486 { 487 if( bFirstMouseMove ) 488 bFirstMouseMove = false; 489 else 490 aDragTimer.Stop(); 491 } 492 493 if (!bReturn && mpView->IsAction() && !mpDocSh->IsReadOnly()) 494 { 495 Point aPix(rMEvt.GetPosPixel()); 496 Point aPnt(mpWindow->PixelToLogic(aPix)); 497 498 ForceScroll(aPix); 499 mpView->MovAction(aPnt); 500 } 501 502 ForcePointer(&rMEvt); 503 504 return bReturn; 505 } 506 507 void FuText::ImpSetAttributesForNewTextObject(SdrTextObj* pTxtObj) 508 { 509 if(mpDoc->GetDocumentType() == DocumentType::Impress) 510 { 511 if( nSlotId == SID_ATTR_CHAR ) 512 { 513 /* Create Impress text object (rescales to line height) 514 We get the correct height during the subsequent creation of the 515 object, otherwise we draw too much */ 516 SfxItemSet aSet(mpViewShell->GetPool()); 517 aSet.Put(makeSdrTextMinFrameHeightItem(0)); 518 aSet.Put(makeSdrTextAutoGrowWidthItem(false)); 519 aSet.Put(makeSdrTextAutoGrowHeightItem(true)); 520 pTxtObj->SetMergedItemSet(aSet); 521 pTxtObj->AdjustTextFrameWidthAndHeight(); 522 aSet.Put(makeSdrTextMaxFrameHeightItem(pTxtObj->GetLogicRect().GetSize().Height())); 523 pTxtObj->SetMergedItemSet(aSet); 524 const SfxViewShell* pCurrentViewShell = SfxViewShell::Current(); 525 if (pCurrentViewShell && (pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet())) 526 pTxtObj->SetText(SdResId(STR_PRESOBJ_TEXT_EDIT_MOBILE)); 527 } 528 else if( nSlotId == SID_ATTR_CHAR_VERTICAL ) 529 { 530 SfxItemSet aSet(mpViewShell->GetPool()); 531 aSet.Put(makeSdrTextMinFrameWidthItem(0)); 532 aSet.Put(makeSdrTextAutoGrowWidthItem(true)); 533 aSet.Put(makeSdrTextAutoGrowHeightItem(false)); 534 535 // Needs to be set since default is SDRTEXTHORZADJUST_BLOCK 536 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); 537 pTxtObj->SetMergedItemSet(aSet); 538 pTxtObj->AdjustTextFrameWidthAndHeight(); 539 aSet.Put(makeSdrTextMaxFrameWidthItem(pTxtObj->GetLogicRect().GetSize().Width())); 540 pTxtObj->SetMergedItemSet(aSet); 541 } 542 } 543 else 544 { 545 if( nSlotId == SID_ATTR_CHAR_VERTICAL ) 546 { 547 // draw text object, needs to be initialized when vertical text is used 548 SfxItemSet aSet(mpViewShell->GetPool()); 549 550 aSet.Put(makeSdrTextAutoGrowWidthItem(true)); 551 aSet.Put(makeSdrTextAutoGrowHeightItem(false)); 552 553 // Set defaults for vertical click-n'drag text object, pool defaults are: 554 // SdrTextVertAdjustItem: SDRTEXTVERTADJUST_TOP 555 // SdrTextHorzAdjustItem: SDRTEXTHORZADJUST_BLOCK 556 // Analog to that: 557 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); 558 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); 559 560 pTxtObj->SetMergedItemSet(aSet); 561 } 562 } 563 } 564 565 void FuText::ImpSetAttributesFitToSize(SdrTextObj* pTxtObj) 566 { 567 // FitToSize (fit to frame) 568 SfxItemSet aSet(mpViewShell->GetPool(), svl::Items<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>{}); 569 aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL)); 570 aSet.Put(makeSdrTextAutoGrowHeightItem(false)); 571 aSet.Put(makeSdrTextAutoGrowWidthItem(false)); 572 pTxtObj->SetMergedItemSet(aSet); 573 pTxtObj->AdjustTextFrameWidthAndHeight(); 574 } 575 576 void FuText::ImpSetAttributesFitToSizeVertical(SdrTextObj* pTxtObj) 577 { 578 SfxItemSet aSet(mpViewShell->GetPool(), 579 svl::Items<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>{}); 580 aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL)); 581 aSet.Put(makeSdrTextAutoGrowHeightItem(false)); 582 aSet.Put(makeSdrTextAutoGrowWidthItem(false)); 583 pTxtObj->SetMergedItemSet(aSet); 584 pTxtObj->AdjustTextFrameWidthAndHeight(); 585 } 586 587 void FuText::ImpSetAttributesFitCommon(SdrTextObj* pTxtObj) 588 { 589 // Normal Textobject 590 if (mpDoc->GetDocumentType() != DocumentType::Impress) 591 return; 592 593 if( nSlotId == SID_ATTR_CHAR ) 594 { 595 // Impress text object (rescales to line height) 596 SfxItemSet aSet(mpViewShell->GetPool()); 597 aSet.Put(makeSdrTextMinFrameHeightItem(0)); 598 aSet.Put(makeSdrTextMaxFrameHeightItem(0)); 599 aSet.Put(makeSdrTextAutoGrowHeightItem(true)); 600 aSet.Put(makeSdrTextAutoGrowWidthItem(false)); 601 pTxtObj->SetMergedItemSet(aSet); 602 } 603 else if( nSlotId == SID_ATTR_CHAR_VERTICAL ) 604 { 605 SfxItemSet aSet(mpViewShell->GetPool()); 606 aSet.Put(makeSdrTextMinFrameWidthItem(0)); 607 aSet.Put(makeSdrTextMaxFrameWidthItem(0)); 608 aSet.Put(makeSdrTextAutoGrowWidthItem(true)); 609 aSet.Put(makeSdrTextAutoGrowHeightItem(false)); 610 pTxtObj->SetMergedItemSet(aSet); 611 } 612 613 pTxtObj->AdjustTextFrameWidthAndHeight(); 614 } 615 616 bool FuText::MouseButtonUp(const MouseEvent& rMEvt) 617 { 618 bool bReturn = false; 619 if (aDragTimer.IsActive()) 620 { 621 aDragTimer.Stop(); 622 bIsInDragMode = false; 623 } 624 625 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); 626 627 Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); 628 629 if( (mpView && mpView->MouseButtonUp(rMEvt, mpWindow->GetOutDev())) || rMEvt.GetClicks() == 2 ) 630 return true; // handle event from SdrView 631 632 bool bEmptyTextObj = false; 633 634 if (mxTextObj.is()) 635 { 636 bool bReset = true; 637 638 if (mpView) 639 { 640 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 641 642 if (rMarkList.GetMarkCount() == 1 643 && ( rMarkList.GetMark(0)->GetMarkedSdrObj() == mxTextObj.get()) ) 644 { 645 if( mxTextObj.is() && !GetTextObj()->GetOutlinerParaObject() ) 646 bEmptyTextObj = true; 647 else 648 bFirstObjCreated = true; 649 bReset = false; 650 } 651 } 652 653 if (bReset) 654 { 655 mxTextObj.reset(nullptr); 656 } 657 } 658 659 if( mpView && mpView->IsDragObj()) 660 { 661 // object was moved 662 FrameView* pFrameView = mpViewShell->GetFrameView(); 663 bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); 664 665 if (bDragWithCopy) 666 { 667 bDragWithCopy = !mpView->IsPresObjSelected(false); 668 } 669 670 mpView->SetDragWithCopy(bDragWithCopy); 671 mpView->EndDragObj( mpView->IsDragWithCopy() ); 672 mpView->ForceMarkedToAnotherPage(); 673 mpView->SetCurrentObj(OBJ_TEXT); 674 675 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 676 677 if (bJustEndedEdit) 678 { 679 bJustEndedEdit = false; 680 FuPoor::cancel(); 681 } 682 if ((rMEvt.GetClicks() != 2) && 683 !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsRight() && 684 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && 685 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) 686 { 687 /************************************************************* 688 * From text mode, you don't want to rotate immediately. 689 **************************************************************/ 690 SdrPageView* pPV; 691 SdrObject* pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK); 692 if (pObj && pPV->IsObjMarkable(pObj)) 693 { 694 mpView->UnmarkAllObj(); 695 mpView->MarkObj(pObj,pPV); 696 return bReturn; 697 } 698 } 699 } 700 else if( mpView && mpView->IsCreateObj() && rMEvt.IsLeft()) 701 { 702 // object was created 703 mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) ); 704 705 if( mxTextObj.is() ) 706 { 707 //AW outliner needs to be set to vertical when there is no 708 // outliner object up to now; also it needs to be set back to not 709 // vertical when there was a vertical one used last time. 710 OutlinerParaObject* pOPO = GetTextObj()->GetOutlinerParaObject(); 711 SdrOutliner& rOutl(mxTextObj->getSdrModelFromSdrObject().GetDrawOutliner(GetTextObj())); 712 bool bVertical((pOPO && pOPO->IsVertical()) 713 || nSlotId == SID_ATTR_CHAR_VERTICAL 714 || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL); 715 rOutl.SetVertical(bVertical); 716 717 // Before ImpSetAttributesForNewTextObject the vertical writing mode 718 // needs to be set at the object. This is done here at the OutlinerParaObject 719 // directly to not mirror the layout text items involved. These items will be set 720 // from ImpSetAttributesForNewTextObject and below. 721 OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject(); 722 723 if(!pPara) 724 { 725 GetTextObj()->ForceOutlinerParaObject(); 726 pPara = GetTextObj()->GetOutlinerParaObject(); 727 } 728 729 if(pPara && bVertical != pPara->IsVertical()) 730 { 731 // set ParaObject orientation accordingly 732 pPara->SetVertical(bVertical); 733 } 734 735 ImpSetAttributesForNewTextObject(GetTextObj()); 736 } 737 738 if (!mpView->EndCreateObj(SdrCreateCmd::ForceEnd)) 739 { 740 // it was not possible to create text object 741 mxTextObj.reset(nullptr); 742 } 743 else if (nSlotId == SID_TEXT_FITTOSIZE) 744 { 745 ImpSetAttributesFitToSize(GetTextObj()); 746 747 SetInEditMode(rMEvt, false); 748 } 749 else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL ) 750 { 751 ImpSetAttributesFitToSizeVertical(GetTextObj()); 752 753 SetInEditMode(rMEvt, false); 754 } 755 else 756 { 757 ImpSetAttributesFitCommon(GetTextObj()); 758 759 // thereby the handles and the gray frame are correct 760 mpView->AdjustMarkHdl(); 761 mpView->PickHandle(aPnt); 762 SetInEditMode(rMEvt, false); 763 } 764 } 765 else if ( mpView && mpView->IsAction()) 766 { 767 mpView->EndAction(); 768 } 769 770 ForcePointer(&rMEvt); 771 mpWindow->ReleaseMouse(); 772 sal_uInt16 nDrgLog1 = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 773 774 if ( mpView && !mpView->AreObjectsMarked() && 775 std::abs(aMDPos.X() - aPnt.X()) < nDrgLog1 && 776 std::abs(aMDPos.Y() - aPnt.Y()) < nDrgLog1 && 777 !rMEvt.IsShift() && !rMEvt.IsMod2() ) 778 { 779 SdrPageView* pPV2 = mpView->GetSdrPageView(); 780 SdrViewEvent aVEvt; 781 mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 782 mpView->MarkObj(aVEvt.pRootObj, pPV2); 783 } 784 785 if ( !mxTextObj.is() && mpView ) 786 { 787 if ( ( (!bEmptyTextObj && bPermanent) || 788 (!bFirstObjCreated && !bPermanent) ) && 789 !mpDocSh->IsReadOnly() && 790 nSlotId != SID_TEXTEDIT ) 791 { 792 // text body (left-justified AutoGrow) 793 mpView->SetCurrentObj(OBJ_TEXT); 794 mpView->SetEditMode(SdrViewEditMode::Create); 795 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 796 mpView->BegCreateObj(aMDPos, nullptr, nDrgLog); 797 798 bool bSnapEnabled = mpView->IsSnapEnabled(); 799 800 if (bSnapEnabled) 801 mpView->SetSnapEnabled(false); 802 803 aPnt.AdjustX(nDrgLog + nDrgLog ); 804 aPnt.AdjustY(nDrgLog + nDrgLog ); 805 mpView->MovAction(aPnt); 806 807 mxTextObj.reset( dynamic_cast< SdrTextObj* >( mpView->GetCreateObj() ) ); 808 809 if(mxTextObj.is()) 810 { 811 GetTextObj()->SetDisableAutoWidthOnDragging(true); 812 } 813 814 if(!mpView->EndCreateObj(SdrCreateCmd::ForceEnd)) 815 { 816 mxTextObj.reset(nullptr); 817 } 818 819 if(bSnapEnabled) 820 mpView->SetSnapEnabled(bSnapEnabled); 821 822 if(mxTextObj.is()) 823 { 824 SfxItemSet aSet(mpViewShell->GetPool()); 825 aSet.Put(makeSdrTextMinFrameHeightItem(0)); 826 aSet.Put(makeSdrTextMinFrameWidthItem(0)); 827 aSet.Put(makeSdrTextAutoGrowHeightItem(true)); 828 aSet.Put(makeSdrTextAutoGrowWidthItem(true)); 829 830 if(nSlotId == SID_ATTR_CHAR_VERTICAL) 831 { 832 // Here, all items which need to be different from pool default need to be set 833 // again on the newly created text object. 834 // Since this is a simple click text object, it is first created, then SetVertical() 835 // is used, then ImpSetAttributesForNewTextObject is called and then the object is 836 // deleted again since not the minimum drag distance was travelled. Then, a new 837 // click text object is created and thus all that stuff needs to be set again here. 838 839 // Before using the new object the vertical writing mode 840 // needs to be set. This is done here at the OutlinerParaObject 841 // directly to not mirror the layout text items involved. These items will be set 842 // below. 843 OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject(); 844 845 if(!pPara) 846 { 847 GetTextObj()->ForceOutlinerParaObject(); 848 pPara = GetTextObj()->GetOutlinerParaObject(); 849 } 850 851 if(pPara && !pPara->IsVertical()) 852 { 853 // set ParaObject orientation accordingly 854 pPara->SetVertical(true); 855 } 856 857 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); 858 859 // Analog to the else case below, for vertical simple click texts 860 // one of the default set items from ImpSetAttributesForNewTextObject 861 // needs to be adapted to non-block mode. 862 const SfxItemSet& rSet = mpView->GetDefaultAttr(); 863 SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue(); 864 865 if(SvxFrameDirection::Horizontal_RL_TB == eDirection || SvxFrameDirection::Vertical_RL_TB == eDirection) 866 { 867 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); 868 } 869 else 870 { 871 aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); 872 } 873 } 874 else 875 { 876 // This is for Format/Page settings. Since this also leads 877 // to the object defaults to be changed, i think this code can be 878 // removed. CL. wanted to take a look before adding this. 879 880 // Look in the object defaults if left-to-right is wanted. If 881 // yes, set text anchoring to right to let the box grow to left. 882 const SfxItemSet& rSet = mpView->GetDefaultAttr(); 883 SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue(); 884 885 if(SvxFrameDirection::Horizontal_RL_TB == eDirection) 886 { 887 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); 888 } 889 else 890 { 891 aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); 892 } 893 } 894 895 GetTextObj()->SetMergedItemSet(aSet); 896 GetTextObj()->SetDisableAutoWidthOnDragging(true); 897 SetInEditMode(rMEvt, false); 898 } 899 900 bFirstObjCreated = true; 901 } 902 else 903 { 904 // switch to selection 905 if (mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) 906 { 907 mxTextObj.reset(nullptr); 908 } 909 910 mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT, 911 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); 912 } 913 } 914 if (bJustEndedEdit) 915 { 916 bJustEndedEdit = false; 917 FuPoor::cancel(); 918 } 919 bMBDown = false; 920 FuConstruct::MouseButtonUp(rMEvt); 921 return bReturn; 922 } 923 924 /** 925 * handle keyboard events 926 * @returns sal_True if the event was handled, sal_False otherwise 927 */ 928 bool FuText::KeyInput(const KeyEvent& rKEvt) 929 { 930 bool bReturn = false; 931 932 vcl::KeyCode nCode = rKEvt.GetKeyCode(); 933 bool bShift = nCode.IsShift(); 934 935 if(mxTextObj.is()) 936 { 937 // maybe object is deleted, test if it's equal to the selected object 938 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 939 SdrObject* pSelectedObj = nullptr; 940 941 if(1 == rMarkList.GetMarkCount()) 942 { 943 SdrMark* pMark = rMarkList.GetMark(0); 944 pSelectedObj = pMark->GetMarkedSdrObj(); 945 } 946 947 if(mxTextObj.get() != pSelectedObj) 948 { 949 mxTextObj.reset(nullptr); 950 } 951 } 952 953 if ( mxTextObj.is() && mxTextObj->GetObjInventor() == SdrInventor::Default && mxTextObj->GetObjIdentifier() == OBJ_TITLETEXT && rKEvt.GetKeyCode().GetCode() == KEY_RETURN ) 954 { 955 // title text object: always soft breaks 956 bShift = true; 957 } 958 959 sal_uInt16 nKey = nCode.GetCode(); 960 vcl::KeyCode aKeyCode (nKey, bShift, nCode.IsMod1(), nCode.IsMod2(), nCode.IsMod3() ); 961 KeyEvent aKEvt(rKEvt.GetCharCode(), aKeyCode); 962 963 bool bOK = true; 964 965 if (mpDocSh->IsReadOnly()) 966 { 967 bOK = !EditEngine::DoesKeyChangeText(aKEvt); 968 } 969 if( aKeyCode.GetCode() == KEY_PAGEUP || aKeyCode.GetCode() == KEY_PAGEDOWN ) 970 { 971 bOK = false; // default handling in base class 972 } 973 974 if (bOK && mpView->KeyInput(aKEvt, mpWindow) ) 975 { 976 bReturn = true; 977 978 mpViewShell->GetViewFrame()->GetBindings().Invalidate( SidArray ); 979 980 } 981 else if (aKeyCode == KEY_ESCAPE) 982 { 983 bReturn = cancel(); 984 } 985 986 if( bPermanent ) 987 { 988 mpView->SetCurrentObj(OBJ_TEXT); 989 mpView->SetEditMode(SdrViewEditMode::Create); 990 } 991 992 if (!bReturn) 993 { 994 bReturn = FuDraw::KeyInput(aKEvt); 995 } 996 997 return bReturn; 998 } 999 1000 void FuText::Activate() 1001 { 1002 mpView->SetQuickTextEditMode(mpViewShell->GetFrameView()->IsQuickEdit()); 1003 1004 // #i89661# it's no longer necessary to make it so big here, it's fine tuned 1005 // for text objects in SdrMarkView::CheckSingleSdrObjectHit 1006 mpView->SetHitTolerancePixel( 2 * HITPIX ); 1007 1008 OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); 1009 1010 if (pOLV) 1011 pOLV->ShowCursor(/*bGotoCursor=*/true, /*bActivate=*/true); 1012 1013 FuConstruct::Activate(); 1014 1015 if( pOLV ) 1016 mpView->SetEditMode(SdrViewEditMode::Edit); 1017 } 1018 1019 void FuText::Deactivate() 1020 { 1021 OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); 1022 1023 if (pOLV) 1024 pOLV->HideCursor(/*bDeactivate=*/true); 1025 1026 mpView->SetHitTolerancePixel( HITPIX ); 1027 1028 FuConstruct::Deactivate(); 1029 } 1030 1031 /** 1032 * Sets the object into the edit mode. 1033 */ 1034 void FuText::SetInEditMode(const MouseEvent& rMEvt, bool bQuickDrag) 1035 { 1036 SdrPageView* pPV = mpView->GetSdrPageView(); 1037 if( mxTextObj.is() && (mxTextObj->getSdrPageFromSdrObject() == pPV->GetPage()) ) 1038 { 1039 mpView->SetCurrentObj(OBJ_TEXT); 1040 1041 if( bPermanent ) 1042 mpView->SetEditMode(SdrViewEditMode::Create); 1043 else 1044 mpView->SetEditMode(SdrViewEditMode::Edit); 1045 1046 bool bEmptyOutliner = false; 1047 1048 if (!GetTextObj()->GetOutlinerParaObject() && mpView->GetTextEditOutliner()) 1049 { 1050 ::Outliner* pOutl = mpView->GetTextEditOutliner(); 1051 sal_Int32 nParagraphCnt = pOutl->GetParagraphCount(); 1052 Paragraph* p1stPara = pOutl->GetParagraph( 0 ); 1053 1054 if (nParagraphCnt==1 && p1stPara) 1055 { 1056 // with only one paragraph 1057 if (pOutl->GetText(p1stPara).isEmpty()) 1058 { 1059 bEmptyOutliner = true; 1060 } 1061 } 1062 } 1063 1064 if (GetTextObj() != mpView->GetTextEditObject() || bEmptyOutliner) 1065 { 1066 SdrInventor nInv = mxTextObj->GetObjInventor(); 1067 sal_uInt16 nSdrObjKind = mxTextObj->GetObjIdentifier(); 1068 1069 if (nInv == SdrInventor::Default && GetTextObj()->HasTextEdit() && 1070 (nSdrObjKind == OBJ_TEXT || 1071 nSdrObjKind == OBJ_TITLETEXT || 1072 nSdrObjKind == OBJ_OUTLINETEXT || !mxTextObj->IsEmptyPresObj() ) ) 1073 { 1074 // create new outliner (owned by SdrObjEditView) 1075 std::unique_ptr<SdrOutliner> pOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, *mpDoc); 1076 1077 if (bEmptyOutliner) 1078 mpView->SdrEndTextEdit(true); 1079 1080 SdrTextObj* pTextObj = GetTextObj(); 1081 if( pTextObj ) 1082 { 1083 OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject(); 1084 if( pOPO && pOPO->IsVertical() ) 1085 { 1086 pOutl->SetVertical(pOPO->GetDirectVertical()); 1087 pOutl->SetRotation(pOPO->GetRotation()); 1088 } 1089 else if (nSlotId == SID_ATTR_CHAR_VERTICAL || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL) 1090 pOutl->SetVertical( true ); 1091 1092 if( pTextObj->getTextCount() > 1 ) 1093 { 1094 Point aPix(rMEvt.GetPosPixel()); 1095 Point aPnt(mpWindow->PixelToLogic(aPix)); 1096 pTextObj->setActiveText( pTextObj->CheckTextHit(aPnt ) ); 1097 } 1098 1099 if (mpView->SdrBeginTextEdit(pTextObj, pPV, mpWindow, true, pOutl.release()) && mxTextObj->GetObjInventor() == SdrInventor::Default) 1100 { 1101 //tdf#102293 flush overlay before going on to pass clicks down to 1102 //the outline view which will want to paint selections 1103 for (sal_uInt32 b = 0; b < pPV->PageWindowCount(); ++b) 1104 { 1105 const SdrPageWindow& rPageWindow = *pPV->GetPageWindow(b); 1106 if (!rPageWindow.GetPaintWindow().OutputToWindow()) 1107 continue; 1108 const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager(); 1109 if (!xManager.is()) 1110 continue; 1111 xManager->flush(); 1112 } 1113 1114 bFirstObjCreated = true; 1115 DeleteDefaultText(); 1116 1117 OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); 1118 1119 nSdrObjKind = mxTextObj->GetObjIdentifier(); 1120 1121 SdrViewEvent aVEvt; 1122 SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 1123 1124 if (eHit == SdrHitKind::TextEdit) 1125 { 1126 // hit text 1127 if (nSdrObjKind == OBJ_TEXT || 1128 nSdrObjKind == OBJ_TITLETEXT || 1129 nSdrObjKind == OBJ_OUTLINETEXT || 1130 nSdrObjKind == OBJ_TABLE || 1131 nSlotId == SID_TEXTEDIT || 1132 !bQuickDrag) 1133 { 1134 pOLV->MouseButtonDown(rMEvt); 1135 pOLV->MouseMove(rMEvt); 1136 pOLV->MouseButtonUp(rMEvt); 1137 } 1138 1139 if (mpViewShell->GetFrameView()->IsQuickEdit() && bQuickDrag && GetTextObj()->GetOutlinerParaObject()) 1140 { 1141 pOLV->MouseButtonDown(rMEvt); 1142 } 1143 } 1144 else 1145 { 1146 // Move cursor to end of text 1147 ESelection aNewSelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND); 1148 if (pOLV != nullptr) 1149 pOLV->SetSelection(aNewSelection); 1150 } 1151 } 1152 else 1153 { 1154 mpView->RestoreDefaultText( mxTextObj.get() ); 1155 } 1156 } 1157 } 1158 } 1159 } 1160 else 1161 { 1162 mxTextObj.reset(nullptr); 1163 } 1164 } 1165 1166 /** 1167 * Text entry is started, if necessary delete the default text. 1168 */ 1169 void FuText::DeleteDefaultText() 1170 { 1171 if ( !(mxTextObj.is() && mxTextObj->IsEmptyPresObj()) ) 1172 return; 1173 1174 SdPage* pPage = static_cast<SdPage*>( mxTextObj->getSdrPageFromSdrObject() ); 1175 1176 if (!pPage) 1177 return; 1178 1179 PresObjKind ePresObjKind = pPage->GetPresObjKind(mxTextObj.get()); 1180 1181 if ( !(ePresObjKind == PresObjKind::Title || 1182 ePresObjKind == PresObjKind::Outline || 1183 ePresObjKind == PresObjKind::Notes || 1184 ePresObjKind == PresObjKind::Text ) || 1185 pPage->IsMasterPage() ) 1186 return; 1187 1188 ::Outliner* pOutliner = mpView->GetTextEditOutliner(); 1189 SfxStyleSheet* pSheet = pOutliner->GetStyleSheet( 0 ); 1190 bool bIsUndoEnabled = pOutliner->IsUndoEnabled(); 1191 if( bIsUndoEnabled ) 1192 pOutliner->EnableUndo(false); 1193 1194 pOutliner->SetText( OUString(), pOutliner->GetParagraph( 0 ) ); 1195 1196 if( bIsUndoEnabled ) 1197 pOutliner->EnableUndo(true); 1198 1199 if (pSheet && 1200 (ePresObjKind == PresObjKind::Notes || ePresObjKind == PresObjKind::Text)) 1201 pOutliner->SetStyleSheet(0, pSheet); 1202 1203 mxTextObj->SetEmptyPresObj(true); 1204 } 1205 1206 bool FuText::RequestHelp(const HelpEvent& rHEvt) 1207 { 1208 bool bReturn = false; 1209 1210 OutlinerView* pOLV = mpView->GetTextEditOutlinerView(); 1211 1212 if ((Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) && 1213 mxTextObj.is() && pOLV && pOLV->GetFieldUnderMousePointer()) 1214 { 1215 OUString aHelpText; 1216 const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer(); 1217 const SvxFieldData* pField = pFieldItem->GetField(); 1218 1219 if (auto pURLField = dynamic_cast< const SvxURLField *>( pField )) 1220 { 1221 // URL-Field 1222 aHelpText = INetURLObject::decode( pURLField->GetURL(), INetURLObject::DecodeMechanism::WithCharset ); 1223 } 1224 if (!aHelpText.isEmpty()) 1225 { 1226 ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(mxTextObj->GetLogicRect()); 1227 ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()), 1228 mpWindow->OutputToScreenPixel(aLogicPix.BottomRight())); 1229 1230 if (Help::IsBalloonHelpEnabled()) 1231 { 1232 Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rHEvt.GetMousePosPixel(), aScreenRect, aHelpText); 1233 bReturn = true; 1234 } 1235 else if (Help::IsQuickHelpEnabled()) 1236 { 1237 Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText); 1238 bReturn = true; 1239 } 1240 } 1241 } 1242 1243 if (!bReturn) 1244 { 1245 bReturn = FuConstruct::RequestHelp(rHEvt); 1246 } 1247 1248 return bReturn; 1249 } 1250 1251 void FuText::ReceiveRequest(SfxRequest& rReq) 1252 { 1253 nSlotId = rReq.GetSlot(); 1254 1255 // then we call the base class (besides others, nSlotId is NOT set there) 1256 FuPoor::ReceiveRequest(rReq); 1257 1258 if (!(nSlotId == SID_TEXTEDIT || mpViewShell->GetFrameView()->IsQuickEdit() || SID_ATTR_CHAR == nSlotId)) 1259 return; 1260 1261 MouseEvent aMEvt(mpWindow->GetPointerPosPixel()); 1262 1263 mxTextObj.reset(nullptr); 1264 1265 if (nSlotId == SID_TEXTEDIT) 1266 { 1267 // are we currently editing? 1268 mxTextObj.reset( mpView->GetTextEditObject() ); 1269 1270 if (!mxTextObj.is()) 1271 { 1272 // Try to select an object 1273 SdrPageView* pPV = mpView->GetSdrPageView(); 1274 SdrViewEvent aVEvt; 1275 mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); 1276 mpView->MarkObj(aVEvt.pRootObj, pPV); 1277 1278 if (auto pSdrTextObj = dynamic_cast< SdrTextObj *>( aVEvt.pObj )) 1279 { 1280 mxTextObj.reset( pSdrTextObj ); 1281 } 1282 } 1283 } 1284 else if (mpView->AreObjectsMarked()) 1285 { 1286 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList(); 1287 1288 if (rMarkList.GetMarkCount() == 1) 1289 { 1290 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 1291 1292 if( auto pTextObj = dynamic_cast<SdrTextObj *>( pObj )) 1293 { 1294 mxTextObj.reset( pTextObj ); 1295 } 1296 } 1297 } 1298 1299 bool bQuickDrag = true; 1300 1301 const SfxItemSet* pArgs = rReq.GetArgs(); 1302 1303 if (pArgs 1304 1305 // test for type before using 1306 && SID_TEXTEDIT == nSlotId 1307 && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT) 1308 1309 && static_cast<const SfxUInt16Item&>( pArgs->Get(SID_TEXTEDIT)).GetValue() == 2) 1310 { 1311 // selection with double click -> do not allow QuickDrag 1312 bQuickDrag = false; 1313 } 1314 1315 SetInEditMode(aMEvt, bQuickDrag); 1316 } 1317 1318 void FuText::DoubleClick(const MouseEvent& ) 1319 { 1320 // Nothing to do 1321 } 1322 1323 /** Removed the insertion of default text and putting a new text 1324 object directly into edit mode. 1325 */ 1326 SdrObjectUniquePtr FuText::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle) 1327 { 1328 SdrObjectUniquePtr pObj( SdrObjFactory::MakeNewObject( 1329 mpView->getSdrModelFromSdrView(), 1330 mpView->GetCurrentObjInventor(), 1331 mpView->GetCurrentObjIdentifier(), 1332 nullptr) ); 1333 1334 if(pObj) 1335 { 1336 if( auto pText = dynamic_cast< SdrTextObj *>( pObj.get() ) ) 1337 { 1338 pText->SetLogicRect(rRectangle); 1339 1340 bool bVertical = (SID_ATTR_CHAR_VERTICAL == nID || SID_TEXT_FITTOSIZE_VERTICAL == nID); 1341 pText->SetVerticalWriting(bVertical); 1342 1343 ImpSetAttributesForNewTextObject(pText); 1344 1345 if (nSlotId == SID_TEXT_FITTOSIZE) 1346 { 1347 ImpSetAttributesFitToSize(pText); 1348 } 1349 else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL ) 1350 { 1351 ImpSetAttributesFitToSizeVertical(pText); 1352 } 1353 else 1354 { 1355 ImpSetAttributesFitCommon(pText); 1356 } 1357 1358 // Put text object into edit mode. 1359 SdrPageView* pPV = mpView->GetSdrPageView(); 1360 mpView->SdrBeginTextEdit(pText, pPV); 1361 } 1362 else 1363 { 1364 OSL_FAIL("Object is NO text object"); 1365 } 1366 } 1367 1368 return pObj; 1369 } 1370 1371 /** is called when the current function should be aborted. <p> 1372 This is used when a function gets a KEY_ESCAPE but can also 1373 be called directly. 1374 1375 @returns true if an active function was aborted 1376 */ 1377 bool FuText::cancel() 1378 { 1379 if ( mpView->IsTextEdit() ) 1380 { 1381 if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted) 1382 mxTextObj.reset(nullptr); 1383 1384 mpView->SetCurrentObj(OBJ_TEXT); 1385 mpView->SetEditMode(SdrViewEditMode::Edit); 1386 return true; 1387 } 1388 else 1389 { 1390 return false; 1391 } 1392 } 1393 1394 void FuText::ChangeFontSize( bool bGrow, OutlinerView* pOLV, const FontList* pFontList, ::sd::View* pView ) 1395 { 1396 if( !pFontList || !pView ) 1397 return; 1398 1399 if( pOLV ) 1400 { 1401 pOLV->GetEditView().ChangeFontSize( bGrow, pFontList ); 1402 } 1403 else 1404 { 1405 1406 pView->BegUndo(SdResId(bGrow ? STR_GROW_FONT_SIZE : STR_SHRINK_FONT_SIZE)); 1407 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 1408 for( size_t nMark = 0; nMark < rMarkList.GetMarkCount(); ++nMark ) 1409 { 1410 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( rMarkList.GetMark(nMark)->GetMarkedSdrObj() ); 1411 if( pTextObj ) 1412 { 1413 rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController()); 1414 if (xSelectionController.is() && xSelectionController->ChangeFontSize(bGrow, pFontList)) 1415 { 1416 continue; 1417 } 1418 for( sal_Int32 nText = 0; nText < pTextObj->getTextCount(); nText++ ) 1419 { 1420 pTextObj->setActiveText( nText ); 1421 1422 // Put text object into edit mode. 1423 SdrPageView* pPV = pView->GetSdrPageView(); 1424 pView->SdrBeginTextEdit(pTextObj, pPV); 1425 1426 pOLV = pView->GetTextEditOutlinerView(); 1427 if( pOLV ) 1428 { 1429 EditEngine* pEditEngine = pOLV->GetEditView().GetEditEngine(); 1430 if( pEditEngine ) 1431 { 1432 ESelection aSel; 1433 aSel.nEndPara = pEditEngine->GetParagraphCount()-1; 1434 aSel.nEndPos = pEditEngine->GetTextLen(aSel.nEndPara); 1435 pOLV->SetSelection(aSel); 1436 } 1437 1438 ChangeFontSize( bGrow, pOLV, pFontList, pView ); 1439 } 1440 1441 pView->SdrEndTextEdit(); 1442 } 1443 1444 SfxItemSet aShapeSet( pTextObj->GetMergedItemSet() ); 1445 if( EditView::ChangeFontSize( bGrow, aShapeSet, pFontList ) ) 1446 { 1447 pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT ) ); 1448 pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CJK ) ); 1449 pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CTL ) ); 1450 } 1451 } 1452 } 1453 pView->EndUndo(); 1454 } 1455 } 1456 1457 void FuText::InvalidateBindings() 1458 { 1459 mpViewShell->GetViewFrame()->GetBindings().Invalidate(SidArray); 1460 } 1461 1462 1463 } // end of namespace sd 1464 1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1466
