xref: /trunk/main/svx/source/form/tabwin.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_svx.hxx"
30 
31 #include "tabwin.hxx"
32 #include "svx/fmtools.hxx"
33 #include "fmservs.hxx"
34 #include "stringlistresource.hxx"
35 
36 #include <svx/svxids.hrc>
37 #include <svx/dbaexchange.hxx>
38 #include <com/sun/star/sdb/CommandType.hpp>
39 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
40 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
41 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
42 #include <com/sun/star/awt/XControlContainer.hpp>
43 #include <com/sun/star/util/XLocalizedAliases.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <comphelper/stl_types.hxx>
46 
47 #ifndef _SVX_FMHELP_HRC
48 #include "fmhelp.hrc"
49 #endif
50 #include <svx/fmshell.hxx>
51 #include "fmshimp.hxx"
52 #include "svx/dbtoolsclient.hxx"
53 #include <svx/fmpage.hxx>
54 
55 #ifndef _SVX_FMPGEIMP_HXX
56 #include "fmpgeimp.hxx"
57 #endif
58 
59 #ifndef _SVX_FMPROP_HRC
60 #include "fmprop.hrc"
61 #endif
62 
63 #ifndef _SVX_FMRESIDS_HRC
64 #include "svx/fmresids.hrc"
65 #endif
66 #include <svx/dialmgr.hxx>
67 #include <tools/shl.hxx>
68 #include <svx/svdpagv.hxx>
69 #include <sfx2/objitem.hxx>
70 #include <sfx2/dispatch.hxx>
71 #include <comphelper/property.hxx>
72 #include <sfx2/frame.hxx>
73 #include <svx/dataaccessdescriptor.hxx>
74 
75 const long STD_WIN_POS_X = 50;
76 const long STD_WIN_POS_Y = 50;
77 
78 const long STD_WIN_SIZE_X = 120;
79 const long STD_WIN_SIZE_Y = 150;
80 
81 const long MIN_WIN_SIZE_X = 50;
82 const long MIN_WIN_SIZE_Y = 50;
83 
84 const long LISTBOX_BORDER = 2;
85 
86 using namespace ::com::sun::star::sdbc;
87 using namespace ::com::sun::star::sdb;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::datatransfer;
90 using namespace ::com::sun::star::beans;
91 using namespace ::com::sun::star::lang;
92 using namespace ::com::sun::star::form;
93 using namespace ::com::sun::star::container;
94 using namespace ::com::sun::star;
95 using namespace ::svxform;
96 using namespace ::svx;
97 
98 
99 struct ColumnInfo
100 {
101     ::rtl::OUString sColumnName;
102     ::rtl::OUString sLabel;
103     bool bColumn;
104     ColumnInfo(const ::rtl::OUString& i_sColumnName,const ::rtl::OUString& i_sLabel)
105         : sColumnName(i_sColumnName)
106         , sLabel(i_sLabel)
107         , bColumn(true)
108     {
109     }
110     ColumnInfo(const ::rtl::OUString& i_sColumnName)
111         : sColumnName(i_sColumnName)
112         , bColumn(false)
113     {
114     }
115 };
116 
117 void lcl_addToList( SvTreeListBox& _rListBox, const uno::Reference< container::XNameAccess>& i_xColumns )
118 {
119     uno::Sequence< ::rtl::OUString > aEntries = i_xColumns->getElementNames();
120     const ::rtl::OUString* pEntries = aEntries.getConstArray();
121     sal_Int32 nEntries = aEntries.getLength();
122     for ( sal_Int32 i = 0; i < nEntries; ++i, ++pEntries )
123     {
124         uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(*pEntries),UNO_QUERY_THROW);
125         ::rtl::OUString sLabel;
126         if ( xColumn->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) )
127             xColumn->getPropertyValue(FM_PROP_LABEL) >>= sLabel;
128         if ( sLabel.getLength() )
129             _rListBox.InsertEntry( sLabel,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) );
130         else
131             _rListBox.InsertEntry( *pEntries,NULL,sal_False,LIST_APPEND,new ColumnInfo(*pEntries,sLabel) );
132     }
133 }
134 //==================================================================
135 // class FmFieldWinListBox
136 //==================================================================
137 DBG_NAME(FmFieldWinListBox)
138 //------------------------------------------------------------------------------
139 FmFieldWinListBox::FmFieldWinListBox( FmFieldWin* pParent )
140     :SvTreeListBox( pParent, WB_HASBUTTONS|WB_BORDER )
141     ,pTabWin( pParent )
142 {
143     DBG_CTOR(FmFieldWinListBox,NULL);
144     SetHelpId( HID_FIELD_SEL );
145 
146     SetHighlightRange( );
147 }
148 
149 //------------------------------------------------------------------------------
150 FmFieldWinListBox::~FmFieldWinListBox()
151 {
152     DBG_DTOR(FmFieldWinListBox,NULL);
153 }
154 
155 //------------------------------------------------------------------------------
156 sal_Int8 FmFieldWinListBox::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
157 {
158     return DND_ACTION_NONE;
159 }
160 
161 //------------------------------------------------------------------------------
162 sal_Int8 FmFieldWinListBox::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
163 {
164     return DND_ACTION_NONE;
165 }
166 
167 //------------------------------------------------------------------------------
168 sal_Bool FmFieldWinListBox::DoubleClickHdl()
169 {
170     if ( pTabWin->createSelectionControls() )
171         return sal_True;
172 
173     return SvTreeListBox::DoubleClickHdl();
174 }
175 
176 //------------------------------------------------------------------------------
177 void FmFieldWinListBox::StartDrag( sal_Int8 /*_nAction*/, const Point& /*_rPosPixel*/ )
178 {
179     SvLBoxEntry* pSelected = FirstSelected();
180     if (!pSelected)
181         // no drag without a field
182         return;
183 
184     ::svx::ODataAccessDescriptor aDescriptor;
185     aDescriptor[ daDataSource ] <<= pTabWin->GetDatabaseName();
186     aDescriptor[ daConnection ] <<= pTabWin->GetConnection().getTyped();
187     aDescriptor[ daCommand ]    <<= pTabWin->GetObjectName();
188     aDescriptor[ daCommandType ]<<= pTabWin->GetObjectType();
189     ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
190     aDescriptor[ daColumnName ] <<= pInfo->sColumnName;
191 
192     TransferableHelper* pTransferColumn = new OColumnTransferable(
193         aDescriptor, CTF_FIELD_DESCRIPTOR | CTF_CONTROL_EXCHANGE | CTF_COLUMN_DESCRIPTOR
194     );
195     Reference< XTransferable> xEnsureDelete = pTransferColumn;
196     if (pTransferColumn)
197     {
198         EndSelection();
199         pTransferColumn->StartDrag( this, DND_ACTION_COPY );
200     }
201 }
202 
203 //========================================================================
204 // class FmFieldWinData
205 //========================================================================
206 DBG_NAME(FmFieldWinData);
207 //-----------------------------------------------------------------------
208 FmFieldWinData::FmFieldWinData()
209 {
210     DBG_CTOR(FmFieldWinData,NULL);
211 }
212 
213 //-----------------------------------------------------------------------
214 FmFieldWinData::~FmFieldWinData()
215 {
216     DBG_DTOR(FmFieldWinData,NULL);
217 }
218 
219 //========================================================================
220 // class FmFieldWin
221 //========================================================================
222 DBG_NAME(FmFieldWin);
223 //-----------------------------------------------------------------------
224 FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, Window* _pParent)
225             :SfxFloatingWindow(_pBindings, _pMgr, _pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE))
226             ,SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings)
227             ,::comphelper::OPropertyChangeListener(m_aMutex)
228             ,pData(new FmFieldWinData)
229             ,m_nObjectType(0)
230             ,m_pChangeListener(NULL)
231 {
232     DBG_CTOR(FmFieldWin,NULL);
233     SetHelpId( HID_FIELD_SEL_WIN );
234 
235     SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetFaceColor()) );
236     pListBox = new FmFieldWinListBox( this );
237     pListBox->Show();
238     UpdateContent(NULL);
239     SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y));
240 }
241 
242 //-----------------------------------------------------------------------
243 FmFieldWin::~FmFieldWin()
244 {
245     if (m_pChangeListener)
246     {
247         m_pChangeListener->dispose();
248         m_pChangeListener->release();
249         //  delete m_pChangeListener;
250     }
251     delete pListBox;
252     delete pData;
253     DBG_DTOR(FmFieldWin,NULL);
254 }
255 
256 //-----------------------------------------------------------------------
257 void FmFieldWin::GetFocus()
258 {
259     if ( pListBox )
260         pListBox->GrabFocus();
261     else
262         SfxFloatingWindow::GetFocus();
263 }
264 
265 //-----------------------------------------------------------------------
266 sal_Bool FmFieldWin::createSelectionControls( )
267 {
268     SvLBoxEntry* pSelected = pListBox->FirstSelected();
269     if ( pSelected )
270     {
271         // build a descriptor for the currently selected field
272         ODataAccessDescriptor aDescr;
273         aDescr.setDataSource(GetDatabaseName());
274 
275         aDescr[ daConnection ]  <<= GetConnection().getTyped();
276 
277         aDescr[ daCommand ]     <<= GetObjectName();
278         aDescr[ daCommandType ] <<= GetObjectType();
279         ColumnInfo* pInfo = static_cast<ColumnInfo*>(pSelected->GetUserData());
280         aDescr[ daColumnName ]  <<= pInfo->sColumnName;//::rtl::OUString( pListBox->GetEntryText( pSelected) );
281 
282         // transfer this to the SFX world
283         SfxUnoAnyItem aDescriptorItem( SID_FM_DATACCESS_DESCRIPTOR, makeAny( aDescr.createPropertyValueSequence() ) );
284         const SfxPoolItem* pArgs[] =
285         {
286             &aDescriptorItem, NULL
287         };
288 
289         // execute the create slot
290         GetBindings().Execute( SID_FM_CREATE_FIELDCONTROL, pArgs );
291     }
292 
293     return NULL != pSelected;
294 }
295 
296 //-----------------------------------------------------------------------
297 long FmFieldWin::PreNotify( NotifyEvent& _rNEvt )
298 {
299     if ( EVENT_KEYINPUT == _rNEvt.GetType() )
300     {
301         const KeyCode& rKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
302         if ( ( 0 == rKeyCode.GetModifier() ) && ( KEY_RETURN == rKeyCode.GetCode() ) )
303         {
304             if ( createSelectionControls() )
305                 return 1;
306         }
307     }
308 
309     return SfxFloatingWindow::PreNotify( _rNEvt );
310 }
311 
312 //-----------------------------------------------------------------------
313 sal_Bool FmFieldWin::Close()
314 {
315     return SfxFloatingWindow::Close();
316 }
317 
318 //-----------------------------------------------------------------------
319 void FmFieldWin::_propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw( ::com::sun::star::uno::RuntimeException )
320 {
321     ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm >  xForm(evt.Source, ::com::sun::star::uno::UNO_QUERY);
322     UpdateContent(xForm);
323 }
324 
325 //-----------------------------------------------------------------------
326 void FmFieldWin::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
327 {
328     if (!pState  || SID_FM_FIELDS_CONTROL != nSID)
329         return;
330 
331     if (eState >= SFX_ITEM_AVAILABLE)
332     {
333         FmFormShell* pShell = PTR_CAST(FmFormShell,((SfxObjectItem*)pState)->GetShell());
334         UpdateContent(pShell);
335     }
336     else
337         UpdateContent(NULL);
338 }
339 
340 //-----------------------------------------------------------------------
341 void FmFieldWin::UpdateContent(FmFormShell* pShell)
342 {
343     pListBox->Clear();
344     String aTitle( SVX_RES( RID_STR_FIELDSELECTION ) );
345     SetText( aTitle );
346 
347     if (!pShell || !pShell->GetImpl())
348         return;
349 
350     Reference< XForm >  xForm = pShell->GetImpl()->getCurrentForm();
351     if ( xForm.is() )
352         UpdateContent( xForm );
353 }
354 
355 //-----------------------------------------------------------------------
356 void FmFieldWin::UpdateContent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > & xForm)
357 {
358     try
359     {
360         // ListBox loeschen
361         pListBox->Clear();
362         UniString aTitle(SVX_RES(RID_STR_FIELDSELECTION));
363         SetText(aTitle);
364 
365         if (!xForm.is())
366             return;
367 
368         Reference< XPreparedStatement >  xStatement;
369         Reference< XPropertySet >  xSet(xForm, UNO_QUERY);
370 
371         m_aObjectName   = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_COMMAND));
372         m_aDatabaseName = ::comphelper::getString(xSet->getPropertyValue(FM_PROP_DATASOURCE));
373         m_nObjectType   = ::comphelper::getINT32(xSet->getPropertyValue(FM_PROP_COMMANDTYPE));
374 
375         // get the connection of the form
376         OStaticDataAccessTools aTools;
377         m_aConnection.reset(
378             aTools.connectRowset( Reference< XRowSet >( xForm, UNO_QUERY ), ::comphelper::getProcessServiceFactory(), sal_True ),
379             SharedConnection::NoTakeOwnership
380         );
381         // TODO: When incompatible changes (such as extending the "virtualdbtools" interface by ensureRowSetConnection)
382         // are allowed, again, we should change this: dbtools should consistently use SharedConnection all over
383         // the place, and connectRowset should be replaced with ensureRowSetConnection
384 
385         // get the fields of the object
386 
387         if ( m_aConnection.is() && m_aObjectName.getLength() )
388         {
389             Reference< XComponent > xKeepFieldsAlive;
390             Reference< XNameAccess > xColumns = getFieldsByCommandDescriptor( m_aConnection, m_nObjectType, m_aObjectName,xKeepFieldsAlive );
391             if ( xColumns.is() )
392                 lcl_addToList(*pListBox,xColumns);
393         }
394 
395         // Prefix setzen
396         UniString  aPrefix;
397         StringListResource aPrefixes( SVX_RES( RID_RSC_TABWIN_PREFIX ) );
398 
399         switch (m_nObjectType)
400         {
401             case CommandType::TABLE:
402                 aPrefix = aPrefixes[0];
403                 break;
404             case CommandType::QUERY:
405                 aPrefix = aPrefixes[1];
406                 break;
407             default:
408                 aPrefix = aPrefixes[2];
409                 break;
410         }
411 
412         // an dem PropertySet nach Aenderungen der ControlSource lauschen
413         if (m_pChangeListener)
414         {
415             m_pChangeListener->dispose();
416             m_pChangeListener->release();
417         }
418         m_pChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet);
419         m_pChangeListener->acquire();
420         m_pChangeListener->addProperty(FM_PROP_DATASOURCE);
421         m_pChangeListener->addProperty(FM_PROP_COMMAND);
422         m_pChangeListener->addProperty(FM_PROP_COMMANDTYPE);
423 
424         // Titel setzen
425         aTitle.AppendAscii(" ");
426         aTitle += aPrefix;
427         aTitle.AppendAscii(" ");
428         aTitle += m_aObjectName.getStr();
429         SetText( aTitle );
430     }
431     catch( const Exception& )
432     {
433         DBG_ERROR( "FmTabWin::UpdateContent: caught an exception!" );
434     }
435 }
436 
437 //-----------------------------------------------------------------------
438 void FmFieldWin::Resize()
439 {
440     SfxFloatingWindow::Resize();
441 
442     Point aPos(GetPosPixel());
443     Size aOutputSize( GetOutputSizePixel() );
444 
445     //////////////////////////////////////////////////////////////////////
446 
447     // Groesse der ::com::sun::star::form::ListBox anpassen
448     Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER );
449     Size aLBSize( aOutputSize );
450     aLBSize.Width() -= (2*LISTBOX_BORDER);
451     aLBSize.Height() -= (2*LISTBOX_BORDER);
452 
453     pListBox->SetPosSizePixel( aLBPos, aLBSize );
454 }
455 
456 //-----------------------------------------------------------------------
457 void FmFieldWin::FillInfo( SfxChildWinInfo& rInfo ) const
458 {
459     rInfo.bVisible = sal_False;
460 }
461 
462 //-----------------------------------------------------------------------
463 SFX_IMPL_FLOATINGWINDOW(FmFieldWinMgr, SID_FM_ADD_FIELD)
464 
465 //-----------------------------------------------------------------------
466 FmFieldWinMgr::FmFieldWinMgr(Window* _pParent, sal_uInt16 _nId,
467                SfxBindings* _pBindings, SfxChildWinInfo* _pInfo)
468               :SfxChildWindow(_pParent, _nId)
469 {
470     pWindow = new FmFieldWin(_pBindings, this, _pParent);
471     SetHideNotDelete(sal_True);
472     eChildAlignment = SFX_ALIGN_NOALIGNMENT;
473     ((SfxFloatingWindow*)pWindow)->Initialize( _pInfo );
474 }
475 
476 
477