merge the formfield patch from ooo-build
[ooovba.git] / fpicker / source / win32 / filepicker / previewadapter.cxx
blobde09f1fae5ff74e06fb7fd4a4f72cc73668e6880
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: previewadapter.cxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_fpicker.hxx"
34 #include <tchar.h>
35 #include "previewadapter.hxx"
37 #ifndef _COM_SUN_STAR_UI_DIALOG_FILEPREVIEWIMAGEFORMATS_HPP_
38 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
39 #endif
40 #include "dibpreview.hxx"
41 #include "../misc/WinImplHelper.hxx"
43 #include <memory>
44 #include <stdexcept>
46 //---------------------------------------------
48 //---------------------------------------------
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::lang;
53 //---------------------------------------------
54 // An impl class to hide implementation details
55 // from clients
56 //---------------------------------------------
58 class CPreviewAdapterImpl
60 public:
61 CPreviewAdapterImpl(HINSTANCE instance);
63 virtual ~CPreviewAdapterImpl();
65 virtual sal_Int32 SAL_CALL getTargetColorDepth();
67 virtual sal_Int32 SAL_CALL getAvailableWidth();
69 virtual sal_Int32 SAL_CALL getAvailableHeight();
71 virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage )
72 throw (IllegalArgumentException,RuntimeException);
74 virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState);
76 virtual sal_Bool SAL_CALL getShowState();
78 virtual void SAL_CALL setParent(HWND parent);
80 virtual HWND SAL_CALL getParent();
82 //-------------------------------------
83 // parent notification handler
84 //-------------------------------------
86 virtual void SAL_CALL notifyParentShow(sal_Bool bShow);
88 virtual void SAL_CALL notifyParentSizeChanged();
90 virtual void SAL_CALL notifyParentWindowPosChanged();
92 protected:
93 virtual void SAL_CALL calcRightMargin();
95 virtual void SAL_CALL rearrangeLayout();
97 void SAL_CALL initializeActivePreview() throw(std::runtime_error);
99 HWND SAL_CALL findFileListbox() const;
101 // member
102 protected:
103 HINSTANCE m_Instance;
104 std::auto_ptr<PreviewBase> m_Preview;
105 HWND m_FileDialog;
106 int m_RightMargin;
108 //prevent copy/assignment
109 private:
110 CPreviewAdapterImpl(const CPreviewAdapterImpl&);
111 CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&);
114 //-----------------------------------------
116 //-----------------------------------------
118 CPreviewAdapterImpl::CPreviewAdapterImpl(HINSTANCE instance) :
119 m_Instance(instance),
120 m_Preview(new PreviewBase()), // create dummy preview (NULL-Object pattern)
121 m_FileDialog(0),
122 m_RightMargin(0)
126 //-----------------------------------------
128 //-----------------------------------------
130 CPreviewAdapterImpl::~CPreviewAdapterImpl()
134 //-----------------------------------------
136 //-----------------------------------------
138 sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth()
140 return m_Preview->getTargetColorDepth();
143 //-----------------------------------------
145 //-----------------------------------------
147 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth()
149 return m_Preview->getAvailableWidth();
152 //-----------------------------------------
154 //-----------------------------------------
156 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight()
158 return m_Preview->getAvailableHeight();
161 //-----------------------------------------
163 //-----------------------------------------
165 void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage )
166 throw (IllegalArgumentException,RuntimeException)
168 m_Preview->setImage(aImageFormat,aImage);
171 //-----------------------------------------
173 //-----------------------------------------
175 sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState )
177 sal_Bool bRet = m_Preview->setShowState(bShowState);
178 rearrangeLayout();
179 return bRet;
182 //-----------------------------------------
184 //-----------------------------------------
186 sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState()
188 return m_Preview->getShowState();
191 //-----------------------------------------
193 //-----------------------------------------
195 void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent)
197 OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle");
199 m_FileDialog = parent;
200 calcRightMargin();
203 //-----------------------------------------
205 //-----------------------------------------
207 HWND SAL_CALL CPreviewAdapterImpl::getParent()
209 return m_FileDialog;
212 //-----------------------------------------
214 //-----------------------------------------
216 void SAL_CALL CPreviewAdapterImpl::calcRightMargin()
218 // Calculate the right reference margin
220 // Assumtions:
221 // 1. This method will be called before the dialog becomes
222 // visible
223 // 2. There exist a FileListbox with the id lst1 even
224 // if it is not visible like under Win2000/XP
225 // 3. Initially this FileListbox has the appropriate size
226 // to fit within the FileListbox
227 // 4. The margin between the right edge of the FileListbox
228 // and the right edge of the FileDialog will be constant
229 // even if the size of the dialog changes
231 HWND flb = GetDlgItem(m_FileDialog,lst1);
233 OSL_ENSURE(IsWindow(flb),"Filelistbox not found");
235 RECT rcFlb;
236 GetWindowRect(flb,&rcFlb);
238 RECT rcFileDlg;
239 GetWindowRect(m_FileDialog,&rcFileDlg);
241 m_RightMargin = rcFileDlg.right - rcFlb.right;
244 //-----------------------------------------
246 //-----------------------------------------
248 void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool)
252 //-----------------------------------------
254 //-----------------------------------------
256 void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged()
258 rearrangeLayout();
261 //-----------------------------------------
263 //-----------------------------------------
265 void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged()
269 //-----------------------------------------
271 //-----------------------------------------
273 void SAL_CALL CPreviewAdapterImpl::rearrangeLayout()
275 // try to get a handle to the filelistbox
276 // if there is no new-style filelistbox like
277 // in Win2000/XP there should be at least the
278 // old listbox, so we take this one
279 // lst1 - identifies the old-style filelistbox
280 // lst2 - identifies the new-style filelistbox
281 // see dlgs.h
282 HWND flb_new = findFileListbox();
284 // under Windows NT 4.0 the size of the old
285 // filelistbox will be used as reference for
286 // sizing the new filelistbox, so we have
287 // to change the size of it too
288 HWND flb_old = GetDlgItem(m_FileDialog,lst1);
290 RECT rcFlbNew;
291 GetWindowRect(flb_new,&rcFlbNew);
293 RECT rcFileDlg;
294 GetWindowRect(m_FileDialog,&rcFileDlg);
295 rcFileDlg.right -= m_RightMargin;
297 // the available area for the filelistbox should be
298 // the left edge of the filelistbox and the right
299 // edge of the OK button, we take this as reference
300 int height = rcFlbNew.bottom - rcFlbNew.top;
301 int width = rcFileDlg.right - rcFlbNew.left;
303 HWND prvwnd = m_Preview->getWindowHandle();
305 // we use GetWindowLong to ask for the visibility
306 // of the preview window because IsWindowVisible
307 // only returns true the specified window including
308 // its parent windows are visible
309 // this is not the case when we are called in response
310 // to the WM_SHOWWINDOW message, somehow the WS_VISIBLE
311 // style bit of the FileOpen dialog must be set after that
312 // message
313 LONG lStyle = GetWindowLong(prvwnd,GWL_STYLE);
314 BOOL bIsVisible = (BOOL)(lStyle & WS_VISIBLE);
316 int cx = 0;
318 if (IsWindow(prvwnd) && bIsVisible)
320 cx = width/2;
322 // resize the filelistbox to the half of the
323 // available space
324 BOOL bRet = SetWindowPos(flb_new,
325 NULL, 0, 0, cx, height,
326 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
328 bRet = SetWindowPos(flb_old,
329 NULL, 0, 0, cx, height,
330 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
332 // get the new dimensions of the filelistbox after
333 // resizing and take the right,top corner as starting
334 // point for the preview window
335 GetWindowRect(flb_new,&rcFlbNew);
336 POINT pt = { rcFlbNew.right, rcFlbNew.top };
337 ScreenToClient(m_FileDialog,&pt);
339 // resize the preview window to fit within
340 // the available space and set the window
341 // to the top of the z-order else it will
342 // be invisible
343 SetWindowPos(prvwnd,
344 HWND_TOP, pt.x, pt.y, cx, height, SWP_NOACTIVATE);
346 else
348 // resize the filelistbox to the maximum available
349 // space
350 cx = rcFileDlg.right - rcFlbNew.left;
352 // resize the old filelistbox
353 SetWindowPos(flb_old,
354 NULL, 0, 0, cx, height,
355 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
357 // resize the new filelistbox
358 SetWindowPos(flb_new,
359 NULL, 0, 0, cx, height,
360 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
364 //-----------------------------------------
366 //-----------------------------------------
368 void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error)
370 sal_Bool bShowState = m_Preview->getImaginaryShowState();
372 sal_Int16 aImgFrmt;
373 Any aImg;
374 m_Preview->getImage(aImgFrmt,aImg);
376 HWND flb = findFileListbox();
378 PreviewBase* prv = new CDIBPreview(
379 m_Instance, GetParent(flb), bShowState);
381 m_Preview.reset(prv);
383 m_Preview->setImage(aImgFrmt,aImg);
386 //-----------------------------------------
388 //-----------------------------------------
390 HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const
392 // try to get a handle to the filelistbox
393 // if there is no new-style filelistbox like
394 // in Win2000/XP there should be at least the
395 // old listbox, so we take this one
396 // lst1 - identifies the old-style filelistbox
397 // lst2 - identifies the new-style filelistbox
398 // see dlgs.h
399 HWND flb = GetDlgItem(m_FileDialog,lst2);
400 if (!IsWindow(flb))
401 flb = GetDlgItem(m_FileDialog,lst1);
403 return flb;
407 //##############################################################
410 //-----------------------------------------
411 // Special implementation for Win98
412 // because:
414 //-----------------------------------------
416 class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl
418 public:
419 CWin98PreviewAdapterImpl(HINSTANCE instance);
421 virtual void SAL_CALL notifyParentWindowPosChanged();
423 protected:
424 virtual void SAL_CALL rearrangeLayout();
426 bool isValidToolbarDimension() const;
428 private:
429 sal_Bool m_PreviewActive;
430 int m_ToolbarPosX;
431 int m_ToolbarPosY;
432 int m_ToolbarWidth;
433 int m_ToolbarHeight;
436 //--------------------------------------------
438 //--------------------------------------------
440 CWin98PreviewAdapterImpl::CWin98PreviewAdapterImpl(HINSTANCE instance) :
441 CPreviewAdapterImpl(instance),
442 m_PreviewActive(sal_False),
443 m_ToolbarPosX(0),
444 m_ToolbarPosY(0),
445 m_ToolbarWidth(0),
446 m_ToolbarHeight(0)
450 //--------------------------------------------
452 //--------------------------------------------
454 void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged()
458 // the reason for this condition is
459 // Windows 98
460 // Under Windows 98 the message WM_SHOWWINDOW
461 // will be sent only the first time the
462 // GetOpenFileName function is called within
463 // the same process
464 // so we must use another message to initialize
465 // the preview window
466 if (IsWindow(m_FileDialog) && !m_PreviewActive)
468 initializeActivePreview();
469 m_PreviewActive = sal_True;
470 rearrangeLayout();
473 if (IsWindow(m_FileDialog) && !isValidToolbarDimension())
475 RECT rcStc1;
476 GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1);
478 RECT rcCmb2;
479 GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2);
481 // Assumption:
482 // the toolbar position is only valid
483 // if the left edge is greater or equal
484 // than the right edge of the drives listbox
485 // the stc1 static text is invisible at runtime
486 // but will be used as reference for the position
487 // and dimension of the toolbar
488 if (rcStc1.left >= rcCmb2.right)
490 // important: save the upper left corner in
491 // client coordinates
492 POINT pt = {rcStc1.left,rcStc1.top};
493 ScreenToClient(m_FileDialog,&pt);
495 m_ToolbarPosX = pt.x;
496 m_ToolbarPosY = pt.y;
497 m_ToolbarWidth = rcStc1.right - rcStc1.left;
498 m_ToolbarHeight = rcStc1.bottom - rcStc1.top;
502 catch(std::runtime_error&)
507 //--------------------------------------------
509 //--------------------------------------------
511 void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout()
513 CPreviewAdapterImpl::rearrangeLayout();
515 // fix the position of the upper toolbar
516 // because the FileDialog moves all windows
517 // that are to the right of the FileListbox
518 // so if we have changed the size of the
519 // FileListbox we would run into trouble else
520 if (isValidToolbarDimension())
522 HWND hwndTlb = FindWindowEx(
523 m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL);
525 SetWindowPos(hwndTlb,
526 HWND_TOP,
527 m_ToolbarPosX,
528 m_ToolbarPosY,
529 m_ToolbarWidth,
530 m_ToolbarHeight,
531 SWP_NOACTIVATE);
535 //--------------------------------------------
537 //--------------------------------------------
539 bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const
541 return (m_ToolbarPosX > 0 &&
542 m_ToolbarPosY > 0 &&
543 m_ToolbarWidth > 0 &&
544 m_ToolbarHeight > 0);
547 //##############################################################
550 //--------------------------------------------
551 // Implementation for Windows 95/NT/ME/2000/XP
552 // because:
554 //--------------------------------------------
556 class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl
558 public:
559 CWin95NTPreviewAdapterImpl(HINSTANCE instance);
561 virtual void SAL_CALL notifyParentShow(sal_Bool bShow);
564 //--------------------------------------------
566 //--------------------------------------------
568 CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) :
569 CPreviewAdapterImpl(instance)
573 //--------------------------------------------
575 //--------------------------------------------
577 void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow)
581 if (bShow)
583 initializeActivePreview();
584 rearrangeLayout();
587 catch(std::runtime_error&)
593 //##############################################################
596 //-------------------------------
597 // ctor
598 //-------------------------------
600 CPreviewAdapter::CPreviewAdapter(HINSTANCE instance)
602 if (!IsWindows98())
603 m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance));
604 else
605 m_pImpl.reset(new CWin98PreviewAdapterImpl(instance));
608 //-------------------------------
610 //-------------------------------
612 CPreviewAdapter::~CPreviewAdapter()
616 //-------------------------------
618 //-------------------------------
620 Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats()
622 com::sun::star::uno::Sequence<sal_Int16> imgFormats(1);
623 imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP;
624 return imgFormats;
627 //-------------------------------
629 //-------------------------------
631 sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth()
633 return m_pImpl->getTargetColorDepth();
636 //-------------------------------
638 //-------------------------------
640 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth()
642 return m_pImpl->getAvailableWidth();
645 //-------------------------------
647 //-------------------------------
649 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight()
651 return m_pImpl->getAvailableHeight();
654 //-------------------------------
656 //-------------------------------
658 void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage )
659 throw (IllegalArgumentException, RuntimeException)
661 m_pImpl->setImage(aImageFormat,aImage);
664 //-------------------------------
666 //-------------------------------
668 sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState )
670 return m_pImpl->setShowState(bShowState);
673 //-------------------------------
675 //-------------------------------
677 sal_Bool SAL_CALL CPreviewAdapter::getShowState()
679 return m_pImpl->getShowState();
682 //-------------------------------
684 //-------------------------------
686 void SAL_CALL CPreviewAdapter::setParent(HWND parent)
688 m_pImpl->setParent(parent);
691 //-------------------------------
693 //-------------------------------
695 void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow)
697 m_pImpl->notifyParentShow(bShow);
700 //-------------------------------
702 //-------------------------------
704 void SAL_CALL CPreviewAdapter::notifyParentSizeChanged()
706 m_pImpl->notifyParentSizeChanged();
709 //-------------------------------
711 //-------------------------------
713 void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged()
715 m_pImpl->notifyParentWindowPosChanged();