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_extensions.hxx"
26
27 #include <list>
28
29 #include <cppuhelper/implbase3.hxx>
30 #include <cppuhelper/implementationentry.hxx>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <com/sun/star/document/XEventListener.hpp>
34 #include <com/sun/star/document/XEventBroadcaster.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/graphic/XGraphicProvider.hpp>
37 #include <com/sun/star/task/XJob.hpp>
38
39 #include <comphelper/processfactory.hxx>
40
41 #include <vos/mutex.hxx>
42 #include <osl/mutex.hxx>
43
44 #include <vcl/window.hxx>
45 #include <vcl/floatwin.hxx>
46 #include <vcl/timer.hxx>
47 #include <vcl/menu.hxx>
48 #include <vcl/outdev.hxx>
49 #include <vcl/msgbox.hxx>
50 #include <vcl/lineinfo.hxx>
51 #include <vcl/button.hxx>
52 #include <vcl/settings.hxx>
53 #include <vcl/svapp.hxx>
54 #include <sfx2/sfx.hrc>
55 #include "rtl/ustrbuf.hxx"
56
57 #include "updatecheckui.hrc"
58
59 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
60
61 #define MSG_ERR_NO_WEBBROWSER_FOUND (RID_SFX_APP_START + 7)
62 #define DEFAULT_MENUBAR_HEIGHT 24
63
64 #define PROPERTY_TITLE RTL_CONSTASCII_STRINGPARAM("BubbleHeading")
65 #define PROPERTY_TEXT RTL_CONSTASCII_STRINGPARAM("BubbleText")
66 #define PROPERTY_IMAGE RTL_CONSTASCII_STRINGPARAM("BubbleImageURL")
67 #define PROPERTY_SHOW_BUBBLE RTL_CONSTASCII_STRINGPARAM("BubbleVisible")
68 #define PROPERTY_CLICK_HDL RTL_CONSTASCII_STRINGPARAM("MenuClickHDL")
69 #define PROPERTY_SHOW_MENUICON RTL_CONSTASCII_STRINGPARAM("MenuIconVisible")
70
71 #define START_TIMER 1
72
73 using namespace ::com::sun::star;
74
75 //------------------------------------------------------------------------------
76
getServiceNames()77 static uno::Sequence< rtl::OUString > getServiceNames()
78 {
79 uno::Sequence< rtl::OUString > aServiceList(1);
80 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckUI");
81 return aServiceList;
82 }
83
84 //------------------------------------------------------------------------------
85
getImplementationName()86 static rtl::OUString getImplementationName()
87 {
88 return UNISTRING( "vnd.sun.UpdateCheckUI");
89 }
90
91 //------------------------------------------------------------------------------
92
93 namespace
94 {
95
96 //------------------------------------------------------------------------------
97 class BubbleWindow : public FloatingWindow
98 {
99 Point maTipPos;
100 Region maBounds;
101 Polygon maRectPoly;
102 Polygon maTriPoly;
103 XubString maBubbleTitle;
104 XubString maBubbleText;
105 Image maBubbleImage;
106 Size maMaxTextSize;
107 Rectangle maTitleRect;
108 Rectangle maTextRect;
109 long mnTipOffset;
110
111 private:
112 void RecalcTextRects();
113
114 public:
115 BubbleWindow( Window* pParent, const XubString& rTitle,
116 const XubString& rText, const Image& rImage );
117 ~BubbleWindow();
118
119 virtual void MouseButtonDown( const MouseEvent& rMEvt );
120 virtual void Paint( const Rectangle& rRect );
121 void Resize();
122 void Show( sal_Bool bVisible = sal_True, sal_uInt16 nFlags = SHOW_NOACTIVATE );
SetTipPosPixel(const Point & rTipPos)123 void SetTipPosPixel( const Point& rTipPos ) { maTipPos = rTipPos; }
124 void SetTitleAndText( const XubString& rTitle, const XubString& rText,
125 const Image& rImage );
126 };
127
128 //------------------------------------------------------------------------------
129 class UpdateCheckUI : public ::cppu::WeakImplHelper3
130 < lang::XServiceInfo, document::XEventListener, beans::XPropertySet >
131 {
132 uno::Reference< uno::XComponentContext > m_xContext;
133 uno::Reference< task::XJob > mrJob;
134 rtl::OUString maBubbleTitle;
135 rtl::OUString maBubbleText;
136 rtl::OUString maBubbleImageURL;
137 Image maBubbleImage;
138 BubbleWindow* mpBubbleWin;
139 SystemWindow* mpIconSysWin;
140 MenuBar* mpIconMBar;
141 ResMgr* mpUpdResMgr;
142 ResMgr* mpSfxResMgr;
143 Timer maWaitTimer;
144 Timer maTimeoutTimer;
145 Link maWindowEventHdl;
146 Link maApplicationEventHdl;
147 bool mbShowBubble;
148 bool mbShowMenuIcon;
149 bool mbBubbleChanged;
150 sal_uInt16 mnIconID;
151
152 private:
153 DECL_LINK( ClickHdl, sal_uInt16* );
154 DECL_LINK( HighlightHdl, MenuBar::MenuBarButtonCallbackArg* );
155 DECL_LINK( WaitTimeOutHdl, Timer* );
156 DECL_LINK( TimeOutHdl, Timer* );
157 DECL_LINK( UserEventHdl, UpdateCheckUI* );
158 DECL_LINK( WindowEventHdl, VclWindowEvent* );
159 DECL_LINK( ApplicationEventHdl, VclSimpleEvent* );
160
161 BubbleWindow* GetBubbleWindow();
162 void RemoveBubbleWindow( bool bRemoveIcon );
163 Image GetMenuBarIcon( MenuBar* pMBar );
164 void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl );
165 Image GetBubbleImage( ::rtl::OUString &rURL );
166
167 uno::Reference< document::XEventBroadcaster > getGlobalEventBroadcaster() const
168 throw (uno::RuntimeException);
169
170 public:
171 UpdateCheckUI(const uno::Reference<uno::XComponentContext>&);
172 virtual ~UpdateCheckUI();
173
174 // XServiceInfo
175 virtual rtl::OUString SAL_CALL getImplementationName()
176 throw (uno::RuntimeException);
177 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
178 throw (uno::RuntimeException);
179 virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
180 throw (uno::RuntimeException);
181
182 // XEventListener
183 virtual void SAL_CALL notifyEvent(const document::EventObject& Event)
184 throw (uno::RuntimeException);
185 virtual void SAL_CALL disposing(const lang::EventObject& Event)
186 throw (uno::RuntimeException);
187
188 //XPropertySet
189 virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(void)
190 throw ( uno::RuntimeException );
191 virtual void SAL_CALL setPropertyValue(const rtl::OUString& PropertyName, const uno::Any& aValue)
192 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
193 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException );
194 virtual uno::Any SAL_CALL getPropertyValue(const rtl::OUString& PropertyName)
195 throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
196 virtual void SAL_CALL addPropertyChangeListener(const rtl::OUString& PropertyName,
197 const uno::Reference< beans::XPropertyChangeListener > & aListener)
198 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
199 virtual void SAL_CALL removePropertyChangeListener(const rtl::OUString& PropertyName,
200 const uno::Reference< beans::XPropertyChangeListener > & aListener)
201 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
202 virtual void SAL_CALL addVetoableChangeListener(const rtl::OUString& PropertyName,
203 const uno::Reference< beans::XVetoableChangeListener > & aListener)
204 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
205 virtual void SAL_CALL removeVetoableChangeListener(const rtl::OUString& PropertyName,
206 const uno::Reference< beans::XVetoableChangeListener > & aListener)
207 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
208 };
209
210 //------------------------------------------------------------------------------
UpdateCheckUI(const uno::Reference<uno::XComponentContext> & xContext)211 UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) :
212 m_xContext(xContext)
213 , mpBubbleWin( NULL )
214 , mpIconSysWin( NULL )
215 , mpIconMBar( NULL )
216 , mbShowBubble( false )
217 , mbShowMenuIcon( false )
218 , mbBubbleChanged( false )
219 , mnIconID( 0 )
220 {
221 mpUpdResMgr = ResMgr::CreateResMgr( "updchk" );
222 mpSfxResMgr = ResMgr::CreateResMgr( "sfx" );
223
224 maBubbleImage = GetBubbleImage( maBubbleImageURL );
225
226 maWaitTimer.SetTimeout( 400 );
227 maWaitTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) );
228
229 maTimeoutTimer.SetTimeout( 10000 );
230 maTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, TimeOutHdl ) );
231
232 uno::Reference< document::XEventBroadcaster > xBroadcaster( getGlobalEventBroadcaster() );
233 xBroadcaster->addEventListener( this );
234
235 maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl );
236 maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl );
237 Application::AddEventListener( maApplicationEventHdl );
238 }
239
240 //------------------------------------------------------------------------------
~UpdateCheckUI()241 UpdateCheckUI::~UpdateCheckUI()
242 {
243 Application::RemoveEventListener( maApplicationEventHdl );
244 RemoveBubbleWindow( true );
245 delete mpUpdResMgr;
246 delete mpSfxResMgr;
247 }
248
249 //------------------------------------------------------------------------------
250 uno::Reference<document::XEventBroadcaster>
getGlobalEventBroadcaster() const251 UpdateCheckUI::getGlobalEventBroadcaster() const throw (uno::RuntimeException)
252 {
253 if( !m_xContext.is() )
254 throw uno::RuntimeException(
255 UNISTRING( "UpdateCheckUI: empty component context" ),
256 uno::Reference< uno::XInterface >() );
257
258 uno::Reference< lang::XMultiComponentFactory > xServiceManager(m_xContext->getServiceManager());
259
260 if( !xServiceManager.is() )
261 throw uno::RuntimeException(
262 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
263 uno::Reference< uno::XInterface >() );
264
265 return uno::Reference<document::XEventBroadcaster> (
266 xServiceManager->createInstanceWithContext(
267 UNISTRING( "com.sun.star.frame.GlobalEventBroadcaster" ),
268 m_xContext),
269 uno::UNO_QUERY_THROW);
270 }
271
272 //------------------------------------------------------------------------------
273 rtl::OUString SAL_CALL
getImplementationName()274 UpdateCheckUI::getImplementationName() throw (uno::RuntimeException)
275 {
276 return ::getImplementationName();
277 }
278
279 //------------------------------------------------------------------------------
280 uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames()281 UpdateCheckUI::getSupportedServiceNames() throw (uno::RuntimeException)
282 {
283 return ::getServiceNames();
284 }
285
286 //------------------------------------------------------------------------------
287 sal_Bool SAL_CALL
supportsService(rtl::OUString const & serviceName)288 UpdateCheckUI::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
289 {
290 uno::Sequence< rtl::OUString > aServiceNameList = ::getServiceNames();
291
292 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
293 if( aServiceNameList[n].equals(serviceName) )
294 return sal_True;
295
296 return sal_False;
297 }
298
299 //------------------------------------------------------------------------------
GetMenuBarIcon(MenuBar * pMBar)300 Image UpdateCheckUI::GetMenuBarIcon( MenuBar* pMBar )
301 {
302 sal_uInt32 nResID;
303 Window *pMBarWin = pMBar->GetWindow();
304 sal_uInt32 nMBarHeight = 20;
305
306 if ( pMBarWin )
307 nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight();
308
309 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) {
310 if ( nMBarHeight >= 35 )
311 nResID = RID_UPDATE_AVAILABLE_26_HC;
312 else
313 nResID = RID_UPDATE_AVAILABLE_16_HC;
314 } else {
315 if ( nMBarHeight >= 35 )
316 nResID = RID_UPDATE_AVAILABLE_26;
317 else
318 nResID = RID_UPDATE_AVAILABLE_16;
319 }
320
321 return Image( ResId( nResID, *mpUpdResMgr ) );
322 }
323
324 //------------------------------------------------------------------------------
GetBubbleImage(::rtl::OUString & rURL)325 Image UpdateCheckUI::GetBubbleImage( ::rtl::OUString &rURL )
326 {
327 Image aImage;
328
329 if ( maBubbleImageURL.getLength() != 0 )
330 {
331 uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
332
333 if( !xServiceManager.is() )
334 throw uno::RuntimeException(
335 UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
336 uno::Reference< uno::XInterface >() );
337
338 try
339 {
340 uno::Reference< graphic::XGraphicProvider > xGraphProvider(
341 xServiceManager->createInstance(
342 ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ),
343 uno::UNO_QUERY );
344 if ( xGraphProvider.is() )
345 {
346 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
347 aMediaProps[0].Name = ::rtl::OUString::createFromAscii( "URL" );
348 aMediaProps[0].Value <<= rURL;
349
350 uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
351 if ( xGraphic.is() )
352 {
353 aImage = Image( xGraphic );
354 }
355 }
356 }
357 catch( uno::Exception& )
358 {
359 }
360 }
361
362 if ( aImage.GetSizePixel().Width() == 0 )
363 aImage = InfoBox::GetStandardImage();
364
365 return aImage;
366 }
367
368 //------------------------------------------------------------------------------
AddMenuBarIcon(SystemWindow * pSysWin,bool bAddEventHdl)369 void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl )
370 {
371 if ( ! mbShowMenuIcon )
372 return;
373
374 vos::OGuard aGuard( Application::GetSolarMutex() );
375
376 MenuBar *pActiveMBar = pSysWin->GetMenuBar();
377 if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) )
378 {
379 if ( bAddEventHdl && mpIconSysWin )
380 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
381
382 RemoveBubbleWindow( true );
383
384 if ( pActiveMBar )
385 {
386 rtl::OUStringBuffer aBuf;
387 if( maBubbleTitle.getLength() )
388 aBuf.append( maBubbleTitle );
389 if( maBubbleText.getLength() )
390 {
391 if( maBubbleTitle.getLength() )
392 aBuf.appendAscii( "\n\n" );
393 aBuf.append( maBubbleText );
394 }
395
396 Image aImage = GetMenuBarIcon( pActiveMBar );
397 mnIconID = pActiveMBar->AddMenuBarButton( aImage,
398 LINK( this, UpdateCheckUI, ClickHdl ),
399 aBuf.makeStringAndClear()
400 );
401 pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID,
402 LINK( this, UpdateCheckUI, HighlightHdl ) );
403 }
404 mpIconMBar = pActiveMBar;
405 mpIconSysWin = pSysWin;
406 if ( bAddEventHdl && mpIconSysWin )
407 mpIconSysWin->AddEventListener( maWindowEventHdl );
408 }
409
410 if ( mbShowBubble && pActiveMBar )
411 {
412 mpBubbleWin = GetBubbleWindow();
413 if ( mpBubbleWin )
414 {
415 mpBubbleWin->Show( sal_True );
416 maTimeoutTimer.Start();
417 }
418 mbShowBubble = false;
419 }
420 }
421
422 //------------------------------------------------------------------------------
notifyEvent(const document::EventObject & rEvent)423 void SAL_CALL UpdateCheckUI::notifyEvent(const document::EventObject& rEvent)
424 throw (uno::RuntimeException)
425 {
426 vos::OGuard aGuard( Application::GetSolarMutex() );
427
428 if( rEvent.EventName.compareToAscii( RTL_CONSTASCII_STRINGPARAM("OnPrepareViewClosing") ) == 0 )
429 {
430 RemoveBubbleWindow( true );
431 }
432 }
433
434 //------------------------------------------------------------------------------
disposing(const lang::EventObject &)435 void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&)
436 throw (uno::RuntimeException)
437 {
438 }
439
440 //------------------------------------------------------------------------------
getPropertySetInfo(void)441 uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo(void)
442 throw ( uno::RuntimeException )
443 {
444 return NULL;
445 }
446
447 //------------------------------------------------------------------------------
setPropertyValue(const rtl::OUString & rPropertyName,const uno::Any & rValue)448 void UpdateCheckUI::setPropertyValue(const rtl::OUString& rPropertyName,
449 const uno::Any& rValue)
450 throw( beans::UnknownPropertyException, beans::PropertyVetoException,
451 lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
452 {
453 vos::OGuard aGuard( Application::GetSolarMutex() );
454
455 rtl::OUString aString;
456
457 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 ) {
458 rValue >>= aString;
459 if ( aString != maBubbleTitle ) {
460 maBubbleTitle = aString;
461 mbBubbleChanged = true;
462 }
463 }
464 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 ) {
465 rValue >>= aString;
466 if ( aString != maBubbleText ) {
467 maBubbleText = aString;
468 mbBubbleChanged = true;
469 }
470 }
471 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 ) {
472 rValue >>= aString;
473 if ( aString != maBubbleImageURL ) {
474 maBubbleImageURL = aString;
475 maBubbleImage = GetBubbleImage( maBubbleImageURL );
476 mbBubbleChanged = true;
477 }
478 }
479 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 ) {
480 rValue >>= mbShowBubble;
481 if ( mbShowBubble )
482 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
483 else if ( mpBubbleWin )
484 mpBubbleWin->Show( sal_False );
485 }
486 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 ) {
487 uno::Reference< task::XJob > aJob;
488 rValue >>= aJob;
489 if ( aJob.is() )
490 mrJob = aJob;
491 else
492 throw lang::IllegalArgumentException();
493 }
494 else if (rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0) {
495 bool bShowMenuIcon = sal_False;
496 rValue >>= bShowMenuIcon;
497 if ( bShowMenuIcon != mbShowMenuIcon )
498 {
499 mbShowMenuIcon = bShowMenuIcon;
500 if ( bShowMenuIcon )
501 Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
502 else
503 RemoveBubbleWindow( true );
504 }
505 }
506 else
507 throw beans::UnknownPropertyException();
508
509 if ( mbBubbleChanged && mpBubbleWin )
510 mpBubbleWin->Show( sal_False );
511 }
512
513 //------------------------------------------------------------------------------
getPropertyValue(const rtl::OUString & rPropertyName)514 uno::Any UpdateCheckUI::getPropertyValue(const rtl::OUString& rPropertyName)
515 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
516 {
517 vos::OGuard aGuard( Application::GetSolarMutex() );
518
519 uno::Any aRet;
520
521 if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 )
522 aRet = uno::makeAny( maBubbleTitle );
523 else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 )
524 aRet = uno::makeAny( maBubbleText );
525 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 )
526 aRet = uno::makeAny( mbShowBubble );
527 else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 )
528 aRet = uno::makeAny( maBubbleImageURL );
529 else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 )
530 aRet = uno::makeAny( mrJob );
531 else if( rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0 )
532 aRet = uno::makeAny( mbShowMenuIcon );
533 else
534 throw beans::UnknownPropertyException();
535
536 return aRet;
537 }
538
539 //------------------------------------------------------------------------------
addPropertyChangeListener(const rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)540 void UpdateCheckUI::addPropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
541 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
542 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
543 {
544 //no bound properties
545 }
546
547 //------------------------------------------------------------------------------
removePropertyChangeListener(const rtl::OUString &,const uno::Reference<beans::XPropertyChangeListener> &)548 void UpdateCheckUI::removePropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
549 const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
550 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
551 {
552 //no bound properties
553 }
554
555 //------------------------------------------------------------------------------
addVetoableChangeListener(const rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)556 void UpdateCheckUI::addVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
557 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
558 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
559 {
560 //no vetoable properties
561 }
562
563 //------------------------------------------------------------------------------
removeVetoableChangeListener(const rtl::OUString &,const uno::Reference<beans::XVetoableChangeListener> &)564 void UpdateCheckUI::removeVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
565 const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
566 throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
567 {
568 //no vetoable properties
569 }
570
571
572 //------------------------------------------------------------------------------
573 //------------------------------------------------------------------------------
574 //------------------------------------------------------------------------------
GetBubbleWindow()575 BubbleWindow * UpdateCheckUI::GetBubbleWindow()
576 {
577 if ( !mpIconSysWin )
578 return NULL;
579
580 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
581 if( aIconRect.IsEmpty() )
582 return NULL;
583
584 BubbleWindow* pBubbleWin = mpBubbleWin;
585
586 if ( !pBubbleWin ) {
587 pBubbleWin = new BubbleWindow( mpIconSysWin,
588 XubString( maBubbleTitle ),
589 XubString( maBubbleText ),
590 maBubbleImage );
591 mbBubbleChanged = false;
592 }
593 else if ( mbBubbleChanged ) {
594 pBubbleWin->SetTitleAndText( XubString( maBubbleTitle ),
595 XubString( maBubbleText ),
596 maBubbleImage );
597 mbBubbleChanged = false;
598 }
599
600 Point aWinPos = aIconRect.BottomCenter();
601
602 pBubbleWin->SetTipPosPixel( aWinPos );
603
604 return pBubbleWin;
605 }
606
607 //------------------------------------------------------------------------------
RemoveBubbleWindow(bool bRemoveIcon)608 void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon )
609 {
610 vos::OGuard aGuard( Application::GetSolarMutex() );
611
612 maWaitTimer.Stop();
613 maTimeoutTimer.Stop();
614
615 if ( mpBubbleWin )
616 {
617 delete mpBubbleWin;
618 mpBubbleWin = NULL;
619 }
620
621 if ( bRemoveIcon )
622 {
623 try {
624 if ( mpIconMBar && ( mnIconID != 0 ) )
625 {
626 mpIconMBar->RemoveMenuBarButton( mnIconID );
627 mpIconMBar = NULL;
628 mnIconID = 0;
629 }
630 }
631 catch ( ... ) {
632 mpIconMBar = NULL;
633 mnIconID = 0;
634 }
635
636 mpIconSysWin = NULL;
637 }
638 }
639
640 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,ClickHdl,sal_uInt16 *,EMPTYARG)641 IMPL_LINK( UpdateCheckUI, ClickHdl, sal_uInt16*, EMPTYARG )
642 {
643 vos::OGuard aGuard( Application::GetSolarMutex() );
644
645 maWaitTimer.Stop();
646 if ( mpBubbleWin )
647 mpBubbleWin->Show( sal_False );
648
649 if ( mrJob.is() )
650 {
651 try {
652 uno::Sequence<beans::NamedValue> aEmpty;
653 mrJob->execute( aEmpty );
654 }
655 catch(const uno::Exception&) {
656 ErrorBox( NULL, ResId( MSG_ERR_NO_WEBBROWSER_FOUND, *mpSfxResMgr )).Execute();
657 }
658 }
659
660 return 0;
661 }
662
663 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,HighlightHdl,MenuBar::MenuBarButtonCallbackArg *,pData)664 IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg*, pData )
665 {
666 if ( pData->bHighlight )
667 maWaitTimer.Start();
668 else
669 RemoveBubbleWindow( false );
670
671 return 0;
672 }
673
674 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,WaitTimeOutHdl,Timer *,EMPTYARG)675 IMPL_LINK( UpdateCheckUI, WaitTimeOutHdl, Timer*, EMPTYARG )
676 {
677 vos::OGuard aGuard( Application::GetSolarMutex() );
678
679 mpBubbleWin = GetBubbleWindow();
680
681 if ( mpBubbleWin )
682 {
683 mpBubbleWin->Show();
684 }
685
686 return 0;
687 }
688
689 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,TimeOutHdl,Timer *,EMPTYARG)690 IMPL_LINK( UpdateCheckUI, TimeOutHdl, Timer*, EMPTYARG )
691 {
692 RemoveBubbleWindow( false );
693
694 return 0;
695 }
696
697 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,UserEventHdl,UpdateCheckUI *,EMPTYARG)698 IMPL_LINK( UpdateCheckUI, UserEventHdl, UpdateCheckUI*, EMPTYARG )
699 {
700 vos::OGuard aGuard( Application::GetSolarMutex() );
701
702 Window *pTopWin = Application::GetFirstTopLevelWindow();
703 Window *pActiveWin = Application::GetActiveTopWindow();
704 SystemWindow *pActiveSysWin = NULL;
705
706 Window *pBubbleWin = NULL;
707 if ( mpBubbleWin )
708 pBubbleWin = mpBubbleWin;
709
710 if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() )
711 pActiveSysWin = pActiveWin->GetSystemWindow();
712
713 if ( pActiveWin == pBubbleWin )
714 pActiveSysWin = NULL;
715
716 while ( !pActiveSysWin && pTopWin )
717 {
718 if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() )
719 pActiveSysWin = pTopWin->GetSystemWindow();
720 if ( !pActiveSysWin )
721 pTopWin = Application::GetNextTopLevelWindow( pTopWin );
722 }
723
724 if ( pActiveSysWin )
725 AddMenuBarIcon( pActiveSysWin, true );
726
727 return 0;
728 }
729
730 // -----------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,WindowEventHdl,VclWindowEvent *,pEvent)731 IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent*, pEvent )
732 {
733 sal_uLong nEventID = pEvent->GetId();
734
735 if ( VCLEVENT_OBJECT_DYING == nEventID )
736 {
737 vos::OGuard aGuard( Application::GetSolarMutex() );
738 if ( mpIconSysWin == pEvent->GetWindow() )
739 {
740 mpIconSysWin->RemoveEventListener( maWindowEventHdl );
741 RemoveBubbleWindow( true );
742 }
743 }
744 else if ( VCLEVENT_WINDOW_MENUBARADDED == nEventID )
745 {
746 vos::OGuard aGuard( Application::GetSolarMutex() );
747 Window *pWindow = pEvent->GetWindow();
748 if ( pWindow )
749 {
750 SystemWindow *pSysWin = pWindow->GetSystemWindow();
751 if ( pSysWin )
752 {
753 AddMenuBarIcon( pSysWin, false );
754 }
755 }
756 }
757 else if ( VCLEVENT_WINDOW_MENUBARREMOVED == nEventID )
758 {
759 vos::OGuard aGuard( Application::GetSolarMutex() );
760 MenuBar *pMBar = (MenuBar*) pEvent->GetData();
761 if ( pMBar && ( pMBar == mpIconMBar ) )
762 RemoveBubbleWindow( true );
763 }
764 else if ( ( nEventID == VCLEVENT_WINDOW_MOVE ) ||
765 ( nEventID == VCLEVENT_WINDOW_RESIZE ) )
766 {
767 vos::OGuard aGuard( Application::GetSolarMutex() );
768 if ( ( mpIconSysWin == pEvent->GetWindow() ) &&
769 ( mpBubbleWin != NULL ) && ( mpIconMBar != NULL ) )
770 {
771 Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
772 Point aWinPos = aIconRect.BottomCenter();
773 mpBubbleWin->SetTipPosPixel( aWinPos );
774 if ( mpBubbleWin->IsVisible() )
775 mpBubbleWin->Show(); // This will recalc the screen position of the bubble
776 }
777 }
778
779 return 0;
780 }
781
782 //------------------------------------------------------------------------------
IMPL_LINK(UpdateCheckUI,ApplicationEventHdl,VclSimpleEvent *,pEvent)783 IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent *, pEvent)
784 {
785 switch (pEvent->GetId())
786 {
787 case VCLEVENT_WINDOW_SHOW:
788 case VCLEVENT_WINDOW_ACTIVATE:
789 case VCLEVENT_WINDOW_GETFOCUS: {
790 vos::OGuard aGuard( Application::GetSolarMutex() );
791
792 Window *pWindow = static_cast< VclWindowEvent * >(pEvent)->GetWindow();
793 if ( pWindow && pWindow->IsTopWindow() )
794 {
795 SystemWindow *pSysWin = pWindow->GetSystemWindow();
796 MenuBar *pMBar = pSysWin->GetMenuBar();
797 if ( pSysWin && pMBar )
798 {
799 AddMenuBarIcon( pSysWin, true );
800 }
801 }
802 break;
803 }
804 }
805 return 0;
806 }
807 //------------------------------------------------------------------------------
808 //------------------------------------------------------------------------------
809 //------------------------------------------------------------------------------
810
811 #define TIP_HEIGHT 15
812 #define TIP_WIDTH 7
813 #define TIP_RIGHT_OFFSET 18
814 #define BUBBLE_BORDER 10
815 #define TEXT_MAX_WIDTH 300
816 #define TEXT_MAX_HEIGHT 200
817 #define INITIAL_SHOW_TIME 10000
818
819 //------------------------------------------------------------------------------
BubbleWindow(Window * pParent,const XubString & rTitle,const XubString & rText,const Image & rImage)820 BubbleWindow::BubbleWindow( Window* pParent, const XubString& rTitle,
821 const XubString& rText, const Image& rImage )
822 : FloatingWindow( pParent, WB_SYSTEMWINDOW
823 | WB_OWNERDRAWDECORATION
824 | WB_NOBORDER
825 )
826 , maBubbleTitle( rTitle )
827 , maBubbleText( rText )
828 , maBubbleImage( rImage )
829 , maMaxTextSize( TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT )
830 , mnTipOffset( 0 )
831 {
832 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
833 }
834
835 //------------------------------------------------------------------------------
~BubbleWindow()836 BubbleWindow::~BubbleWindow()
837 {
838 }
839
840 //------------------------------------------------------------------------------
Resize()841 void BubbleWindow::Resize()
842 {
843 vos::OGuard aGuard( Application::GetSolarMutex() );
844
845 FloatingWindow::Resize();
846
847 Size aSize = GetSizePixel();
848
849 if ( ( aSize.Height() < 20 ) || ( aSize.Width() < 60 ) )
850 return;
851
852 Rectangle aRect( 0, TIP_HEIGHT, aSize.Width(), aSize.Height() - TIP_HEIGHT );
853 maRectPoly = Polygon( aRect, 6, 6 );
854 Region aRegion( maRectPoly );
855 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
856
857 Point aPointArr[4];
858 aPointArr[0] = Point( nTipOffset, TIP_HEIGHT );
859 aPointArr[1] = Point( nTipOffset, 0 );
860 aPointArr[2] = Point( nTipOffset + TIP_WIDTH , TIP_HEIGHT );
861 aPointArr[3] = Point( nTipOffset, TIP_HEIGHT );
862 maTriPoly = Polygon( 4, aPointArr );
863 Region aTriRegion( maTriPoly );
864
865 aRegion.Union( aTriRegion);
866 maBounds = aRegion;
867
868 SetWindowRegionPixel( maBounds );
869 }
870
871 //------------------------------------------------------------------------------
SetTitleAndText(const XubString & rTitle,const XubString & rText,const Image & rImage)872 void BubbleWindow::SetTitleAndText( const XubString& rTitle,
873 const XubString& rText,
874 const Image& rImage )
875 {
876 maBubbleTitle = rTitle;
877 maBubbleText = rText;
878 maBubbleImage = rImage;
879
880 Resize();
881 }
882
883 //------------------------------------------------------------------------------
Paint(const Rectangle &)884 void BubbleWindow::Paint( const Rectangle& )
885 {
886 vos::OGuard aGuard( Application::GetSolarMutex() );
887
888 LineInfo aThickLine( LINE_SOLID, 2 );
889
890 DrawPolyLine( maRectPoly, aThickLine );
891 DrawPolyLine( maTriPoly );
892
893 Color aOldLine = GetLineColor();
894 Size aSize = GetSizePixel();
895 long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
896
897 SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
898 DrawLine( Point( nTipOffset+2, TIP_HEIGHT ),
899 Point( nTipOffset + TIP_WIDTH -1 , TIP_HEIGHT ),
900 aThickLine );
901 SetLineColor( aOldLine );
902
903 //Image aImage = InfoBox::GetStandardImage();
904 Size aImgSize = maBubbleImage.GetSizePixel();
905
906 DrawImage( Point( BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT ), maBubbleImage );
907
908 Font aOldFont = GetFont();
909 Font aBoldFont = aOldFont;
910 aBoldFont.SetWeight( WEIGHT_BOLD );
911
912 SetFont( aBoldFont );
913 Rectangle aTitleRect = maTitleRect;
914 aTitleRect.Move( aImgSize.Width(), 0 );
915 DrawText( aTitleRect, maBubbleTitle, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
916
917 SetFont( aOldFont );
918 Rectangle aTextRect = maTextRect;
919 aTextRect.Move( aImgSize.Width(), 0 );
920 DrawText( aTextRect, maBubbleText, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
921 }
922
923 //------------------------------------------------------------------------------
MouseButtonDown(const MouseEvent &)924 void BubbleWindow::MouseButtonDown( const MouseEvent& )
925 {
926 Show( sal_False );
927 }
928
929 //------------------------------------------------------------------------------
Show(sal_Bool bVisible,sal_uInt16 nFlags)930 void BubbleWindow::Show( sal_Bool bVisible, sal_uInt16 nFlags )
931 {
932 vos::OGuard aGuard( Application::GetSolarMutex() );
933
934 if ( !bVisible )
935 {
936 FloatingWindow::Show( bVisible );
937 return;
938 }
939
940 // don't show bubbles without a text
941 if ( ( maBubbleTitle.Len() == 0 ) && ( maBubbleText.Len() == 0 ) )
942 return;
943
944 Size aWindowSize = GetSizePixel();
945
946 // Image aImage = InfoBox::GetStandardImage();
947 Size aImgSize = maBubbleImage.GetSizePixel();
948
949 RecalcTextRects();
950
951 aWindowSize.setHeight( maTitleRect.GetHeight() * 7 / 4+ maTextRect.GetHeight() +
952 3 * BUBBLE_BORDER + TIP_HEIGHT );
953
954 if ( maTitleRect.GetWidth() > maTextRect.GetWidth() )
955 aWindowSize.setWidth( maTitleRect.GetWidth() );
956 else
957 aWindowSize.setWidth( maTextRect.GetWidth() );
958
959 aWindowSize.setWidth( aWindowSize.Width() + 3 * BUBBLE_BORDER + aImgSize.Width() );
960
961 if ( aWindowSize.Height() < aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER )
962 aWindowSize.setHeight( aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER );
963
964 Point aPos;
965 aPos.X() = maTipPos.X() - aWindowSize.Width() + TIP_RIGHT_OFFSET;
966 aPos.Y() = maTipPos.Y();
967 Point aScreenPos = GetParent()->OutputToAbsoluteScreenPixel( aPos );
968 if ( aScreenPos.X() < 0 )
969 {
970 mnTipOffset = aScreenPos.X();
971 aPos.X() -= mnTipOffset;
972 }
973 SetPosSizePixel( aPos, aWindowSize );
974
975 FloatingWindow::Show( bVisible, nFlags );
976 }
977
978 //------------------------------------------------------------------------------
RecalcTextRects()979 void BubbleWindow::RecalcTextRects()
980 {
981 Size aTotalSize;
982 sal_Bool bFinished = sal_False;
983 Font aOldFont = GetFont();
984 Font aBoldFont = aOldFont;
985
986 aBoldFont.SetWeight( WEIGHT_BOLD );
987
988 while ( !bFinished )
989 {
990 SetFont( aBoldFont );
991
992 maTitleRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
993 maBubbleTitle,
994 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
995
996 SetFont( aOldFont );
997 maTextRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
998 maBubbleText,
999 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
1000
1001 if ( maTextRect.GetHeight() < 10 )
1002 maTextRect.setHeight( 10 );
1003
1004 aTotalSize.setHeight( maTitleRect.GetHeight() +
1005 aBoldFont.GetHeight() * 3 / 4 +
1006 maTextRect.GetHeight() +
1007 3 * BUBBLE_BORDER + TIP_HEIGHT );
1008 if ( aTotalSize.Height() > maMaxTextSize.Height() )
1009 {
1010 maMaxTextSize.Width() = maMaxTextSize.Width() * 3 / 2;
1011 maMaxTextSize.Height() = maMaxTextSize.Height() * 3 / 2;
1012 }
1013 else
1014 bFinished = sal_True;
1015 }
1016 maTitleRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT );
1017 maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetHeight() * 3 / 4 );
1018 }
1019 //------------------------------------------------------------------------------
1020 //------------------------------------------------------------------------------
1021 //------------------------------------------------------------------------------
1022
1023 } // anonymous namespace
1024
1025 //------------------------------------------------------------------------------
1026
1027 static uno::Reference<uno::XInterface> SAL_CALL
createInstance(const uno::Reference<uno::XComponentContext> & xContext)1028 createInstance(const uno::Reference<uno::XComponentContext>& xContext)
1029 {
1030 return *new UpdateCheckUI(xContext);
1031 }
1032
1033 //------------------------------------------------------------------------------
1034
1035 static const cppu::ImplementationEntry kImplementations_entries[] =
1036 {
1037 {
1038 createInstance,
1039 getImplementationName,
1040 getServiceNames,
1041 cppu::createSingleComponentFactory,
1042 NULL,
1043 0
1044 },
1045 { NULL, NULL, NULL, NULL, NULL, 0 }
1046 } ;
1047
1048 //------------------------------------------------------------------------------
1049
1050 extern "C" void SAL_CALL
component_getImplementationEnvironment(const sal_Char ** aEnvTypeName,uno_Environment **)1051 component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
1052 {
1053 *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
1054 }
1055
1056 //------------------------------------------------------------------------------
1057
1058 extern "C" void *
component_getFactory(const sal_Char * pszImplementationName,void * pServiceManager,void * pRegistryKey)1059 component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
1060 {
1061 return cppu::component_getFactoryHelper(
1062 pszImplementationName,
1063 pServiceManager,
1064 pRegistryKey,
1065 kImplementations_entries) ;
1066 }
1067
1068