1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_svx.hxx" 24 25 #include <string> // HACK: prevent conflict between STLPORT and Workshop headers 26 #include <sfx2/app.hxx> 27 #include <sfx2/dispatch.hxx> 28 #include <sfx2/objsh.hxx> 29 #include <sfx2/viewsh.hxx> 30 #include <rtl/ustring.hxx> 31 #include <svx/dialogs.hrc> 32 33 #define TMP_STR_BEGIN '[' 34 #define TMP_STR_END ']' 35 36 #include "svx/drawitem.hxx" 37 #include "svx/xattr.hxx" 38 #include <svx/xtable.hxx> 39 #include <svx/fillctrl.hxx> 40 #include <svx/itemwin.hxx> 41 #include <svx/dialmgr.hxx> 42 #include "helpid.hrc" 43 44 using namespace ::com::sun::star::uno; 45 using namespace ::com::sun::star::util; 46 using namespace ::com::sun::star::beans; 47 using namespace ::com::sun::star::frame; 48 using namespace ::com::sun::star::lang; 49 50 SFX_IMPL_TOOLBOX_CONTROL( SvxFillToolBoxControl, XFillStyleItem ); 51 52 /************************************************************************* 53 |* 54 |* SvxFillToolBoxControl 55 |* 56 \************************************************************************/ 57 58 SvxFillToolBoxControl::SvxFillToolBoxControl( 59 sal_uInt16 nSlotId, 60 sal_uInt16 nId, 61 ToolBox& rTbx ) 62 : SfxToolBoxControl( nSlotId, nId, rTbx ), 63 mpStyleItem(0), 64 mpColorItem(0), 65 mpGradientItem(0), 66 mpHatchItem(0), 67 mpBitmapItem(0), 68 mpFillControl(0), 69 mpFillTypeLB(0), 70 mpFillAttrLB(0), 71 meLastXFS(XFILL_NONE), 72 mbUpdate(false) 73 { 74 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillColor" ))); 75 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillGradient" ))); 76 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillHatch" ))); 77 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FillBitmap" ))); 78 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ColorTableState" ))); 79 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GradientListState" ))); 80 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:HatchListState" ))); 81 addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:BitmapListState" ))); 82 } 83 84 //======================================================================== 85 86 SvxFillToolBoxControl::~SvxFillToolBoxControl() 87 { 88 delete mpStyleItem; 89 delete mpColorItem; 90 delete mpGradientItem; 91 delete mpHatchItem; 92 delete mpBitmapItem; 93 } 94 95 //======================================================================== 96 97 void SvxFillToolBoxControl::StateChanged( 98 sal_uInt16 nSID, 99 SfxItemState eState, 100 const SfxPoolItem* pState) 101 { 102 bool bEnableControls(false); 103 104 if(eState == SFX_ITEM_DISABLED) 105 { 106 // slot disable state 107 if(nSID == SID_ATTR_FILL_STYLE) 108 { 109 mpFillTypeLB->Disable(); 110 mpFillTypeLB->SetNoSelection(); 111 } 112 113 mpFillAttrLB->Disable(); 114 mpFillAttrLB->SetNoSelection(); 115 } 116 else if(SFX_ITEM_AVAILABLE == eState) 117 { 118 // slot available state 119 if(nSID == SID_ATTR_FILL_STYLE) 120 { 121 delete mpStyleItem; 122 mpStyleItem = static_cast< XFillStyleItem* >(pState->Clone()); 123 mpFillTypeLB->Enable(); 124 } 125 else if(mpStyleItem) 126 { 127 const XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue())); 128 129 if(nSID == SID_ATTR_FILL_COLOR) 130 { 131 delete mpColorItem; 132 mpColorItem = static_cast< XFillColorItem* >(pState->Clone()); 133 134 if(eXFS == XFILL_SOLID) 135 { 136 bEnableControls = true; 137 } 138 } 139 else if(nSID == SID_ATTR_FILL_GRADIENT) 140 { 141 delete mpGradientItem; 142 mpGradientItem = static_cast< XFillGradientItem* >(pState->Clone()); 143 144 if(eXFS == XFILL_GRADIENT) 145 { 146 bEnableControls = true; 147 } 148 } 149 else if(nSID == SID_ATTR_FILL_HATCH) 150 { 151 delete mpHatchItem; 152 mpHatchItem = static_cast< XFillHatchItem* >(pState->Clone()); 153 154 if(eXFS == XFILL_HATCH) 155 { 156 bEnableControls = true; 157 } 158 } 159 else if(nSID == SID_ATTR_FILL_BITMAP) 160 { 161 delete mpBitmapItem; 162 mpBitmapItem = static_cast< XFillBitmapItem* >(pState->Clone()); 163 164 if(eXFS == XFILL_BITMAP) 165 { 166 bEnableControls = true; 167 } 168 } 169 } 170 171 if(mpStyleItem) 172 { 173 // ensure that the correct entry is selected in mpFillTypeLB 174 XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue())); 175 const bool bFillTypeChangedByUser(mpFillControl->mbFillTypeChanged); 176 177 if(bFillTypeChangedByUser) 178 { 179 meLastXFS = static_cast< XFillStyle >(mpFillControl->mnLastFillTypeControlSelectEntryPos); 180 mpFillControl->mbFillTypeChanged = false; 181 } 182 183 if(meLastXFS != eXFS) 184 { 185 mbUpdate = true; 186 mpFillTypeLB->SelectEntryPos(sal::static_int_cast<sal_uInt16>(eXFS)); 187 } 188 189 mpFillAttrLB->Enable(); 190 } 191 192 if(bEnableControls) 193 { 194 mpFillAttrLB->Enable(); 195 mbUpdate = true; 196 } 197 198 Update(pState); 199 } 200 else 201 { 202 // slot empty or ambigous 203 if(nSID == SID_ATTR_FILL_STYLE) 204 { 205 mpFillTypeLB->SetNoSelection(); 206 mpFillAttrLB->Disable(); 207 mpFillAttrLB->SetNoSelection(); 208 delete mpStyleItem; 209 mpStyleItem = 0; 210 mbUpdate = false; 211 } 212 else 213 { 214 XFillStyle eXFS(XFILL_NONE); 215 216 if(mpStyleItem) 217 { 218 eXFS = static_cast< XFillStyle >(mpStyleItem->GetValue()); 219 } 220 221 if(!mpStyleItem || 222 (nSID == SID_ATTR_FILL_COLOR && eXFS == XFILL_SOLID) || 223 (nSID == SID_ATTR_FILL_GRADIENT && eXFS == XFILL_GRADIENT) || 224 (nSID == SID_ATTR_FILL_HATCH && eXFS == XFILL_HATCH) || 225 (nSID == SID_ATTR_FILL_BITMAP && eXFS == XFILL_BITMAP)) 226 { 227 mpFillAttrLB->SetNoSelection(); 228 } 229 } 230 } 231 } 232 233 //======================================================================== 234 235 void SvxFillToolBoxControl::Update(const SfxPoolItem* pState) 236 { 237 if(mpStyleItem && pState && mbUpdate) 238 { 239 mbUpdate = false; 240 const XFillStyle eXFS(static_cast< XFillStyle >(mpStyleItem->GetValue())); 241 242 // Pruefen, ob Fuellstil schon vorher aktiv war 243 if(meLastXFS != eXFS) 244 { 245 // update mnLastFillTypeControlSelectEntryPos and fill style list 246 mpFillControl->updateLastFillTypeControlSelectEntryPos(); 247 mpFillControl->InitializeFillStyleAccordingToGivenFillType(eXFS); 248 meLastXFS = eXFS; 249 } 250 251 switch(eXFS) 252 { 253 case XFILL_NONE: 254 { 255 break; 256 } 257 258 case XFILL_SOLID: 259 { 260 if(mpColorItem) 261 { 262 String aString(mpColorItem->GetName()); 263 ::Color aColor = mpColorItem->GetColorValue(); 264 265 mpFillAttrLB->SelectEntry(aString); 266 267 if(mpFillAttrLB->GetSelectEntryPos() == LISTBOX_ENTRY_NOTFOUND || mpFillAttrLB->GetSelectEntryColor() != aColor) 268 { 269 mpFillAttrLB->SelectEntry(aColor); 270 } 271 272 // Pruefen, ob Eintrag nicht in der Liste ist 273 if(mpFillAttrLB->GetSelectEntryPos() == LISTBOX_ENTRY_NOTFOUND || mpFillAttrLB->GetSelectEntryColor() != aColor) 274 { 275 sal_uInt16 nCount = mpFillAttrLB->GetEntryCount(); 276 String aTmpStr; 277 if(nCount > 0) 278 { 279 //Letzter Eintrag wird auf temporaere Farbe geprueft 280 aTmpStr = mpFillAttrLB->GetEntry(nCount - 1); 281 282 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END) 283 { 284 mpFillAttrLB->RemoveEntry(nCount - 1); 285 } 286 } 287 288 aTmpStr = TMP_STR_BEGIN; 289 aTmpStr += aString; 290 aTmpStr += TMP_STR_END; 291 292 sal_uInt16 nPos = mpFillAttrLB->InsertEntry(aColor,aTmpStr); 293 mpFillAttrLB->SelectEntryPos(nPos); 294 } 295 } 296 else 297 { 298 mpFillAttrLB->SetNoSelection(); 299 } 300 break; 301 } 302 303 case XFILL_GRADIENT: 304 { 305 if(mpGradientItem) 306 { 307 String aString(mpGradientItem->GetName()); 308 mpFillAttrLB->SelectEntry(aString); 309 310 // Pruefen, ob Eintrag nicht in der Liste ist 311 if(mpFillAttrLB->GetSelectEntry() != aString) 312 { 313 sal_uInt16 nCount = mpFillAttrLB->GetEntryCount(); 314 String aTmpStr; 315 316 if(nCount > 0) 317 { 318 //Letzter Eintrag wird auf temporaeren Eintrag geprueft 319 aTmpStr = mpFillAttrLB->GetEntry(nCount - 1); 320 321 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END) 322 { 323 mpFillAttrLB->RemoveEntry(nCount - 1); 324 } 325 } 326 327 aTmpStr = TMP_STR_BEGIN; 328 aTmpStr += aString; 329 aTmpStr += TMP_STR_END; 330 331 XGradientEntry* pEntry = new XGradientEntry(mpGradientItem->GetGradientValue(),aTmpStr); 332 XGradientListSharedPtr aGradientList(XPropertyListFactory::CreateSharedXGradientList(String::CreateFromAscii("TmpList"))); 333 334 aGradientList->Insert(pEntry); 335 aGradientList->SetDirty(false); 336 const Bitmap aBmp = aGradientList->GetUiBitmap(0); 337 338 if(!aBmp.IsEmpty()) 339 { 340 ((ListBox*)mpFillAttrLB)->InsertEntry(pEntry->GetName(),aBmp); 341 mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1); 342 } 343 } 344 } 345 else 346 { 347 mpFillAttrLB->SetNoSelection(); 348 } 349 break; 350 } 351 352 case XFILL_HATCH: 353 { 354 if(mpHatchItem) 355 { 356 String aString(mpHatchItem->GetName()); 357 mpFillAttrLB->SelectEntry(aString); 358 359 // Pruefen, ob Eintrag nicht in der Liste ist 360 if(mpFillAttrLB->GetSelectEntry() != aString) 361 { 362 sal_uInt16 nCount = mpFillAttrLB->GetEntryCount(); 363 String aTmpStr; 364 if(nCount > 0) 365 { 366 //Letzter Eintrag wird auf temporaeren Eintrag geprueft 367 aTmpStr = mpFillAttrLB->GetEntry(nCount - 1); 368 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && 369 aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END) 370 { 371 mpFillAttrLB->RemoveEntry(nCount - 1); 372 } 373 } 374 375 aTmpStr = TMP_STR_BEGIN; 376 aTmpStr += aString; 377 aTmpStr += TMP_STR_END; 378 379 XHatchEntry* pEntry = new XHatchEntry(mpHatchItem->GetHatchValue(),aTmpStr); 380 XHatchListSharedPtr aHatchList(XPropertyListFactory::CreateSharedXHatchList(String::CreateFromAscii("TmpList"))); 381 382 aHatchList->Insert(pEntry); 383 aHatchList->SetDirty(sal_False); 384 const Bitmap aBmp = aHatchList->GetUiBitmap(0); 385 386 if(!aBmp.IsEmpty()) 387 { 388 ((ListBox*)mpFillAttrLB)->InsertEntry(pEntry->GetName(),aBmp); 389 mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1); 390 } 391 } 392 } 393 else 394 { 395 mpFillAttrLB->SetNoSelection(); 396 } 397 break; 398 } 399 400 case XFILL_BITMAP: 401 { 402 if(mpBitmapItem) 403 { 404 String aString(mpBitmapItem->GetName()); 405 mpFillAttrLB->SelectEntry(aString); 406 407 // Pruefen, ob Eintrag nicht in der Liste ist 408 if(mpFillAttrLB->GetSelectEntry() != aString) 409 { 410 sal_uInt16 nCount = mpFillAttrLB->GetEntryCount(); 411 String aTmpStr; 412 413 if(nCount > 0) 414 { 415 //Letzter Eintrag wird auf temporaeren Eintrag geprueft 416 aTmpStr = mpFillAttrLB->GetEntry(nCount - 1); 417 418 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END) 419 { 420 mpFillAttrLB->RemoveEntry(nCount - 1); 421 } 422 } 423 424 aTmpStr = TMP_STR_BEGIN; 425 aTmpStr += aString; 426 aTmpStr += TMP_STR_END; 427 428 XBitmapListSharedPtr aNew(XPropertyListFactory::CreateSharedXBitmapList(String::CreateFromAscii("TmpList"))); 429 aNew->Insert(new XBitmapEntry(mpBitmapItem->GetGraphicObject(),aTmpStr)); 430 aNew->SetDirty(false); 431 432 mpFillAttrLB->Fill(aNew); 433 mpFillAttrLB->SelectEntryPos(mpFillAttrLB->GetEntryCount() - 1); 434 } 435 } 436 else 437 { 438 mpFillAttrLB->SetNoSelection(); 439 } 440 break; 441 } 442 443 default: 444 { 445 DBG_ERROR("Nicht unterstuetzter Flaechentyp"); 446 break; 447 } 448 } 449 450 // update mnLastFillAttrControlSelectEntryPos 451 mpFillControl->updateLastFillAttrControlSelectEntryPos(); 452 } 453 454 if(pState && mpStyleItem) 455 { 456 XFillStyle eXFS = static_cast< XFillStyle >(mpStyleItem->GetValue()); 457 458 // Die Listen haben sich geaendert ? 459 switch(eXFS) 460 { 461 case XFILL_SOLID: 462 { 463 const SvxColorTableItem* pItem = dynamic_cast< const SvxColorTableItem* >(pState); 464 465 if(pItem) 466 { 467 ::Color aTmpColor(mpFillAttrLB->GetSelectEntryColor()); 468 mpFillAttrLB->Clear(); 469 mpFillAttrLB->Fill(pItem->GetColorTable()); 470 mpFillAttrLB->SelectEntry(aTmpColor); 471 } 472 break; 473 } 474 case XFILL_GRADIENT: 475 { 476 const SvxGradientListItem* pItem = dynamic_cast< const SvxGradientListItem* >(pState); 477 478 if(pItem) 479 { 480 String aString(mpFillAttrLB->GetSelectEntry()); 481 mpFillAttrLB->Clear(); 482 mpFillAttrLB->Fill(pItem->GetGradientList()); 483 mpFillAttrLB->SelectEntry(aString); 484 } 485 break; 486 } 487 case XFILL_HATCH: 488 { 489 const SvxHatchListItem* pItem = dynamic_cast< const SvxHatchListItem* >(pState); 490 491 if(pItem) 492 { 493 String aString(mpFillAttrLB->GetSelectEntry()); 494 mpFillAttrLB->Clear(); 495 mpFillAttrLB->Fill(pItem->GetHatchList()); 496 mpFillAttrLB->SelectEntry(aString); 497 } 498 break; 499 } 500 case XFILL_BITMAP: 501 { 502 const SvxBitmapListItem* pItem = dynamic_cast< const SvxBitmapListItem* >(pState); 503 504 if(pItem) 505 { 506 String aString(mpFillAttrLB->GetSelectEntry()); 507 mpFillAttrLB->Clear(); 508 mpFillAttrLB->Fill(pItem->GetBitmapList()); 509 mpFillAttrLB->SelectEntry(aString); 510 } 511 break; 512 } 513 default: // XFILL_NONE 514 { 515 break; 516 } 517 } 518 } 519 } 520 521 //======================================================================== 522 523 Window* SvxFillToolBoxControl::CreateItemWindow(Window *pParent) 524 { 525 if(GetSlotId() == SID_ATTR_FILL_STYLE) 526 { 527 mpFillControl = new FillControl(pParent); 528 // Damit dem FillControl das SvxFillToolBoxControl bekannt ist 529 // (und um kompatibel zu bleiben) 530 mpFillControl->SetData(this); 531 532 mpFillAttrLB = (SvxFillAttrBox*)mpFillControl->mpLbFillAttr; 533 mpFillTypeLB = (SvxFillTypeBox*)mpFillControl->mpLbFillType; 534 535 mpFillAttrLB->SetUniqueId(HID_FILL_ATTR_LISTBOX); 536 mpFillTypeLB->SetUniqueId(HID_FILL_TYPE_LISTBOX); 537 538 if(!mpStyleItem) 539 { 540 // for Writer and Calc it's not the same instance of 541 // SvxFillToolBoxControl which gets used after deselecting 542 // and selecting a DrawObject, thhus a useful initialization is 543 // needed to get the FillType and the FillStyle List inited 544 // correctly. This in combination with meLastXFS inited to 545 // XFILL_NONE do the trick 546 mpStyleItem = new XFillStyleItem(XFILL_SOLID); 547 } 548 549 return mpFillControl; 550 } 551 return NULL; 552 } 553 554 /************************************************************************* 555 |* 556 |* FillControl 557 |* 558 \************************************************************************/ 559 560 FillControl::FillControl(Window* pParent,WinBits nStyle) 561 : Window(pParent,nStyle | WB_DIALOGCONTROL), 562 mpLbFillType(new SvxFillTypeBox(this)), 563 mpLbFillAttr(new SvxFillAttrBox(this)), 564 maLogicalFillSize(40,80), 565 maLogicalAttrSize(50,80), 566 mnLastFillTypeControlSelectEntryPos(mpLbFillType->GetSelectEntryPos()), 567 mnLastFillAttrControlSelectEntryPos(mpLbFillAttr->GetSelectEntryPos()), 568 mbFillTypeChanged(false) 569 { 570 Size aTypeSize(LogicToPixel(maLogicalFillSize,MAP_APPFONT)); 571 Size aAttrSize(LogicToPixel(maLogicalAttrSize,MAP_APPFONT)); 572 mpLbFillType->SetSizePixel(aTypeSize); 573 mpLbFillAttr->SetSizePixel(aAttrSize); 574 575 //to get the base height 576 aTypeSize = mpLbFillType->GetSizePixel(); 577 aAttrSize = mpLbFillAttr->GetSizePixel(); 578 Point aAttrPnt = mpLbFillAttr->GetPosPixel(); 579 SetSizePixel( 580 Size(aAttrPnt.X() + aAttrSize.Width(), 581 Max(aAttrSize.Height(),aTypeSize.Height()))); 582 583 mpLbFillType->SetSelectHdl(LINK(this,FillControl,SelectFillTypeHdl)); 584 mpLbFillAttr->SetSelectHdl(LINK(this,FillControl,SelectFillAttrHdl)); 585 } 586 587 //------------------------------------------------------------------------ 588 589 FillControl::~FillControl() 590 { 591 delete mpLbFillType; 592 delete mpLbFillAttr; 593 } 594 595 //------------------------------------------------------------------------ 596 597 void FillControl::InitializeFillStyleAccordingToGivenFillType(XFillStyle aFillStyle) 598 { 599 SfxObjectShell* pSh = SfxObjectShell::Current(); 600 bool bDone(false); 601 602 if(pSh) 603 { 604 // clear in all cases, else we would risk a mix of FillStyles in the Style list 605 mpLbFillAttr->Clear(); 606 607 switch(aFillStyle) 608 { 609 case XFILL_SOLID: 610 { 611 if(pSh->GetItem(SID_COLOR_TABLE)) 612 { 613 const SvxColorTableItem* pItem = static_cast< const SvxColorTableItem* >(pSh->GetItem(SID_COLOR_TABLE)); 614 mpLbFillAttr->Enable(); 615 mpLbFillAttr->Fill(pItem->GetColorTable()); 616 bDone = true; 617 } 618 break; 619 } 620 621 case XFILL_GRADIENT: 622 { 623 if(pSh->GetItem(SID_GRADIENT_LIST)) 624 { 625 const SvxGradientListItem* pItem = static_cast< const SvxGradientListItem* >(pSh->GetItem(SID_GRADIENT_LIST)); 626 mpLbFillAttr->Enable(); 627 mpLbFillAttr->Fill(pItem->GetGradientList()); 628 bDone = true; 629 } 630 break; 631 } 632 633 case XFILL_HATCH: 634 { 635 if(pSh->GetItem(SID_HATCH_LIST)) 636 { 637 const SvxHatchListItem* pItem = static_cast< const SvxHatchListItem* >(pSh->GetItem(SID_HATCH_LIST)); 638 mpLbFillAttr->Enable(); 639 mpLbFillAttr->Fill(pItem->GetHatchList()); 640 bDone = true; 641 } 642 break; 643 } 644 645 case XFILL_BITMAP: 646 { 647 if(pSh->GetItem(SID_BITMAP_LIST)) 648 { 649 const SvxBitmapListItem* pItem = static_cast< const SvxBitmapListItem* >(pSh->GetItem(SID_BITMAP_LIST)); 650 mpLbFillAttr->Enable(); 651 mpLbFillAttr->Fill(pItem->GetBitmapList()); 652 bDone = true; 653 } 654 break; 655 } 656 default: // XFILL_NONE 657 { 658 // accept disable (no styles for XFILL_NONE) 659 break; 660 } 661 } 662 } 663 664 if(!bDone) 665 { 666 mpLbFillAttr->Disable(); 667 } 668 } 669 670 void FillControl::updateLastFillTypeControlSelectEntryPos() 671 { 672 mnLastFillTypeControlSelectEntryPos = mpLbFillType->GetSelectEntryPos(); 673 } 674 675 IMPL_LINK(FillControl,SelectFillTypeHdl,ListBox *,pBox) 676 { 677 if(!pBox) // only work with real calls from ListBox, do not accept direct calls with zeros here 678 { 679 return 0; 680 } 681 682 const bool bAction( 683 !mpLbFillType->IsTravelSelect() // keep TravelSelect, this means keyboard up/down in the list 684 && mpLbFillType->GetSelectEntryCount() 685 && mpLbFillType->GetSelectEntryPos() != mnLastFillTypeControlSelectEntryPos); 686 687 updateLastFillTypeControlSelectEntryPos(); 688 XFillStyle eXFS = static_cast< XFillStyle >(mpLbFillType->GetSelectEntryPos()); 689 690 if(bAction && XFILL_NONE != eXFS) 691 { 692 mbFillTypeChanged = true; 693 } 694 695 // update list of FillStyles in any case 696 InitializeFillStyleAccordingToGivenFillType(eXFS); 697 698 // for XFILL_NONE do no longer call SelectFillAttrHdl (as done before), 699 // trigger needed actions directly. This is the only action this handler 700 // can trigger directly as the user action is finished in this case 701 if(XFILL_NONE == eXFS && bAction) 702 { 703 // for XFILL_NONE do no longer call SelectFillAttrHdl, 704 // trigger needed actions directly 705 Any a; 706 Sequence< PropertyValue > aArgsFillStyle(1); 707 XFillStyleItem aXFillStyleItem(eXFS); 708 709 aArgsFillStyle[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle")); 710 aXFillStyleItem.QueryValue(a); 711 aArgsFillStyle[0].Value = a; 712 ((SvxFillToolBoxControl*)GetData())->Dispatch(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillStyle")), aArgsFillStyle); 713 } 714 715 mpLbFillType->Selected(); 716 717 // release focus. Needed to get focus automatically back to EditView 718 if(mpLbFillType->IsRelease()) 719 { 720 SfxViewShell* pViewShell = SfxViewShell::Current(); 721 722 if(pViewShell && pViewShell->GetWindow()) 723 { 724 pViewShell->GetWindow()->GrabFocus(); 725 } 726 } 727 728 return 0; 729 } 730 731 //------------------------------------------------------------------------ 732 733 void FillControl::updateLastFillAttrControlSelectEntryPos() 734 { 735 mnLastFillAttrControlSelectEntryPos = mpLbFillAttr->GetSelectEntryPos(); 736 } 737 738 IMPL_LINK(FillControl, SelectFillAttrHdl, ListBox *, pBox) 739 { 740 if(!pBox) // only work with real calls from ListBox, do not accept direct calls with zeros here 741 { 742 return 0; 743 } 744 745 const bool bAction( 746 !mpLbFillAttr->IsTravelSelect() // keep TravelSelect, this means keyboard up/down in the list 747 && mpLbFillAttr->GetSelectEntryCount() 748 && mpLbFillAttr->GetSelectEntryPos() != mnLastFillAttrControlSelectEntryPos); 749 750 updateLastFillAttrControlSelectEntryPos(); 751 752 if(bAction) 753 { 754 SfxObjectShell* pSh = SfxObjectShell::Current(); 755 756 // Need to prepare the PropertyValue for the FillStyle dispatch action early, 757 // else the call for FillType to Dispatch(".uno:FillStyle") will already destroy the current state 758 // of selection in mpLbFillAttr again by calls to StateChanged which *will* set to no 759 // selection again (e.g. when two objects, same fill style, but different fill attributes) 760 Any a; 761 Sequence< PropertyValue > aArgsFillAttr(1); 762 ::rtl::OUString aFillAttrCommand; 763 XFillStyle eXFS(static_cast< XFillStyle >(mpLbFillType->GetSelectEntryPos())); 764 765 switch(eXFS) 766 { 767 case XFILL_NONE: 768 { 769 // handled in SelectFillTypeHdl, nothing to do here 770 break; 771 } 772 773 case XFILL_SOLID: 774 { 775 //Eintrag wird auf temporaere Farbe geprueft 776 String aTmpStr = mpLbFillAttr->GetSelectEntry(); 777 778 if(aTmpStr.GetChar(0) == TMP_STR_BEGIN && aTmpStr.GetChar(aTmpStr.Len() - 1) == TMP_STR_END) 779 { 780 aTmpStr.Erase(aTmpStr.Len() - 1,1); 781 aTmpStr.Erase(0,1); 782 } 783 784 XFillColorItem aXFillColorItem(aTmpStr,mpLbFillAttr->GetSelectEntryColor()); 785 aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")); 786 aXFillColorItem.QueryValue(a); 787 aArgsFillAttr[0].Value = a; 788 aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillColor")); 789 break; 790 } 791 case XFILL_GRADIENT: 792 { 793 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos(); 794 795 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_GRADIENT_LIST)) 796 { 797 const SvxGradientListItem* pItem = static_cast< const SvxGradientListItem* >(pSh->GetItem(SID_GRADIENT_LIST)); 798 799 if(nPos < pItem->GetGradientList()->Count()) // kein temp. Eintrag ? 800 { 801 XGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient(); 802 XFillGradientItem aXFillGradientItem(mpLbFillAttr->GetSelectEntry(),aGradient); 803 aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillGradient")); 804 aXFillGradientItem.QueryValue(a); 805 aArgsFillAttr[0].Value = a; 806 aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillGradient")); 807 } 808 } 809 break; 810 } 811 812 case XFILL_HATCH: 813 { 814 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos(); 815 816 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_HATCH_LIST)) 817 { 818 const SvxHatchListItem* pItem = static_cast< const SvxHatchListItem* >(pSh->GetItem(SID_HATCH_LIST)); 819 820 if(nPos < pItem->GetHatchList()->Count()) // kein temp. Eintrag ? 821 { 822 XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch(); 823 XFillHatchItem aXFillHatchItem(mpLbFillAttr->GetSelectEntry(),aHatch); 824 825 aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillHatch")); 826 aXFillHatchItem.QueryValue(a); 827 aArgsFillAttr[0].Value = a; 828 aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillHatch")); 829 } 830 } 831 break; 832 } 833 834 case XFILL_BITMAP: 835 { 836 sal_uInt16 nPos = mpLbFillAttr->GetSelectEntryPos(); 837 838 if(nPos != LISTBOX_ENTRY_NOTFOUND && pSh && pSh->GetItem(SID_BITMAP_LIST)) 839 { 840 const SvxBitmapListItem* pItem = static_cast< const SvxBitmapListItem* >(pSh->GetItem(SID_BITMAP_LIST)); 841 842 if(nPos < pItem->GetBitmapList()->Count()) // kein temp. Eintrag ? 843 { 844 const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos); 845 const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->GetSelectEntry(),pXBitmapEntry->GetGraphicObject()); 846 847 aArgsFillAttr[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillBitmap")); 848 aXFillBitmapItem.QueryValue(a); 849 aArgsFillAttr[0].Value = a; 850 aFillAttrCommand = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillBitmap")); 851 } 852 } 853 break; 854 } 855 } 856 857 // this is the place where evtl. a new slot action may be introduced to avoid the 858 // two undo entries. Reason for this is that indeed two actions are executed, the fill style 859 // and the fill attribute change. The sidebar already handles both separately, so 860 // changing the fill style already changes the object and adds a default fill attribute for 861 // the newly choosen fill style. 862 // This control uses the older user's two-step action to select a fill style and a fill attribute. In 863 // this case a lot of things may go wrong (e.g. the user stops that action and does something 864 // different), thus the solution of the sidebar should be preferred from my POV in the future 865 866 // first set the fill style if changed 867 if(mbFillTypeChanged) 868 { 869 Sequence< PropertyValue > aArgsFillStyle(1); 870 XFillStyleItem aXFillStyleItem(eXFS); 871 872 aArgsFillStyle[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle")); 873 aXFillStyleItem.QueryValue(a); 874 aArgsFillStyle[0].Value = a; 875 ((SvxFillToolBoxControl*)GetData())->Dispatch(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:FillStyle")), aArgsFillStyle); 876 mbFillTypeChanged = false; 877 } 878 879 // second set fill attribute when a change was detected and prepared 880 if(aFillAttrCommand.getLength()) 881 { 882 ((SvxFillToolBoxControl*)GetData())->Dispatch(aFillAttrCommand, aArgsFillAttr); 883 } 884 885 // release focus. Needed to get focus automatically back to EditView 886 if(mpLbFillAttr->IsRelease() && pBox) 887 { 888 SfxViewShell* pViewShell = SfxViewShell::Current(); 889 890 if(pViewShell && pViewShell->GetWindow()) 891 { 892 pViewShell->GetWindow()->GrabFocus(); 893 } 894 } 895 } 896 897 return 0; 898 } 899 900 //------------------------------------------------------------------------ 901 902 void FillControl::Resize() 903 { 904 // Breite der beiden ListBoxen nicht 1/2 : 1/2, sondern 2/5 : 3/5 905 long nW = GetOutputSizePixel().Width() / 5; 906 long nH = 180; 907 long nSep = 0; // war vorher 4 908 909 mpLbFillType->SetSizePixel(Size(nW * 2 - nSep,nH)); 910 mpLbFillAttr->SetPosSizePixel(Point(nW * 2 + nSep,0),Size(nW * 3 - nSep,nH)); 911 } 912 913 //------------------------------------------------------------------------ 914 915 void FillControl::DataChanged(const DataChangedEvent& rDCEvt) 916 { 917 if((rDCEvt.GetType() == DATACHANGED_SETTINGS) && 918 (rDCEvt.GetFlags() & SETTINGS_STYLE)) 919 { 920 Size aTypeSize(LogicToPixel(maLogicalFillSize,MAP_APPFONT)); 921 Size aAttrSize(LogicToPixel(maLogicalAttrSize,MAP_APPFONT)); 922 mpLbFillType->SetSizePixel(aTypeSize); 923 mpLbFillAttr->SetSizePixel(aAttrSize); 924 925 //to get the base height 926 aTypeSize = mpLbFillType->GetSizePixel(); 927 aAttrSize = mpLbFillAttr->GetSizePixel(); 928 Point aAttrPnt = mpLbFillAttr->GetPosPixel(); 929 930 SetSizePixel( 931 Size(aAttrPnt.X() + aAttrSize.Width(), 932 Max(aAttrSize.Height(),aTypeSize.Height()))); 933 } 934 Window::DataChanged(rDCEvt); 935 } 936 937 //------------------------------------------------------------------------ 938 //eof 939