| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_fpicker.hxx" |
| |
| #include <tchar.h> |
| #include "previewadapter.hxx" |
| |
| #ifndef _COM_SUN_STAR_UI_DIALOG_FILEPREVIEWIMAGEFORMATS_HPP_ |
| #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> |
| #endif |
| #include "dibpreview.hxx" |
| #include "../misc/WinImplHelper.hxx" |
| |
| #include <memory> |
| #include <stdexcept> |
| |
| //--------------------------------------------- |
| // |
| //--------------------------------------------- |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::lang; |
| |
| //--------------------------------------------- |
| // An impl class to hide implementation details |
| // from clients |
| //--------------------------------------------- |
| |
| class CPreviewAdapterImpl |
| { |
| public: |
| CPreviewAdapterImpl(HINSTANCE instance); |
| |
| virtual ~CPreviewAdapterImpl(); |
| |
| virtual sal_Int32 SAL_CALL getTargetColorDepth(); |
| |
| virtual sal_Int32 SAL_CALL getAvailableWidth(); |
| |
| virtual sal_Int32 SAL_CALL getAvailableHeight(); |
| |
| virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage ) |
| throw (IllegalArgumentException,RuntimeException); |
| |
| virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState); |
| |
| virtual sal_Bool SAL_CALL getShowState(); |
| |
| virtual void SAL_CALL setParent(HWND parent); |
| |
| virtual HWND SAL_CALL getParent(); |
| |
| //------------------------------------- |
| // parent notification handler |
| //------------------------------------- |
| |
| virtual void SAL_CALL notifyParentShow(sal_Bool bShow); |
| |
| virtual void SAL_CALL notifyParentSizeChanged(); |
| |
| virtual void SAL_CALL notifyParentWindowPosChanged(); |
| |
| protected: |
| virtual void SAL_CALL calcRightMargin(); |
| |
| virtual void SAL_CALL rearrangeLayout(); |
| |
| void SAL_CALL initializeActivePreview() throw(std::runtime_error); |
| |
| HWND SAL_CALL findFileListbox() const; |
| |
| // member |
| protected: |
| HINSTANCE m_Instance; |
| std::auto_ptr<PreviewBase> m_Preview; |
| HWND m_FileDialog; |
| int m_RightMargin; |
| |
| //prevent copy/assignment |
| private: |
| CPreviewAdapterImpl(const CPreviewAdapterImpl&); |
| CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&); |
| }; |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| CPreviewAdapterImpl::CPreviewAdapterImpl(HINSTANCE instance) : |
| m_Instance(instance), |
| m_Preview(new PreviewBase()), // create dummy preview (NULL-Object pattern) |
| m_FileDialog(0), |
| m_RightMargin(0) |
| { |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| CPreviewAdapterImpl::~CPreviewAdapterImpl() |
| { |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth() |
| { |
| return m_Preview->getTargetColorDepth(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth() |
| { |
| return m_Preview->getAvailableWidth(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight() |
| { |
| return m_Preview->getAvailableHeight(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage ) |
| throw (IllegalArgumentException,RuntimeException) |
| { |
| m_Preview->setImage(aImageFormat,aImage); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState ) |
| { |
| sal_Bool bRet = m_Preview->setShowState(bShowState); |
| rearrangeLayout(); |
| return bRet; |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState() |
| { |
| return m_Preview->getShowState(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent) |
| { |
| OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle"); |
| |
| m_FileDialog = parent; |
| calcRightMargin(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| HWND SAL_CALL CPreviewAdapterImpl::getParent() |
| { |
| return m_FileDialog; |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::calcRightMargin() |
| { |
| // Calculate the right reference margin |
| // |
| // Assumtions: |
| // 1. This method will be called before the dialog becomes |
| // visible |
| // 2. There exist a FileListbox with the id lst1 even |
| // if it is not visible like under Win2000/XP |
| // 3. Initially this FileListbox has the appropriate size |
| // to fit within the FileListbox |
| // 4. The margin between the right edge of the FileListbox |
| // and the right edge of the FileDialog will be constant |
| // even if the size of the dialog changes |
| |
| HWND flb = GetDlgItem(m_FileDialog,lst1); |
| |
| OSL_ENSURE(IsWindow(flb),"Filelistbox not found"); |
| |
| RECT rcFlb; |
| GetWindowRect(flb,&rcFlb); |
| |
| RECT rcFileDlg; |
| GetWindowRect(m_FileDialog,&rcFileDlg); |
| |
| m_RightMargin = rcFileDlg.right - rcFlb.right; |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool) |
| { |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged() |
| { |
| rearrangeLayout(); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged() |
| { |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::rearrangeLayout() |
| { |
| // try to get a handle to the filelistbox |
| // if there is no new-style filelistbox like |
| // in Win2000/XP there should be at least the |
| // old listbox, so we take this one |
| // lst1 - identifies the old-style filelistbox |
| // lst2 - identifies the new-style filelistbox |
| // see dlgs.h |
| HWND flb_new = findFileListbox(); |
| |
| // under Windows NT 4.0 the size of the old |
| // filelistbox will be used as reference for |
| // sizing the new filelistbox, so we have |
| // to change the size of it too |
| HWND flb_old = GetDlgItem(m_FileDialog,lst1); |
| |
| RECT rcFlbNew; |
| GetWindowRect(flb_new,&rcFlbNew); |
| |
| RECT rcFileDlg; |
| GetWindowRect(m_FileDialog,&rcFileDlg); |
| rcFileDlg.right -= m_RightMargin; |
| |
| // the available area for the filelistbox should be |
| // the left edge of the filelistbox and the right |
| // edge of the OK button, we take this as reference |
| int height = rcFlbNew.bottom - rcFlbNew.top; |
| int width = rcFileDlg.right - rcFlbNew.left; |
| |
| HWND prvwnd = m_Preview->getWindowHandle(); |
| |
| // we use GetWindowLong to ask for the visibility |
| // of the preview window because IsWindowVisible |
| // only returns true the specified window including |
| // its parent windows are visible |
| // this is not the case when we are called in response |
| // to the WM_SHOWWINDOW message, somehow the WS_VISIBLE |
| // style bit of the FileOpen dialog must be set after that |
| // message |
| LONG lStyle = GetWindowLong(prvwnd,GWL_STYLE); |
| bool bIsVisible = ((lStyle & WS_VISIBLE) != 0); |
| |
| int cx = 0; |
| |
| if (IsWindow(prvwnd) && bIsVisible) |
| { |
| cx = width/2; |
| |
| // resize the filelistbox to the half of the |
| // available space |
| bool bRet = SetWindowPos(flb_new, |
| NULL, 0, 0, cx, height, |
| SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); |
| |
| bRet = SetWindowPos(flb_old, |
| NULL, 0, 0, cx, height, |
| SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); |
| |
| // get the new dimensions of the filelistbox after |
| // resizing and take the right,top corner as starting |
| // point for the preview window |
| GetWindowRect(flb_new,&rcFlbNew); |
| POINT pt = { rcFlbNew.right, rcFlbNew.top }; |
| ScreenToClient(m_FileDialog,&pt); |
| |
| // resize the preview window to fit within |
| // the available space and set the window |
| // to the top of the z-order else it will |
| // be invisible |
| SetWindowPos(prvwnd, |
| HWND_TOP, pt.x, pt.y, cx, height, SWP_NOACTIVATE); |
| } |
| else |
| { |
| // resize the filelistbox to the maximum available |
| // space |
| cx = rcFileDlg.right - rcFlbNew.left; |
| |
| // resize the old filelistbox |
| SetWindowPos(flb_old, |
| NULL, 0, 0, cx, height, |
| SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); |
| |
| // resize the new filelistbox |
| SetWindowPos(flb_new, |
| NULL, 0, 0, cx, height, |
| SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); |
| } |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error) |
| { |
| sal_Bool bShowState = m_Preview->getImaginaryShowState(); |
| |
| sal_Int16 aImgFrmt; |
| Any aImg; |
| m_Preview->getImage(aImgFrmt,aImg); |
| |
| HWND flb = findFileListbox(); |
| |
| PreviewBase* prv = new CDIBPreview( |
| m_Instance, GetParent(flb), bShowState); |
| |
| m_Preview.reset(prv); |
| |
| m_Preview->setImage(aImgFrmt,aImg); |
| } |
| |
| //----------------------------------------- |
| // |
| //----------------------------------------- |
| |
| HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const |
| { |
| // try to get a handle to the filelistbox |
| // if there is no new-style filelistbox like |
| // in Win2000/XP there should be at least the |
| // old listbox, so we take this one |
| // lst1 - identifies the old-style filelistbox |
| // lst2 - identifies the new-style filelistbox |
| // see dlgs.h |
| HWND flb = GetDlgItem(m_FileDialog,lst2); |
| if (!IsWindow(flb)) |
| flb = GetDlgItem(m_FileDialog,lst1); |
| |
| return flb; |
| } |
| |
| |
| //############################################################## |
| |
| |
| //----------------------------------------- |
| // Special implementation for Win98 |
| // because: |
| // |
| //----------------------------------------- |
| |
| class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl |
| { |
| public: |
| CWin98PreviewAdapterImpl(HINSTANCE instance); |
| |
| virtual void SAL_CALL notifyParentWindowPosChanged(); |
| |
| protected: |
| virtual void SAL_CALL rearrangeLayout(); |
| |
| bool isValidToolbarDimension() const; |
| |
| private: |
| sal_Bool m_PreviewActive; |
| int m_ToolbarPosX; |
| int m_ToolbarPosY; |
| int m_ToolbarWidth; |
| int m_ToolbarHeight; |
| }; |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| CWin98PreviewAdapterImpl::CWin98PreviewAdapterImpl(HINSTANCE instance) : |
| CPreviewAdapterImpl(instance), |
| m_PreviewActive(sal_False), |
| m_ToolbarPosX(0), |
| m_ToolbarPosY(0), |
| m_ToolbarWidth(0), |
| m_ToolbarHeight(0) |
| { |
| } |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged() |
| { |
| try |
| { |
| // the reason for this condition is |
| // Windows 98 |
| // Under Windows 98 the message WM_SHOWWINDOW |
| // will be sent only the first time the |
| // GetOpenFileName function is called within |
| // the same process |
| // so we must use another message to initialize |
| // the preview window |
| if (IsWindow(m_FileDialog) && !m_PreviewActive) |
| { |
| initializeActivePreview(); |
| m_PreviewActive = sal_True; |
| rearrangeLayout(); |
| } |
| |
| if (IsWindow(m_FileDialog) && !isValidToolbarDimension()) |
| { |
| RECT rcStc1; |
| GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1); |
| |
| RECT rcCmb2; |
| GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2); |
| |
| // Assumption: |
| // the toolbar position is only valid |
| // if the left edge is greater or equal |
| // than the right edge of the drives listbox |
| // the stc1 static text is invisible at runtime |
| // but will be used as reference for the position |
| // and dimension of the toolbar |
| if (rcStc1.left >= rcCmb2.right) |
| { |
| // important: save the upper left corner in |
| // client coordinates |
| POINT pt = {rcStc1.left,rcStc1.top}; |
| ScreenToClient(m_FileDialog,&pt); |
| |
| m_ToolbarPosX = pt.x; |
| m_ToolbarPosY = pt.y; |
| m_ToolbarWidth = rcStc1.right - rcStc1.left; |
| m_ToolbarHeight = rcStc1.bottom - rcStc1.top; |
| } |
| } |
| } |
| catch(std::runtime_error&) |
| { |
| } |
| } |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout() |
| { |
| CPreviewAdapterImpl::rearrangeLayout(); |
| |
| // fix the position of the upper toolbar |
| // because the FileDialog moves all windows |
| // that are to the right of the FileListbox |
| // so if we have changed the size of the |
| // FileListbox we would run into trouble else |
| if (isValidToolbarDimension()) |
| { |
| HWND hwndTlb = FindWindowEx( |
| m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL); |
| |
| SetWindowPos(hwndTlb, |
| HWND_TOP, |
| m_ToolbarPosX, |
| m_ToolbarPosY, |
| m_ToolbarWidth, |
| m_ToolbarHeight, |
| SWP_NOACTIVATE); |
| } |
| } |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const |
| { |
| return (m_ToolbarPosX > 0 && |
| m_ToolbarPosY > 0 && |
| m_ToolbarWidth > 0 && |
| m_ToolbarHeight > 0); |
| } |
| |
| //############################################################## |
| |
| |
| //-------------------------------------------- |
| // Implementation for Windows 95/NT/ME/2000/XP |
| // because: |
| // |
| //-------------------------------------------- |
| |
| class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl |
| { |
| public: |
| CWin95NTPreviewAdapterImpl(HINSTANCE instance); |
| |
| virtual void SAL_CALL notifyParentShow(sal_Bool bShow); |
| }; |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) : |
| CPreviewAdapterImpl(instance) |
| { |
| } |
| |
| //-------------------------------------------- |
| // |
| //-------------------------------------------- |
| |
| void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow) |
| { |
| try |
| { |
| if (bShow) |
| { |
| initializeActivePreview(); |
| rearrangeLayout(); |
| } |
| } |
| catch(std::runtime_error&) |
| { |
| } |
| } |
| |
| |
| //############################################################## |
| |
| |
| //------------------------------- |
| // ctor |
| //------------------------------- |
| |
| CPreviewAdapter::CPreviewAdapter(HINSTANCE instance) |
| { |
| if (!IsWindows98()) |
| m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance)); |
| else |
| m_pImpl.reset(new CWin98PreviewAdapterImpl(instance)); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| CPreviewAdapter::~CPreviewAdapter() |
| { |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats() |
| { |
| com::sun::star::uno::Sequence<sal_Int16> imgFormats(1); |
| imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP; |
| return imgFormats; |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth() |
| { |
| return m_pImpl->getTargetColorDepth(); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth() |
| { |
| return m_pImpl->getAvailableWidth(); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight() |
| { |
| return m_pImpl->getAvailableHeight(); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage ) |
| throw (IllegalArgumentException, RuntimeException) |
| { |
| m_pImpl->setImage(aImageFormat,aImage); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState ) |
| { |
| return m_pImpl->setShowState(bShowState); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| sal_Bool SAL_CALL CPreviewAdapter::getShowState() |
| { |
| return m_pImpl->getShowState(); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| void SAL_CALL CPreviewAdapter::setParent(HWND parent) |
| { |
| m_pImpl->setParent(parent); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow) |
| { |
| m_pImpl->notifyParentShow(bShow); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| void SAL_CALL CPreviewAdapter::notifyParentSizeChanged() |
| { |
| m_pImpl->notifyParentSizeChanged(); |
| } |
| |
| //------------------------------- |
| // |
| //------------------------------- |
| |
| void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged() |
| { |
| m_pImpl->notifyParentWindowPosChanged(); |
| } |