xref: /aoo42x/main/svx/source/form/tabwin.cxx (revision cdf0e10c)
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