1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include "browserline.hxx"
31 
32 /** === begin UNO includes === **/
33 #include <com/sun/star/inspection/PropertyLineElement.hpp>
34 #include <com/sun/star/graphic/XGraphicProvider.hpp>
35 /** === end UNO includes === **/
36 
37 #include <vcl/svapp.hxx>
38 #include <tools/debug.hxx>
39 #include <tools/diagnose_ex.h>
40 #include <tools/urlobj.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
42 
43 #include <comphelper/processfactory.hxx>
44 #include <comphelper/componentcontext.hxx>
45 
46 //............................................................................
47 namespace pcr
48 {
49 //............................................................................
50 
51     /** === begin UNO using === **/
52     using ::com::sun::star::uno::Reference;
53     using ::com::sun::star::inspection::XPropertyControl;
54     using ::com::sun::star::inspection::XPropertyControlContext;
55     using ::com::sun::star::uno::UNO_QUERY_THROW;
56     using ::com::sun::star::uno::Exception;
57     using ::com::sun::star::graphic::XGraphicProvider;
58     using ::com::sun::star::uno::Sequence;
59     using ::com::sun::star::beans::PropertyValue;
60     using ::com::sun::star::graphic::XGraphic;
61     /** === end UNO using === **/
62 
63     namespace PropertyLineElement = ::com::sun::star::inspection::PropertyLineElement;
64 
65     //==================================================================
66 	//= OBrowserLine
67 	//==================================================================
68 	DBG_NAME(OBrowserLine)
69 	//------------------------------------------------------------------
70 
71 	OBrowserLine::OBrowserLine( const ::rtl::OUString& _rEntryName, Window* pParent )
72 			:m_sEntryName( _rEntryName )
73             ,m_aFtTitle(pParent)
74             ,m_pControlWindow( NULL )
75             ,m_pBrowseButton(NULL)
76             ,m_pAdditionalBrowseButton( NULL )
77             ,m_pClickListener( NULL )
78 			,m_pTheParent(pParent)
79 			,m_nNameWidth(0)
80             ,m_nEnableFlags( 0xFFFF )
81             ,m_bIndentTitle( false )
82             ,m_bReadOnly( false )
83 	{
84 		DBG_CTOR(OBrowserLine,NULL);
85 		m_aFtTitle.Show();
86 	}
87 
88     //------------------------------------------------------------------
89 	OBrowserLine::~OBrowserLine()
90 	{
91         implHideBrowseButton( true, false );
92         implHideBrowseButton( false, false );
93 
94 		DBG_DTOR(OBrowserLine,NULL);
95 	}
96 
97 	//------------------------------------------------------------------
98 	void OBrowserLine::IndentTitle( bool _bIndent )
99     {
100         if ( m_bIndentTitle != _bIndent )
101         {
102             m_bIndentTitle = _bIndent;
103 		    impl_layoutComponents();
104         }
105     }
106 
107 	//------------------------------------------------------------------
108 	void OBrowserLine::SetComponentHelpIds( const rtl::OString& _rHelpId, const rtl::OString& _sPrimaryButtonId, const rtl::OString& _sSecondaryButtonId )
109 	{
110         if ( m_pControlWindow )
111             m_pControlWindow->SetHelpId( _rHelpId );
112 
113 		if ( m_pBrowseButton )
114 		{
115             m_pBrowseButton->SetHelpId( _rHelpId );
116 			m_pBrowseButton->SetUniqueId( _sPrimaryButtonId );
117 
118             if ( m_pAdditionalBrowseButton )
119 		    {
120 			    m_pAdditionalBrowseButton->SetHelpId( _rHelpId );
121 			    m_pAdditionalBrowseButton->SetUniqueId( _sSecondaryButtonId );
122 		    }
123 		}
124 	}
125 
126 	//------------------------------------------------------------------
127     void OBrowserLine::setControl( const Reference< XPropertyControl >& _rxControl )
128 	{
129         m_xControl = _rxControl;
130         m_pControlWindow = m_xControl.is() ? VCLUnoHelper::GetWindow( _rxControl->getControlWindow() ) : NULL;
131         DBG_ASSERT( m_pControlWindow, "OBrowserLine::setControl: setting NULL controls/windows is not allowed!" );
132 
133         if ( m_pControlWindow )
134         {
135             m_pControlWindow->SetParent( m_pTheParent );
136             m_pControlWindow->Show();
137         }
138 		impl_layoutComponents();
139 	}
140 
141 	//------------------------------------------------------------------
142 	Window* OBrowserLine::GetRefWindow()
143 	{
144 		Window* pRefWindow=&m_aFtTitle;
145 
146 		if(m_pBrowseButton)
147 		{
148 			pRefWindow=(Window*)m_pBrowseButton;
149 		}
150 		else if ( m_pControlWindow )
151 		{
152 			pRefWindow = m_pControlWindow;
153 		}
154 		return pRefWindow;
155 	}
156 
157 	//------------------------------------------------------------------
158 	void OBrowserLine::SetTabOrder(Window* pRefWindow, sal_uInt16 nFlags )
159 	{
160 		m_aFtTitle.SetZOrder(pRefWindow,nFlags);
161 		if ( m_pControlWindow )
162 			m_pControlWindow->SetZOrder( (Window*)&m_aFtTitle, WINDOW_ZORDER_BEHIND );
163 
164 		if ( m_pBrowseButton )
165 			m_pBrowseButton->SetZOrder( m_pControlWindow, WINDOW_ZORDER_BEHIND );
166 
167         if ( m_pAdditionalBrowseButton )
168             m_pAdditionalBrowseButton->SetZOrder( m_pBrowseButton, WINDOW_ZORDER_BEHIND );
169 	}
170 
171 	//------------------------------------------------------------------
172 	sal_Bool OBrowserLine::GrabFocus()
173 	{
174 		sal_Bool bRes=sal_False;
175 
176 		if ( m_pControlWindow && m_pControlWindow->IsEnabled() )
177 		{
178 			m_pControlWindow->GrabFocus();
179 			bRes = sal_True;
180 		}
181 		else if ( m_pAdditionalBrowseButton && m_pAdditionalBrowseButton->IsEnabled() )
182 		{
183 			m_pAdditionalBrowseButton->GrabFocus();
184 			bRes = sal_True;
185 		}
186 		else if ( m_pBrowseButton && m_pBrowseButton->IsEnabled() )
187 		{
188 			m_pBrowseButton->GrabFocus();
189 			bRes = sal_True;
190 		}
191 		return bRes;
192 	}
193 
194 	//------------------------------------------------------------------
195 	void OBrowserLine::SetPosSizePixel( Point _rPos, Size _rSize )
196 	{
197 		m_aLinePos = _rPos;
198 		m_aOutputSize = _rSize;
199 
200         impl_layoutComponents();
201 	}
202 
203 	//------------------------------------------------------------------
204 	void OBrowserLine::Show(sal_Bool bFlag)
205 	{
206 		m_aFtTitle.Show(bFlag);
207 		if ( m_pControlWindow )
208 			m_pControlWindow->Show( bFlag );
209 		if ( m_pBrowseButton )
210 			m_pBrowseButton->Show( bFlag );
211 		if ( m_pAdditionalBrowseButton )
212 			m_pAdditionalBrowseButton->Show( bFlag );
213 	}
214 
215 	//------------------------------------------------------------------
216 	void OBrowserLine::Hide()
217 	{
218 		Show(sal_False);
219 	}
220 
221 	//------------------------------------------------------------------
222 	sal_Bool OBrowserLine::IsVisible()
223 	{
224 		return m_aFtTitle.IsVisible();
225 	}
226 
227 	//------------------------------------------------------------------
228 	void OBrowserLine::impl_layoutComponents()
229 	{
230         {
231 		    Point aTitlePos( m_aLinePos.X(), m_aLinePos.Y() + 8 );
232             Size aTitleSize( m_nNameWidth - 3, m_aOutputSize.Height() );
233 
234             if ( m_bIndentTitle )
235             {
236                 Size aIndent( m_pTheParent->LogicToPixel( Size( 8, 0 ), MAP_APPFONT ) );
237                 aTitlePos.X() += aIndent.Width();
238                 aTitleSize.Width() -= aIndent.Width();
239             }
240     		m_aFtTitle.SetPosSizePixel( aTitlePos, aTitleSize );
241         }
242 
243 		sal_Int32 nBrowseButtonSize = m_aOutputSize.Height() - 4;
244 
245 		if ( m_pControlWindow )
246 		{
247             Point aControlPos( m_aLinePos.X() + m_nNameWidth, m_aLinePos.Y() + 2 );
248 			m_pControlWindow->SetPosPixel( aControlPos );
249 
250             Size aControlSize( m_aOutputSize.Width() - 4 - m_nNameWidth - nBrowseButtonSize - 4, m_pControlWindow->GetSizePixel().Height() );
251             if ( m_pAdditionalBrowseButton )
252                 aControlSize.Width() -= nBrowseButtonSize + 4;
253 			m_pControlWindow->SetSizePixel( aControlSize );
254 		}
255 
256         if ( m_pBrowseButton )
257 		{
258             Point aButtonPos( m_aOutputSize.Width() - 4 - nBrowseButtonSize, m_aLinePos.Y() + 2 );
259             Size aButtonSize( nBrowseButtonSize, nBrowseButtonSize );
260 			m_pBrowseButton->SetPosSizePixel( aButtonPos, aButtonSize );
261 
262             if ( m_pAdditionalBrowseButton )
263 		    {
264                 aButtonPos.X() -= nBrowseButtonSize + 4;
265 			    m_pAdditionalBrowseButton->SetPosSizePixel( aButtonPos, aButtonSize );
266 		    }
267 		}
268 	}
269 
270 	//------------------------------------------------------------------
271 	void OBrowserLine::SetTitle(const XubString& _rNewTtile )
272 	{
273         if ( GetTitle() == _rNewTtile )
274             return;
275 		// #99102# --------------
276 		m_aFtTitle.SetText( _rNewTtile );
277         if ( m_pControlWindow )
278             m_pControlWindow->SetAccessibleName( _rNewTtile );
279         if ( m_pBrowseButton )
280             m_pBrowseButton->SetAccessibleName( _rNewTtile );
281 		FullFillTitleString();
282 	}
283 
284 	// #99102# ---------------------------------------------------------
285 	void OBrowserLine::FullFillTitleString()
286 	{
287 		if( m_pTheParent )
288 		{
289 			String aText = m_aFtTitle.GetText();
290 
291 			while( m_pTheParent->GetTextWidth( aText ) < m_nNameWidth )
292 		                aText.AppendAscii("...........");
293 
294 			// for Issue 69452
295 			if (Application::GetSettings().GetLayoutRTL())
296 			{
297 				sal_Unicode cRTL_mark = 0x200F;
298 				aText.Append(cRTL_mark);
299 			}
300 
301 			m_aFtTitle.SetText(aText);
302 		}
303 	}
304 
305 	//------------------------------------------------------------------
306 	XubString OBrowserLine::GetTitle() const
307 	{
308         String sDisplayName = m_aFtTitle.GetText();
309 
310 	// for Issue 69452
311 	if (Application::GetSettings().GetLayoutRTL())
312 	{
313 		sal_Unicode cRTL_mark = 0x200F;
314 		sDisplayName.EraseTrailingChars(cRTL_mark);
315 	}
316 
317         sDisplayName.EraseTrailingChars( '.' );
318 
319         return sDisplayName;
320 	}
321 
322     //------------------------------------------------------------------
323     void OBrowserLine::SetReadOnly( bool _bReadOnly )
324     {
325         if ( m_bReadOnly != _bReadOnly )
326         {
327             m_bReadOnly = _bReadOnly;
328             implUpdateEnabledDisabled();
329         }
330     }
331 
332     //------------------------------------------------------------------
333     namespace
334     {
335         void implSetBitIfAffected( sal_uInt16& _nEnabledBits, sal_Int16 _nAffectedMask, sal_Int16 _nTestBit, bool _bSet )
336         {
337             if ( _nAffectedMask & _nTestBit )
338             {
339                 if ( _bSet )
340                     _nEnabledBits |= _nTestBit;
341                 else
342                     _nEnabledBits &= ~_nTestBit;
343             }
344         }
345 
346         void implEnable( Window* _pWindow, sal_uInt16 _nEnabledBits, sal_uInt16 _nMatchBits  )
347         {
348             if ( _pWindow )
349                 _pWindow->Enable( ( _nEnabledBits & _nMatchBits ) == _nMatchBits );
350         }
351 
352         void implEnable( Window* _pWindow, bool _bEnable )
353         {
354             if ( _pWindow )
355                 _pWindow->Enable( _bEnable );
356         }
357     }
358 
359     //------------------------------------------------------------------
360 	void OBrowserLine::implUpdateEnabledDisabled()
361     {
362         implEnable( &m_aFtTitle,                m_nEnableFlags, PropertyLineElement::CompleteLine );
363         if ( m_pControlWindow )
364             implEnable( m_pControlWindow,       m_nEnableFlags, PropertyLineElement::CompleteLine | PropertyLineElement::InputControl );
365 
366         if ( m_bReadOnly )
367         {
368             implEnable( m_pBrowseButton,            false );
369             implEnable( m_pAdditionalBrowseButton,  false );
370         }
371         else
372         {
373             implEnable( m_pBrowseButton,            m_nEnableFlags, PropertyLineElement::CompleteLine | PropertyLineElement::PrimaryButton );
374             implEnable( m_pAdditionalBrowseButton,  m_nEnableFlags, PropertyLineElement::CompleteLine | PropertyLineElement::SecondaryButton );
375         }
376     }
377 
378     //------------------------------------------------------------------
379 	void OBrowserLine::EnablePropertyLine( bool _bEnable )
380     {
381         implSetBitIfAffected( m_nEnableFlags, PropertyLineElement::CompleteLine, PropertyLineElement::CompleteLine, _bEnable );
382         implUpdateEnabledDisabled();
383     }
384 
385     //------------------------------------------------------------------
386 	void OBrowserLine::EnablePropertyControls( sal_Int16 _nControls, bool _bEnable )
387 	{
388         implSetBitIfAffected( m_nEnableFlags, _nControls, PropertyLineElement::InputControl, _bEnable );
389         implSetBitIfAffected( m_nEnableFlags, _nControls, PropertyLineElement::PrimaryButton, _bEnable );
390         implSetBitIfAffected( m_nEnableFlags, _nControls, PropertyLineElement::SecondaryButton, _bEnable );
391         implUpdateEnabledDisabled();
392     }
393 
394     //------------------------------------------------------------------
395     PushButton& OBrowserLine::impl_ensureButton( bool _bPrimary )
396     {
397         PushButton*& rpButton = _bPrimary ? m_pBrowseButton : m_pAdditionalBrowseButton;
398 
399         if ( !rpButton )
400         {
401 		    rpButton = new PushButton( m_pTheParent, WB_NOPOINTERFOCUS );
402 		    rpButton->SetGetFocusHdl( LINK( this, OBrowserLine, OnButtonFocus ) );
403 		    rpButton->SetClickHdl( LINK( this, OBrowserLine, OnButtonClicked ) );
404 		    rpButton->SetText( String::CreateFromAscii( "..." ) );
405         }
406 
407         rpButton->Show();
408 
409         impl_layoutComponents();
410 
411         return *rpButton;
412     }
413 
414     //------------------------------------------------------------------
415     void OBrowserLine::impl_getImagesFromURL_nothrow( const ::rtl::OUString& _rImageURL, Image& _out_rImage, Image& _out_rHCImage )
416     {
417         try
418         {
419             ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
420             Reference< XGraphicProvider > xGraphicProvider( aContext.createComponent( "com.sun.star.graphic.GraphicProvider" ), UNO_QUERY_THROW );
421 
422             Sequence< PropertyValue > aMediaProperties(1);
423             aMediaProperties[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
424             aMediaProperties[0].Value <<= _rImageURL;
425 
426             Reference< XGraphic > xGraphic( xGraphicProvider->queryGraphic( aMediaProperties ), UNO_QUERY_THROW );
427             _out_rImage = _out_rHCImage = Image( xGraphic );
428 
429             // see if we find an HC version beside the normal graphic
430             INetURLObject aURL( _rImageURL );
431             ::rtl::OUString sBaseName( aURL.getBase() );
432             aURL.setBase( sBaseName + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_hc" ) ) );
433             ::rtl::OUString sHCImageURL( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
434 
435             Reference< XGraphic > xHCGraphic;
436             try
437             {
438                 aMediaProperties[0].Value <<= sHCImageURL;
439                 xHCGraphic = xGraphicProvider->queryGraphic( aMediaProperties );
440             }
441             catch( const Exception& ) { }
442 
443             if ( xHCGraphic.is() )
444                 _out_rHCImage = Image( xHCGraphic );
445         }
446         catch( const Exception& )
447         {
448         	DBG_UNHANDLED_EXCEPTION();
449         }
450     }
451 
452     //------------------------------------------------------------------
453 	void OBrowserLine::ShowBrowseButton( const ::rtl::OUString& _rImageURL, sal_Bool _bPrimary )
454 	{
455         PushButton& rButton( impl_ensureButton( _bPrimary ) );
456 
457         OSL_PRECOND( _rImageURL.getLength(), "OBrowserLine::ShowBrowseButton: use the other version if you don't have an image!" );
458         Image aImage, aHCImage;
459         impl_getImagesFromURL_nothrow( _rImageURL, aImage, aHCImage );
460 
461         rButton.SetModeImage( aImage, BMP_COLOR_NORMAL );
462         rButton.SetModeImage( aHCImage, BMP_COLOR_HIGHCONTRAST );
463 	}
464 
465     //------------------------------------------------------------------
466 	void OBrowserLine::ShowBrowseButton( const Image& _rImage, sal_Bool _bPrimary )
467 	{
468         PushButton& rButton( impl_ensureButton( _bPrimary ) );
469         if ( !!_rImage )
470             rButton.SetModeImage( _rImage );
471 	}
472 
473     //------------------------------------------------------------------
474 	void OBrowserLine::ShowBrowseButton( sal_Bool _bPrimary )
475 	{
476         impl_ensureButton( _bPrimary );
477 	}
478 
479 	//------------------------------------------------------------------
480     void OBrowserLine::implHideBrowseButton( sal_Bool _bPrimary, bool _bReLayout )
481     {
482         PushButton*& rpButton = _bPrimary ? m_pBrowseButton : m_pAdditionalBrowseButton;
483 
484         if ( rpButton )
485 		{
486 			rpButton->Hide();
487 			delete rpButton;
488 			rpButton = NULL;
489 		}
490 
491         if ( _bReLayout )
492 		    impl_layoutComponents();
493     }
494 
495 	//------------------------------------------------------------------
496 	void OBrowserLine::HideBrowseButton( sal_Bool _bPrimary )
497 	{
498         implHideBrowseButton( _bPrimary, true );
499 	}
500 
501 	//------------------------------------------------------------------
502 	void OBrowserLine::SetTitleWidth(sal_uInt16 nWidth)
503 	{
504 		if (m_nNameWidth != nWidth+10)
505 		{
506 			m_nNameWidth = nWidth+10;
507 			impl_layoutComponents();
508 		}
509 		// #99102# ---------
510 		FullFillTitleString();
511 	}
512 
513 	//------------------------------------------------------------------
514     void OBrowserLine::SetClickListener( IButtonClickListener* _pListener )
515     {
516         m_pClickListener = _pListener;
517     }
518 
519 	//------------------------------------------------------------------
520     IMPL_LINK( OBrowserLine, OnButtonClicked, PushButton*, _pButton )
521     {
522         if ( m_pClickListener )
523             m_pClickListener->buttonClicked( this, _pButton == m_pBrowseButton );
524 
525         return 0L;
526     }
527 
528 	//------------------------------------------------------------------
529 	IMPL_LINK( OBrowserLine, OnButtonFocus, PushButton*, /*pPB*/ )
530 	{
531 		if ( m_xControl.is() )
532 		{
533             try
534             {
535                 Reference< XPropertyControlContext > xContext( m_xControl->getControlContext(), UNO_QUERY_THROW );
536                 xContext->focusGained( m_xControl );
537             }
538             catch( const Exception& )
539             {
540                 DBG_UNHANDLED_EXCEPTION();
541             }
542 		}
543 		return 0;
544 	}
545 //............................................................................
546 } // namespace pcr
547 //............................................................................
548 
549