1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_fpicker.hxx" 30 31 #include <tchar.h> 32 #include "previewadapter.hxx" 33 34 #ifndef _COM_SUN_STAR_UI_DIALOG_FILEPREVIEWIMAGEFORMATS_HPP_ 35 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> 36 #endif 37 #include "dibpreview.hxx" 38 #include "../misc/WinImplHelper.hxx" 39 40 #include <memory> 41 #include <stdexcept> 42 43 //--------------------------------------------- 44 // 45 //--------------------------------------------- 46 47 using namespace ::com::sun::star::uno; 48 using namespace ::com::sun::star::lang; 49 50 //--------------------------------------------- 51 // An impl class to hide implementation details 52 // from clients 53 //--------------------------------------------- 54 55 class CPreviewAdapterImpl 56 { 57 public: 58 CPreviewAdapterImpl(HINSTANCE instance); 59 60 virtual ~CPreviewAdapterImpl(); 61 62 virtual sal_Int32 SAL_CALL getTargetColorDepth(); 63 64 virtual sal_Int32 SAL_CALL getAvailableWidth(); 65 66 virtual sal_Int32 SAL_CALL getAvailableHeight(); 67 68 virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage ) 69 throw (IllegalArgumentException,RuntimeException); 70 71 virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState); 72 73 virtual sal_Bool SAL_CALL getShowState(); 74 75 virtual void SAL_CALL setParent(HWND parent); 76 77 virtual HWND SAL_CALL getParent(); 78 79 //------------------------------------- 80 // parent notification handler 81 //------------------------------------- 82 83 virtual void SAL_CALL notifyParentShow(sal_Bool bShow); 84 85 virtual void SAL_CALL notifyParentSizeChanged(); 86 87 virtual void SAL_CALL notifyParentWindowPosChanged(); 88 89 protected: 90 virtual void SAL_CALL calcRightMargin(); 91 92 virtual void SAL_CALL rearrangeLayout(); 93 94 void SAL_CALL initializeActivePreview() throw(std::runtime_error); 95 96 HWND SAL_CALL findFileListbox() const; 97 98 // member 99 protected: 100 HINSTANCE m_Instance; 101 std::auto_ptr<PreviewBase> m_Preview; 102 HWND m_FileDialog; 103 int m_RightMargin; 104 105 //prevent copy/assignment 106 private: 107 CPreviewAdapterImpl(const CPreviewAdapterImpl&); 108 CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&); 109 }; 110 111 //----------------------------------------- 112 // 113 //----------------------------------------- 114 115 CPreviewAdapterImpl::CPreviewAdapterImpl(HINSTANCE instance) : 116 m_Instance(instance), 117 m_Preview(new PreviewBase()), // create dummy preview (NULL-Object pattern) 118 m_FileDialog(0), 119 m_RightMargin(0) 120 { 121 } 122 123 //----------------------------------------- 124 // 125 //----------------------------------------- 126 127 CPreviewAdapterImpl::~CPreviewAdapterImpl() 128 { 129 } 130 131 //----------------------------------------- 132 // 133 //----------------------------------------- 134 135 sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth() 136 { 137 return m_Preview->getTargetColorDepth(); 138 } 139 140 //----------------------------------------- 141 // 142 //----------------------------------------- 143 144 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth() 145 { 146 return m_Preview->getAvailableWidth(); 147 } 148 149 //----------------------------------------- 150 // 151 //----------------------------------------- 152 153 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight() 154 { 155 return m_Preview->getAvailableHeight(); 156 } 157 158 //----------------------------------------- 159 // 160 //----------------------------------------- 161 162 void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage ) 163 throw (IllegalArgumentException,RuntimeException) 164 { 165 m_Preview->setImage(aImageFormat,aImage); 166 } 167 168 //----------------------------------------- 169 // 170 //----------------------------------------- 171 172 sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState ) 173 { 174 sal_Bool bRet = m_Preview->setShowState(bShowState); 175 rearrangeLayout(); 176 return bRet; 177 } 178 179 //----------------------------------------- 180 // 181 //----------------------------------------- 182 183 sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState() 184 { 185 return m_Preview->getShowState(); 186 } 187 188 //----------------------------------------- 189 // 190 //----------------------------------------- 191 192 void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent) 193 { 194 OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle"); 195 196 m_FileDialog = parent; 197 calcRightMargin(); 198 } 199 200 //----------------------------------------- 201 // 202 //----------------------------------------- 203 204 HWND SAL_CALL CPreviewAdapterImpl::getParent() 205 { 206 return m_FileDialog; 207 } 208 209 //----------------------------------------- 210 // 211 //----------------------------------------- 212 213 void SAL_CALL CPreviewAdapterImpl::calcRightMargin() 214 { 215 // Calculate the right reference margin 216 // 217 // Assumtions: 218 // 1. This method will be called before the dialog becomes 219 // visible 220 // 2. There exist a FileListbox with the id lst1 even 221 // if it is not visible like under Win2000/XP 222 // 3. Initially this FileListbox has the appropriate size 223 // to fit within the FileListbox 224 // 4. The margin between the right edge of the FileListbox 225 // and the right edge of the FileDialog will be constant 226 // even if the size of the dialog changes 227 228 HWND flb = GetDlgItem(m_FileDialog,lst1); 229 230 OSL_ENSURE(IsWindow(flb),"Filelistbox not found"); 231 232 RECT rcFlb; 233 GetWindowRect(flb,&rcFlb); 234 235 RECT rcFileDlg; 236 GetWindowRect(m_FileDialog,&rcFileDlg); 237 238 m_RightMargin = rcFileDlg.right - rcFlb.right; 239 } 240 241 //----------------------------------------- 242 // 243 //----------------------------------------- 244 245 void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool) 246 { 247 } 248 249 //----------------------------------------- 250 // 251 //----------------------------------------- 252 253 void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged() 254 { 255 rearrangeLayout(); 256 } 257 258 //----------------------------------------- 259 // 260 //----------------------------------------- 261 262 void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged() 263 { 264 } 265 266 //----------------------------------------- 267 // 268 //----------------------------------------- 269 270 void SAL_CALL CPreviewAdapterImpl::rearrangeLayout() 271 { 272 // try to get a handle to the filelistbox 273 // if there is no new-style filelistbox like 274 // in Win2000/XP there should be at least the 275 // old listbox, so we take this one 276 // lst1 - identifies the old-style filelistbox 277 // lst2 - identifies the new-style filelistbox 278 // see dlgs.h 279 HWND flb_new = findFileListbox(); 280 281 // under Windows NT 4.0 the size of the old 282 // filelistbox will be used as reference for 283 // sizing the new filelistbox, so we have 284 // to change the size of it too 285 HWND flb_old = GetDlgItem(m_FileDialog,lst1); 286 287 RECT rcFlbNew; 288 GetWindowRect(flb_new,&rcFlbNew); 289 290 RECT rcFileDlg; 291 GetWindowRect(m_FileDialog,&rcFileDlg); 292 rcFileDlg.right -= m_RightMargin; 293 294 // the available area for the filelistbox should be 295 // the left edge of the filelistbox and the right 296 // edge of the OK button, we take this as reference 297 int height = rcFlbNew.bottom - rcFlbNew.top; 298 int width = rcFileDlg.right - rcFlbNew.left; 299 300 HWND prvwnd = m_Preview->getWindowHandle(); 301 302 // we use GetWindowLong to ask for the visibility 303 // of the preview window because IsWindowVisible 304 // only returns true the specified window including 305 // its parent windows are visible 306 // this is not the case when we are called in response 307 // to the WM_SHOWWINDOW message, somehow the WS_VISIBLE 308 // style bit of the FileOpen dialog must be set after that 309 // message 310 LONG lStyle = GetWindowLong(prvwnd,GWL_STYLE); 311 bool bIsVisible = ((lStyle & WS_VISIBLE) != 0); 312 313 int cx = 0; 314 315 if (IsWindow(prvwnd) && bIsVisible) 316 { 317 cx = width/2; 318 319 // resize the filelistbox to the half of the 320 // available space 321 bool bRet = SetWindowPos(flb_new, 322 NULL, 0, 0, cx, height, 323 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 324 325 bRet = SetWindowPos(flb_old, 326 NULL, 0, 0, cx, height, 327 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 328 329 // get the new dimensions of the filelistbox after 330 // resizing and take the right,top corner as starting 331 // point for the preview window 332 GetWindowRect(flb_new,&rcFlbNew); 333 POINT pt = { rcFlbNew.right, rcFlbNew.top }; 334 ScreenToClient(m_FileDialog,&pt); 335 336 // resize the preview window to fit within 337 // the available space and set the window 338 // to the top of the z-order else it will 339 // be invisible 340 SetWindowPos(prvwnd, 341 HWND_TOP, pt.x, pt.y, cx, height, SWP_NOACTIVATE); 342 } 343 else 344 { 345 // resize the filelistbox to the maximum available 346 // space 347 cx = rcFileDlg.right - rcFlbNew.left; 348 349 // resize the old filelistbox 350 SetWindowPos(flb_old, 351 NULL, 0, 0, cx, height, 352 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 353 354 // resize the new filelistbox 355 SetWindowPos(flb_new, 356 NULL, 0, 0, cx, height, 357 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 358 } 359 } 360 361 //----------------------------------------- 362 // 363 //----------------------------------------- 364 365 void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error) 366 { 367 sal_Bool bShowState = m_Preview->getImaginaryShowState(); 368 369 sal_Int16 aImgFrmt; 370 Any aImg; 371 m_Preview->getImage(aImgFrmt,aImg); 372 373 HWND flb = findFileListbox(); 374 375 PreviewBase* prv = new CDIBPreview( 376 m_Instance, GetParent(flb), bShowState); 377 378 m_Preview.reset(prv); 379 380 m_Preview->setImage(aImgFrmt,aImg); 381 } 382 383 //----------------------------------------- 384 // 385 //----------------------------------------- 386 387 HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const 388 { 389 // try to get a handle to the filelistbox 390 // if there is no new-style filelistbox like 391 // in Win2000/XP there should be at least the 392 // old listbox, so we take this one 393 // lst1 - identifies the old-style filelistbox 394 // lst2 - identifies the new-style filelistbox 395 // see dlgs.h 396 HWND flb = GetDlgItem(m_FileDialog,lst2); 397 if (!IsWindow(flb)) 398 flb = GetDlgItem(m_FileDialog,lst1); 399 400 return flb; 401 } 402 403 404 //############################################################## 405 406 407 //----------------------------------------- 408 // Special implementation for Win98 409 // because: 410 // 411 //----------------------------------------- 412 413 class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl 414 { 415 public: 416 CWin98PreviewAdapterImpl(HINSTANCE instance); 417 418 virtual void SAL_CALL notifyParentWindowPosChanged(); 419 420 protected: 421 virtual void SAL_CALL rearrangeLayout(); 422 423 bool isValidToolbarDimension() const; 424 425 private: 426 sal_Bool m_PreviewActive; 427 int m_ToolbarPosX; 428 int m_ToolbarPosY; 429 int m_ToolbarWidth; 430 int m_ToolbarHeight; 431 }; 432 433 //-------------------------------------------- 434 // 435 //-------------------------------------------- 436 437 CWin98PreviewAdapterImpl::CWin98PreviewAdapterImpl(HINSTANCE instance) : 438 CPreviewAdapterImpl(instance), 439 m_PreviewActive(sal_False), 440 m_ToolbarPosX(0), 441 m_ToolbarPosY(0), 442 m_ToolbarWidth(0), 443 m_ToolbarHeight(0) 444 { 445 } 446 447 //-------------------------------------------- 448 // 449 //-------------------------------------------- 450 451 void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged() 452 { 453 try 454 { 455 // the reason for this condition is 456 // Windows 98 457 // Under Windows 98 the message WM_SHOWWINDOW 458 // will be sent only the first time the 459 // GetOpenFileName function is called within 460 // the same process 461 // so we must use another message to initialize 462 // the preview window 463 if (IsWindow(m_FileDialog) && !m_PreviewActive) 464 { 465 initializeActivePreview(); 466 m_PreviewActive = sal_True; 467 rearrangeLayout(); 468 } 469 470 if (IsWindow(m_FileDialog) && !isValidToolbarDimension()) 471 { 472 RECT rcStc1; 473 GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1); 474 475 RECT rcCmb2; 476 GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2); 477 478 // Assumption: 479 // the toolbar position is only valid 480 // if the left edge is greater or equal 481 // than the right edge of the drives listbox 482 // the stc1 static text is invisible at runtime 483 // but will be used as reference for the position 484 // and dimension of the toolbar 485 if (rcStc1.left >= rcCmb2.right) 486 { 487 // important: save the upper left corner in 488 // client coordinates 489 POINT pt = {rcStc1.left,rcStc1.top}; 490 ScreenToClient(m_FileDialog,&pt); 491 492 m_ToolbarPosX = pt.x; 493 m_ToolbarPosY = pt.y; 494 m_ToolbarWidth = rcStc1.right - rcStc1.left; 495 m_ToolbarHeight = rcStc1.bottom - rcStc1.top; 496 } 497 } 498 } 499 catch(std::runtime_error&) 500 { 501 } 502 } 503 504 //-------------------------------------------- 505 // 506 //-------------------------------------------- 507 508 void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout() 509 { 510 CPreviewAdapterImpl::rearrangeLayout(); 511 512 // fix the position of the upper toolbar 513 // because the FileDialog moves all windows 514 // that are to the right of the FileListbox 515 // so if we have changed the size of the 516 // FileListbox we would run into trouble else 517 if (isValidToolbarDimension()) 518 { 519 HWND hwndTlb = FindWindowEx( 520 m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL); 521 522 SetWindowPos(hwndTlb, 523 HWND_TOP, 524 m_ToolbarPosX, 525 m_ToolbarPosY, 526 m_ToolbarWidth, 527 m_ToolbarHeight, 528 SWP_NOACTIVATE); 529 } 530 } 531 532 //-------------------------------------------- 533 // 534 //-------------------------------------------- 535 536 bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const 537 { 538 return (m_ToolbarPosX > 0 && 539 m_ToolbarPosY > 0 && 540 m_ToolbarWidth > 0 && 541 m_ToolbarHeight > 0); 542 } 543 544 //############################################################## 545 546 547 //-------------------------------------------- 548 // Implementation for Windows 95/NT/ME/2000/XP 549 // because: 550 // 551 //-------------------------------------------- 552 553 class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl 554 { 555 public: 556 CWin95NTPreviewAdapterImpl(HINSTANCE instance); 557 558 virtual void SAL_CALL notifyParentShow(sal_Bool bShow); 559 }; 560 561 //-------------------------------------------- 562 // 563 //-------------------------------------------- 564 565 CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) : 566 CPreviewAdapterImpl(instance) 567 { 568 } 569 570 //-------------------------------------------- 571 // 572 //-------------------------------------------- 573 574 void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow) 575 { 576 try 577 { 578 if (bShow) 579 { 580 initializeActivePreview(); 581 rearrangeLayout(); 582 } 583 } 584 catch(std::runtime_error&) 585 { 586 } 587 } 588 589 590 //############################################################## 591 592 593 //------------------------------- 594 // ctor 595 //------------------------------- 596 597 CPreviewAdapter::CPreviewAdapter(HINSTANCE instance) 598 { 599 if (!IsWindows98()) 600 m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance)); 601 else 602 m_pImpl.reset(new CWin98PreviewAdapterImpl(instance)); 603 } 604 605 //------------------------------- 606 // 607 //------------------------------- 608 609 CPreviewAdapter::~CPreviewAdapter() 610 { 611 } 612 613 //------------------------------- 614 // 615 //------------------------------- 616 617 Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats() 618 { 619 com::sun::star::uno::Sequence<sal_Int16> imgFormats(1); 620 imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP; 621 return imgFormats; 622 } 623 624 //------------------------------- 625 // 626 //------------------------------- 627 628 sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth() 629 { 630 return m_pImpl->getTargetColorDepth(); 631 } 632 633 //------------------------------- 634 // 635 //------------------------------- 636 637 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth() 638 { 639 return m_pImpl->getAvailableWidth(); 640 } 641 642 //------------------------------- 643 // 644 //------------------------------- 645 646 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight() 647 { 648 return m_pImpl->getAvailableHeight(); 649 } 650 651 //------------------------------- 652 // 653 //------------------------------- 654 655 void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage ) 656 throw (IllegalArgumentException, RuntimeException) 657 { 658 m_pImpl->setImage(aImageFormat,aImage); 659 } 660 661 //------------------------------- 662 // 663 //------------------------------- 664 665 sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState ) 666 { 667 return m_pImpl->setShowState(bShowState); 668 } 669 670 //------------------------------- 671 // 672 //------------------------------- 673 674 sal_Bool SAL_CALL CPreviewAdapter::getShowState() 675 { 676 return m_pImpl->getShowState(); 677 } 678 679 //------------------------------- 680 // 681 //------------------------------- 682 683 void SAL_CALL CPreviewAdapter::setParent(HWND parent) 684 { 685 m_pImpl->setParent(parent); 686 } 687 688 //------------------------------- 689 // 690 //------------------------------- 691 692 void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow) 693 { 694 m_pImpl->notifyParentShow(bShow); 695 } 696 697 //------------------------------- 698 // 699 //------------------------------- 700 701 void SAL_CALL CPreviewAdapter::notifyParentSizeChanged() 702 { 703 m_pImpl->notifyParentSizeChanged(); 704 } 705 706 //------------------------------- 707 // 708 //------------------------------- 709 710 void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged() 711 { 712 m_pImpl->notifyParentWindowPosChanged(); 713 } 714