merged tag ooo/DEV300_m102
[LibreOffice.git] / fpicker / source / win32 / filepicker / previewadapter.cxx
bloba145c2af563d4735486708b9a22511d89c010f72
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
31 #include <tchar.h>
32 #include "previewadapter.hxx"
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"
40 #include <memory>
41 #include <stdexcept>
43 //---------------------------------------------
45 //---------------------------------------------
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::lang;
50 //---------------------------------------------
51 // An impl class to hide implementation details
52 // from clients
53 //---------------------------------------------
55 class CPreviewAdapterImpl
57 public:
58 CPreviewAdapterImpl(HINSTANCE instance);
60 virtual ~CPreviewAdapterImpl();
62 virtual sal_Int32 SAL_CALL getTargetColorDepth();
64 virtual sal_Int32 SAL_CALL getAvailableWidth();
66 virtual sal_Int32 SAL_CALL getAvailableHeight();
68 virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage )
69 throw (IllegalArgumentException,RuntimeException);
71 virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState);
73 virtual sal_Bool SAL_CALL getShowState();
75 virtual void SAL_CALL setParent(HWND parent);
77 virtual HWND SAL_CALL getParent();
79 //-------------------------------------
80 // parent notification handler
81 //-------------------------------------
83 virtual void SAL_CALL notifyParentShow(sal_Bool bShow);
85 virtual void SAL_CALL notifyParentSizeChanged();
87 virtual void SAL_CALL notifyParentWindowPosChanged();
89 protected:
90 virtual void SAL_CALL calcRightMargin();
92 virtual void SAL_CALL rearrangeLayout();
94 void SAL_CALL initializeActivePreview() throw(std::runtime_error);
96 HWND SAL_CALL findFileListbox() const;
98 // member
99 protected:
100 HINSTANCE m_Instance;
101 std::auto_ptr<PreviewBase> m_Preview;
102 HWND m_FileDialog;
103 int m_RightMargin;
105 //prevent copy/assignment
106 private:
107 CPreviewAdapterImpl(const CPreviewAdapterImpl&);
108 CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&);
111 //-----------------------------------------
113 //-----------------------------------------
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)
123 //-----------------------------------------
125 //-----------------------------------------
127 CPreviewAdapterImpl::~CPreviewAdapterImpl()
131 //-----------------------------------------
133 //-----------------------------------------
135 sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth()
137 return m_Preview->getTargetColorDepth();
140 //-----------------------------------------
142 //-----------------------------------------
144 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth()
146 return m_Preview->getAvailableWidth();
149 //-----------------------------------------
151 //-----------------------------------------
153 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight()
155 return m_Preview->getAvailableHeight();
158 //-----------------------------------------
160 //-----------------------------------------
162 void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage )
163 throw (IllegalArgumentException,RuntimeException)
165 m_Preview->setImage(aImageFormat,aImage);
168 //-----------------------------------------
170 //-----------------------------------------
172 sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState )
174 sal_Bool bRet = m_Preview->setShowState(bShowState);
175 rearrangeLayout();
176 return bRet;
179 //-----------------------------------------
181 //-----------------------------------------
183 sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState()
185 return m_Preview->getShowState();
188 //-----------------------------------------
190 //-----------------------------------------
192 void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent)
194 OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle");
196 m_FileDialog = parent;
197 calcRightMargin();
200 //-----------------------------------------
202 //-----------------------------------------
204 HWND SAL_CALL CPreviewAdapterImpl::getParent()
206 return m_FileDialog;
209 //-----------------------------------------
211 //-----------------------------------------
213 void SAL_CALL CPreviewAdapterImpl::calcRightMargin()
215 // Calculate the right reference margin
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
228 HWND flb = GetDlgItem(m_FileDialog,lst1);
230 OSL_ENSURE(IsWindow(flb),"Filelistbox not found");
232 RECT rcFlb;
233 GetWindowRect(flb,&rcFlb);
235 RECT rcFileDlg;
236 GetWindowRect(m_FileDialog,&rcFileDlg);
238 m_RightMargin = rcFileDlg.right - rcFlb.right;
241 //-----------------------------------------
243 //-----------------------------------------
245 void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool)
249 //-----------------------------------------
251 //-----------------------------------------
253 void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged()
255 rearrangeLayout();
258 //-----------------------------------------
260 //-----------------------------------------
262 void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged()
266 //-----------------------------------------
268 //-----------------------------------------
270 void SAL_CALL CPreviewAdapterImpl::rearrangeLayout()
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();
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);
287 RECT rcFlbNew;
288 GetWindowRect(flb_new,&rcFlbNew);
290 RECT rcFileDlg;
291 GetWindowRect(m_FileDialog,&rcFileDlg);
292 rcFileDlg.right -= m_RightMargin;
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;
300 HWND prvwnd = m_Preview->getWindowHandle();
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 sal_Bool bIsVisible = (sal_Bool)(lStyle & WS_VISIBLE);
313 int cx = 0;
315 if (IsWindow(prvwnd) && bIsVisible)
317 cx = width/2;
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);
325 bRet = SetWindowPos(flb_old,
326 NULL, 0, 0, cx, height,
327 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
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);
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);
343 else
345 // resize the filelistbox to the maximum available
346 // space
347 cx = rcFileDlg.right - rcFlbNew.left;
349 // resize the old filelistbox
350 SetWindowPos(flb_old,
351 NULL, 0, 0, cx, height,
352 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
354 // resize the new filelistbox
355 SetWindowPos(flb_new,
356 NULL, 0, 0, cx, height,
357 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
361 //-----------------------------------------
363 //-----------------------------------------
365 void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error)
367 sal_Bool bShowState = m_Preview->getImaginaryShowState();
369 sal_Int16 aImgFrmt;
370 Any aImg;
371 m_Preview->getImage(aImgFrmt,aImg);
373 HWND flb = findFileListbox();
375 PreviewBase* prv = new CDIBPreview(
376 m_Instance, GetParent(flb), bShowState);
378 m_Preview.reset(prv);
380 m_Preview->setImage(aImgFrmt,aImg);
383 //-----------------------------------------
385 //-----------------------------------------
387 HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const
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);
400 return flb;
404 //##############################################################
407 //-----------------------------------------
408 // Special implementation for Win98
409 // because:
411 //-----------------------------------------
413 class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl
415 public:
416 CWin98PreviewAdapterImpl(HINSTANCE instance);
418 virtual void SAL_CALL notifyParentWindowPosChanged();
420 protected:
421 virtual void SAL_CALL rearrangeLayout();
423 bool isValidToolbarDimension() const;
425 private:
426 sal_Bool m_PreviewActive;
427 int m_ToolbarPosX;
428 int m_ToolbarPosY;
429 int m_ToolbarWidth;
430 int m_ToolbarHeight;
433 //--------------------------------------------
435 //--------------------------------------------
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)
447 //--------------------------------------------
449 //--------------------------------------------
451 void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged()
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)
465 initializeActivePreview();
466 m_PreviewActive = sal_True;
467 rearrangeLayout();
470 if (IsWindow(m_FileDialog) && !isValidToolbarDimension())
472 RECT rcStc1;
473 GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1);
475 RECT rcCmb2;
476 GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2);
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)
487 // important: save the upper left corner in
488 // client coordinates
489 POINT pt = {rcStc1.left,rcStc1.top};
490 ScreenToClient(m_FileDialog,&pt);
492 m_ToolbarPosX = pt.x;
493 m_ToolbarPosY = pt.y;
494 m_ToolbarWidth = rcStc1.right - rcStc1.left;
495 m_ToolbarHeight = rcStc1.bottom - rcStc1.top;
499 catch(std::runtime_error&)
504 //--------------------------------------------
506 //--------------------------------------------
508 void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout()
510 CPreviewAdapterImpl::rearrangeLayout();
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())
519 HWND hwndTlb = FindWindowEx(
520 m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL);
522 SetWindowPos(hwndTlb,
523 HWND_TOP,
524 m_ToolbarPosX,
525 m_ToolbarPosY,
526 m_ToolbarWidth,
527 m_ToolbarHeight,
528 SWP_NOACTIVATE);
532 //--------------------------------------------
534 //--------------------------------------------
536 bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const
538 return (m_ToolbarPosX > 0 &&
539 m_ToolbarPosY > 0 &&
540 m_ToolbarWidth > 0 &&
541 m_ToolbarHeight > 0);
544 //##############################################################
547 //--------------------------------------------
548 // Implementation for Windows 95/NT/ME/2000/XP
549 // because:
551 //--------------------------------------------
553 class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl
555 public:
556 CWin95NTPreviewAdapterImpl(HINSTANCE instance);
558 virtual void SAL_CALL notifyParentShow(sal_Bool bShow);
561 //--------------------------------------------
563 //--------------------------------------------
565 CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) :
566 CPreviewAdapterImpl(instance)
570 //--------------------------------------------
572 //--------------------------------------------
574 void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow)
578 if (bShow)
580 initializeActivePreview();
581 rearrangeLayout();
584 catch(std::runtime_error&)
590 //##############################################################
593 //-------------------------------
594 // ctor
595 //-------------------------------
597 CPreviewAdapter::CPreviewAdapter(HINSTANCE instance)
599 if (!IsWindows98())
600 m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance));
601 else
602 m_pImpl.reset(new CWin98PreviewAdapterImpl(instance));
605 //-------------------------------
607 //-------------------------------
609 CPreviewAdapter::~CPreviewAdapter()
613 //-------------------------------
615 //-------------------------------
617 Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats()
619 com::sun::star::uno::Sequence<sal_Int16> imgFormats(1);
620 imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP;
621 return imgFormats;
624 //-------------------------------
626 //-------------------------------
628 sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth()
630 return m_pImpl->getTargetColorDepth();
633 //-------------------------------
635 //-------------------------------
637 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth()
639 return m_pImpl->getAvailableWidth();
642 //-------------------------------
644 //-------------------------------
646 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight()
648 return m_pImpl->getAvailableHeight();
651 //-------------------------------
653 //-------------------------------
655 void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage )
656 throw (IllegalArgumentException, RuntimeException)
658 m_pImpl->setImage(aImageFormat,aImage);
661 //-------------------------------
663 //-------------------------------
665 sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState )
667 return m_pImpl->setShowState(bShowState);
670 //-------------------------------
672 //-------------------------------
674 sal_Bool SAL_CALL CPreviewAdapter::getShowState()
676 return m_pImpl->getShowState();
679 //-------------------------------
681 //-------------------------------
683 void SAL_CALL CPreviewAdapter::setParent(HWND parent)
685 m_pImpl->setParent(parent);
688 //-------------------------------
690 //-------------------------------
692 void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow)
694 m_pImpl->notifyParentShow(bShow);
697 //-------------------------------
699 //-------------------------------
701 void SAL_CALL CPreviewAdapter::notifyParentSizeChanged()
703 m_pImpl->notifyParentSizeChanged();
706 //-------------------------------
708 //-------------------------------
710 void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged()
712 m_pImpl->notifyParentWindowPosChanged();