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 "propertyeditor.hxx"
31 #include "browserpage.hxx"
32 #include "linedescriptor.hxx"
33 
34 /** === begin UNO includes === **/
35 /** === end UNO includes === **/
36 #include <tools/debug.hxx>
37 
38 //............................................................................
39 namespace pcr
40 {
41 //............................................................................
42 
43     #define LAYOUT_BORDER_LEFT      3
44     #define LAYOUT_BORDER_TOP       3
45     #define LAYOUT_BORDER_RIGHT     3
46     #define LAYOUT_BORDER_BOTTOM    3
47 
48     /** === begin UNO using === **/
49     using ::com::sun::star::uno::Any;
50     using ::com::sun::star::inspection::XPropertyControl;
51     using ::com::sun::star::uno::Reference;
52     /** === end UNO using === **/
53 
54     //==================================================================
55     // class OPropertyEditor
56     //==================================================================
57     DBG_NAME(OPropertyEditor)
58     //------------------------------------------------------------------
59     OPropertyEditor::OPropertyEditor( Window* pParent, WinBits nWinStyle)
60             :Control(pParent, nWinStyle)
61             ,m_aTabControl( this )
62             ,m_nNextId(1)
63             ,m_bHasHelpSection( false )
64             ,m_nMinHelpLines( 0 )
65             ,m_nMaxHelpLines( 0 )
66     {
67         DBG_CTOR(OPropertyEditor,NULL);
68 
69         m_aTabControl.Show();
70         m_aTabControl.SetDeactivatePageHdl(LINK(this, OPropertyEditor, OnPageDeactivate));
71         m_aTabControl.SetActivatePageHdl(LINK(this, OPropertyEditor, OnPageActivate));
72         m_aTabControl.SetBackground(GetBackground());
73         m_aTabControl.SetPaintTransparent(sal_True);
74     }
75 
76     //------------------------------------------------------------------
77     OPropertyEditor::~OPropertyEditor()
78     {
79         Hide();
80         ClearAll();
81         DBG_DTOR(OPropertyEditor,NULL);
82     }
83 
84     //------------------------------------------------------------------
85     void OPropertyEditor::ClearAll()
86     {
87         m_nNextId=1;
88         sal_uInt16 nCount = m_aTabControl.GetPageCount();
89         for(long i = nCount-1; i >= 0; --i)
90         {
91             sal_uInt16 nID = m_aTabControl.GetPageId((sal_uInt16)i);
92             OBrowserPage* pPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage(nID));
93             if (pPage)
94             {
95                 pPage->EnableInput(sal_False);
96                 m_aTabControl.RemovePage(nID);
97                 delete pPage;
98             }
99         }
100         m_aTabControl.Clear();
101 
102         {
103             MapStringToPageId aEmpty;
104             m_aPropertyPageIds.swap( aEmpty );
105         }
106 
107         while ( !m_aHiddenPages.empty() )
108         {
109             delete m_aHiddenPages.begin()->second.pPage;
110             m_aHiddenPages.erase( m_aHiddenPages.begin() );
111         }
112     }
113 
114     //------------------------------------------------------------------
115     sal_Int32 OPropertyEditor::getMinimumHeight()
116     {
117         sal_Int32 nMinHeight( LAYOUT_BORDER_TOP + LAYOUT_BORDER_BOTTOM );
118 
119         if ( m_aTabControl.GetPageCount() > 0 )
120         {
121             sal_uInt16 nFirstID = m_aTabControl.GetPageId( 0 );
122 
123             // reserve space for the tabs themself
124             Rectangle aTabArea( m_aTabControl.GetTabBounds( nFirstID ) );
125             nMinHeight += aTabArea.GetHeight();
126 
127             // ask the page how much it requires
128             OBrowserPage* pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( nFirstID ) );
129             if ( pPage )
130                 nMinHeight += pPage->getMinimumHeight();
131         }
132         else
133             nMinHeight += 250;  // arbitrary ...
134 
135         return nMinHeight;
136     }
137 
138     //------------------------------------------------------------------
139     sal_Int32 OPropertyEditor::getMinimumWidth()
140     {
141         sal_uInt16 nCount = m_aTabControl.GetPageCount();
142         sal_Int32 nPageMinWidth = 0;
143         for(long i = nCount-1; i >= 0; --i)
144         {
145             sal_uInt16 nID = m_aTabControl.GetPageId((sal_uInt16)i);
146             OBrowserPage* pPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage(nID));
147             if (pPage)
148             {
149                 sal_Int32 nCurPageMinWidth = pPage->getMinimumWidth();
150                 if( nCurPageMinWidth > nPageMinWidth )
151                     nPageMinWidth = nCurPageMinWidth;
152             }
153         }
154         return nPageMinWidth+6;
155     }
156 
157     //------------------------------------------------------------------
158     void OPropertyEditor::CommitModified()
159     {
160         // commit all of my pages, if necessary
161 
162         sal_uInt16 nCount = m_aTabControl.GetPageCount();
163         for ( sal_uInt16 i=0; i<nCount; ++i )
164         {
165             sal_uInt16 nID = m_aTabControl.GetPageId( i );
166             OBrowserPage* pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( nID ) );
167 
168             if ( pPage && pPage->getListBox().IsModified() )
169                 pPage->getListBox().CommitModified();
170         }
171     }
172 
173     //------------------------------------------------------------------
174     void OPropertyEditor::GetFocus()
175     {
176         m_aTabControl.GrabFocus();
177     }
178 
179     //------------------------------------------------------------------
180     OBrowserPage* OPropertyEditor::getPage( const ::rtl::OUString& _rPropertyName )
181     {
182         OBrowserPage* pPage = NULL;
183         MapStringToPageId::const_iterator aPropertyPageIdPos = m_aPropertyPageIds.find( _rPropertyName );
184         if ( aPropertyPageIdPos != m_aPropertyPageIds.end() )
185             pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( aPropertyPageIdPos->second ) );
186         return pPage;
187     }
188 
189     //------------------------------------------------------------------
190     const OBrowserPage* OPropertyEditor::getPage( const ::rtl::OUString& _rPropertyName ) const
191     {
192         return const_cast< OPropertyEditor* >( this )->getPage( _rPropertyName );
193     }
194 
195     //------------------------------------------------------------------
196     OBrowserPage* OPropertyEditor::getPage( sal_uInt16& _rPageId )
197     {
198         return static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( _rPageId ) );
199     }
200 
201     //------------------------------------------------------------------
202     const OBrowserPage* OPropertyEditor::getPage( sal_uInt16& _rPageId ) const
203     {
204         return const_cast< OPropertyEditor* >( this )->getPage( _rPageId );
205     }
206 
207     //------------------------------------------------------------------
208     void OPropertyEditor::Resize()
209     {
210         Rectangle aPlayground(
211             Point( LAYOUT_BORDER_LEFT, LAYOUT_BORDER_TOP ),
212             Size(
213                 GetOutputSizePixel().Width() - LAYOUT_BORDER_LEFT - LAYOUT_BORDER_RIGHT,
214                 GetOutputSizePixel().Height() - LAYOUT_BORDER_TOP - LAYOUT_BORDER_BOTTOM
215             )
216         );
217 
218         Rectangle aTabArea( aPlayground );
219         m_aTabControl.SetPosSizePixel( aTabArea.TopLeft(), aTabArea.GetSize() );
220     }
221 
222     //------------------------------------------------------------------
223     sal_uInt16 OPropertyEditor::AppendPage( const String & _rText, const rtl::OString& _rHelpId )
224     {
225         // obtain a new id
226         sal_uInt16 nId = m_nNextId++;
227         // insert the id
228         m_aTabControl.InsertPage(nId, _rText);
229 
230         // create a new page
231         OBrowserPage* pPage = new OBrowserPage(&m_aTabControl);
232         pPage->SetText( _rText );
233         // some knittings
234         pPage->SetSizePixel(m_aTabControl.GetTabPageSizePixel());
235         pPage->getListBox().SetListener(m_pListener);
236         pPage->getListBox().SetObserver(m_pObserver);
237         pPage->getListBox().EnableHelpSection( m_bHasHelpSection );
238         pPage->getListBox().SetHelpLineLimites( m_nMinHelpLines, m_nMaxHelpLines );
239         pPage->SetHelpId( _rHelpId );
240 
241         // immediately activate the page
242         m_aTabControl.SetTabPage(nId, pPage);
243         m_aTabControl.SetCurPageId(nId);
244 
245         return nId;
246     }
247 
248     //------------------------------------------------------------------
249     void OPropertyEditor::SetHelpId( const rtl::OString& rHelpId )
250     {
251         Control::SetHelpId("");
252         m_aTabControl.SetHelpId(rHelpId);
253     }
254 
255     //------------------------------------------------------------------
256     void OPropertyEditor::RemovePage(sal_uInt16 nID)
257     {
258         OBrowserPage* pPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage(nID));
259 
260         if (pPage)
261             pPage->EnableInput(sal_False);
262         m_aTabControl.RemovePage(nID);
263         if (pPage)
264             delete pPage;
265     }
266 
267     //------------------------------------------------------------------
268     void OPropertyEditor::SetPage(sal_uInt16 nId)
269     {
270         m_aTabControl.SetCurPageId(nId);
271     }
272 
273     //------------------------------------------------------------------
274     sal_uInt16 OPropertyEditor::GetCurPage()
275     {
276         if(m_aTabControl.GetPageCount()>0)
277             return m_aTabControl.GetCurPageId();
278         else
279             return 0;
280     }
281 
282     //------------------------------------------------------------------
283     void OPropertyEditor::Update(const ::std::mem_fun_t<void,OBrowserListBox>& _aUpdateFunction)
284     {
285         // forward this to all our pages
286         sal_uInt16 nCount = m_aTabControl.GetPageCount();
287         for (sal_uInt16 i=0;i<nCount;++i)
288         {
289             sal_uInt16 nID = m_aTabControl.GetPageId(i);
290             OBrowserPage* pPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage(nID));
291             if (pPage)
292                 _aUpdateFunction(&pPage->getListBox());
293         }
294     }
295     //------------------------------------------------------------------
296     void OPropertyEditor::EnableUpdate()
297     {
298         Update(::std::mem_fun(&OBrowserListBox::EnableUpdate));
299     }
300     //------------------------------------------------------------------
301     void OPropertyEditor::DisableUpdate()
302     {
303         Update(::std::mem_fun(&OBrowserListBox::DisableUpdate));
304     }
305 
306     //------------------------------------------------------------------
307     void OPropertyEditor::forEachPage( PageOperation _pOperation, const void* _pArgument )
308     {
309         sal_uInt16 nCount = m_aTabControl.GetPageCount();
310         for ( sal_uInt16 i=0; i<nCount; ++i )
311         {
312             sal_uInt16 nID = m_aTabControl.GetPageId(i);
313             OBrowserPage* pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( nID ) );
314             if ( !pPage )
315                 continue;
316             (this->*_pOperation)( *pPage, _pArgument );
317         }
318     }
319 
320     //------------------------------------------------------------------
321     void OPropertyEditor::setPageLineListener( OBrowserPage& _rPage, const void* )
322     {
323         _rPage.getListBox().SetListener( m_pListener );
324     }
325 
326     //------------------------------------------------------------------
327     void OPropertyEditor::SetLineListener(IPropertyLineListener* _pListener)
328     {
329         m_pListener = _pListener;
330         forEachPage( &OPropertyEditor::setPageLineListener );
331     }
332 
333     //------------------------------------------------------------------
334     void OPropertyEditor::setPageControlObserver( OBrowserPage& _rPage, const void* )
335     {
336         _rPage.getListBox().SetObserver( m_pObserver );
337     }
338 
339     //------------------------------------------------------------------
340     void OPropertyEditor::SetControlObserver( IPropertyControlObserver* _pObserver )
341     {
342         m_pObserver = _pObserver;
343         forEachPage( &OPropertyEditor::setPageControlObserver );
344     }
345 
346     //------------------------------------------------------------------
347     void OPropertyEditor::EnableHelpSection( bool _bEnable )
348     {
349         m_bHasHelpSection = _bEnable;
350         forEachPage( &OPropertyEditor::enableHelpSection );
351     }
352 
353     //------------------------------------------------------------------
354     bool OPropertyEditor::HasHelpSection() const
355     {
356         return m_bHasHelpSection;
357     }
358 
359     //------------------------------------------------------------------
360     void OPropertyEditor::SetHelpText( const ::rtl::OUString& _rHelpText )
361     {
362         forEachPage( &OPropertyEditor::setHelpSectionText, &_rHelpText );
363     }
364 
365     //------------------------------------------------------------------
366     void OPropertyEditor::SetHelpLineLimites( sal_Int32 _nMinLines, sal_Int32 _nMaxLines )
367     {
368         m_nMinHelpLines = _nMinLines;
369         m_nMaxHelpLines = _nMaxLines;
370         forEachPage( &OPropertyEditor::setHelpLineLimits );
371     }
372 
373     //------------------------------------------------------------------
374     void OPropertyEditor::enableHelpSection( OBrowserPage& _rPage, const void* )
375     {
376         _rPage.getListBox().EnableHelpSection( m_bHasHelpSection );
377     }
378 
379     //------------------------------------------------------------------
380     void OPropertyEditor::setHelpSectionText( OBrowserPage& _rPage, const void* _pPointerToOUString )
381     {
382         OSL_ENSURE( _pPointerToOUString, "OPropertyEditor::setHelpSectionText: invalid argument!" );
383         if ( !_pPointerToOUString )
384             return;
385 
386         const ::rtl::OUString& rText( *(const ::rtl::OUString*)_pPointerToOUString );
387         _rPage.getListBox().SetHelpText( rText );
388     }
389 
390     //------------------------------------------------------------------
391     void OPropertyEditor::setHelpLineLimits( OBrowserPage& _rPage, const void* )
392     {
393         _rPage.getListBox().SetHelpLineLimites( m_nMinHelpLines, m_nMaxHelpLines );
394     }
395 
396     //------------------------------------------------------------------
397     sal_uInt16 OPropertyEditor::InsertEntry( const OLineDescriptor& rData, sal_uInt16 _nPageId, sal_uInt16 nPos )
398     {
399         // let the current page handle this
400         OBrowserPage* pPage = getPage( _nPageId );
401         DBG_ASSERT( pPage, "OPropertyEditor::InsertEntry: don't have such a page!" );
402         if ( !pPage )
403             return LISTBOX_ENTRY_NOTFOUND;
404 
405         sal_uInt16 nEntry = pPage->getListBox().InsertEntry( rData, nPos );
406 
407         OSL_ENSURE( m_aPropertyPageIds.find( rData.sName ) == m_aPropertyPageIds.end(),
408             "OPropertyEditor::InsertEntry: property already present in the map!" );
409         m_aPropertyPageIds.insert( MapStringToPageId::value_type( rData.sName, _nPageId ) );
410 
411         return nEntry;
412     }
413 
414     //------------------------------------------------------------------
415     void OPropertyEditor::RemoveEntry( const ::rtl::OUString& _rName )
416     {
417         OBrowserPage* pPage = getPage( _rName );
418         if ( pPage )
419         {
420             OSL_VERIFY( pPage->getListBox().RemoveEntry( _rName ) );
421 
422             OSL_ENSURE( m_aPropertyPageIds.find( _rName ) != m_aPropertyPageIds.end(),
423                 "OPropertyEditor::RemoveEntry: property not present in the map!" );
424             m_aPropertyPageIds.erase( _rName );
425         }
426     }
427 
428     //------------------------------------------------------------------
429     void OPropertyEditor::ChangeEntry( const OLineDescriptor& rData )
430     {
431         OBrowserPage* pPage = getPage( rData.sName );
432         if ( pPage )
433             pPage->getListBox().ChangeEntry( rData, EDITOR_LIST_REPLACE_EXISTING );
434     }
435 
436     //------------------------------------------------------------------
437     void OPropertyEditor::SetPropertyValue( const ::rtl::OUString& rEntryName, const Any& _rValue, bool _bUnknownValue )
438     {
439         OBrowserPage* pPage = getPage( rEntryName );
440         if ( pPage )
441             pPage->getListBox().SetPropertyValue( rEntryName, _rValue, _bUnknownValue );
442     }
443 
444     //------------------------------------------------------------------
445     sal_uInt16 OPropertyEditor::GetPropertyPos( const ::rtl::OUString& rEntryName ) const
446     {
447         sal_uInt16 nVal=LISTBOX_ENTRY_NOTFOUND;
448         const OBrowserPage* pPage = getPage( rEntryName );
449         if ( pPage )
450             nVal = pPage->getListBox().GetPropertyPos( rEntryName );
451         return nVal;
452     }
453 
454     //------------------------------------------------------------------
455     void OPropertyEditor::ShowPropertyPage( sal_uInt16 _nPageId, bool _bShow )
456     {
457         if ( !_bShow )
458         {
459             sal_uInt16 nPagePos = m_aTabControl.GetPagePos( _nPageId );
460             if ( TAB_PAGE_NOTFOUND == nPagePos )
461                 return;
462             DBG_ASSERT( m_aHiddenPages.find( _nPageId ) == m_aHiddenPages.end(), "OPropertyEditor::ShowPropertyPage: page already hidden!" );
463 
464             m_aHiddenPages[ _nPageId ] = HiddenPage( nPagePos, m_aTabControl.GetTabPage( _nPageId ) );
465             m_aTabControl.RemovePage( _nPageId );
466         }
467         else
468         {
469             ::std::map< sal_uInt16, HiddenPage >::iterator aPagePos = m_aHiddenPages.find( _nPageId );
470             if ( aPagePos == m_aHiddenPages.end() )
471                 return;
472 
473             aPagePos->second.pPage->SetSizePixel( m_aTabControl.GetTabPageSizePixel() );
474             m_aTabControl.InsertPage( aPagePos->first, aPagePos->second.pPage->GetText(), aPagePos->second.nPos );
475             m_aTabControl.SetTabPage( aPagePos->first, aPagePos->second.pPage );
476 
477             m_aHiddenPages.erase( aPagePos );
478         }
479     }
480 
481     //------------------------------------------------------------------
482     void OPropertyEditor::EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable )
483     {
484         for ( sal_uInt16 i = 0; i < m_aTabControl.GetPageCount(); ++i )
485         {
486             OBrowserPage* pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( m_aTabControl.GetPageId( i ) ) );
487             if ( pPage )
488                 pPage->getListBox().EnablePropertyControls( _rEntryName, _nControls, _bEnable );
489         }
490     }
491 
492     //------------------------------------------------------------------
493     void OPropertyEditor::EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable )
494     {
495         for ( sal_uInt16 i = 0; i < m_aTabControl.GetPageCount(); ++i )
496         {
497             OBrowserPage* pPage = static_cast< OBrowserPage* >( m_aTabControl.GetTabPage( m_aTabControl.GetPageId( i ) ) );
498             if ( pPage )
499                 pPage->getListBox().EnablePropertyLine( _rEntryName, _bEnable );
500         }
501     }
502 
503     //------------------------------------------------------------------
504     Reference< XPropertyControl > OPropertyEditor::GetPropertyControl(const ::rtl::OUString& rEntryName)
505     {
506         Reference< XPropertyControl > xControl;
507         // let the current page handle this
508         OBrowserPage* pPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage(m_aTabControl.GetCurPageId()));
509         if (pPage)
510             xControl = pPage->getListBox().GetPropertyControl(rEntryName);
511         return xControl;
512     }
513 
514     //------------------------------------------------------------------
515     IMPL_LINK(OPropertyEditor, OnPageActivate, TabControl*, EMPTYARG)
516     {
517         if (m_aPageActivationHandler.IsSet())
518             m_aPageActivationHandler.Call(NULL);
519         return 0L;
520     }
521 
522     //------------------------------------------------------------------
523     IMPL_LINK(OPropertyEditor, OnPageDeactivate, TabControl*, EMPTYARG)
524     {
525         // commit the data on the current (to-be-decativated) tab page
526         // (79404)
527         sal_Int32 nCurrentId = m_aTabControl.GetCurPageId();
528         OBrowserPage* pCurrentPage = static_cast<OBrowserPage*>(m_aTabControl.GetTabPage((sal_uInt16)nCurrentId));
529         if ( !pCurrentPage )
530             return 1L;
531 
532         if ( pCurrentPage->getListBox().IsModified() )
533             pCurrentPage->getListBox().CommitModified();
534 
535         return 1L;
536     }
537 
538 //............................................................................
539 } // namespace pcr
540 //............................................................................
541 
542 
543