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