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