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_dbaccess.hxx"
30 #ifndef DBAUI_RELATIONCONTROL_HXX
31 #include "RelationControl.hxx"
32 #endif
33 #ifndef DBACCESS_SOURCE_UI_INC_RELATIONCONTROL_HRC
34 #include "RelationControl.hrc"
35 #endif
36 
37 #ifndef _SVTOOLS_EDITBROWSEBOX_HXX_
38 #include <svtools/editbrowsebox.hxx>
39 #endif
40 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #endif
43 #ifndef _TOOLS_DEBUG_HXX
44 #include <tools/debug.hxx>
45 #endif
46 #ifndef TOOLS_DIAGNOSE_EX_H
47 #include <tools/diagnose_ex.h>
48 #endif
49 #ifndef DBAUI_TABLECONNECTIONDATA_HXX
50 #include "TableConnectionData.hxx"
51 #endif
52 #ifndef DBAUI_TABLECONNECTION_HXX
53 #include "TableConnection.hxx"
54 #endif
55 #ifndef DBAUI_TABLEWINDOW_HXX
56 #include "TableWindow.hxx"
57 #endif
58 #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
59 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
60 #endif
61 #ifndef DBAUI_TOOLS_HXX
62 #include "UITools.hxx"
63 #endif
64 #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
65 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
66 #endif
67 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
68 #include <com/sun/star/container/XNameAccess.hpp>
69 #endif
70 #ifndef DBAUI_RELCONTROLIFACE_HXX
71 #include "RelControliFace.hxx"
72 #endif
73 #ifndef _DBU_CONTROL_HRC_
74 #include "dbu_control.hrc"
75 #endif
76 #ifndef _DBA_DBACCESS_HELPID_HRC_
77 #include "dbaccess_helpid.hrc"
78 #endif
79 #ifndef _TOOLS_DEBUG_HXX
80 #include <tools/debug.hxx>
81 #endif
82 
83 #include <algorithm>
84 
85 #define SOURCE_COLUMN	1
86 #define DEST_COLUMN		2
87 
88 namespace dbaui
89 {
90 	using namespace ::com::sun::star::uno;
91 	using namespace ::com::sun::star::beans;
92 	using namespace ::com::sun::star::sdbc;
93 	using namespace ::com::sun::star::sdbcx;
94 	using namespace ::com::sun::star::container;
95 	using namespace svt;
96 
97 	typedef ::svt::EditBrowseBox ORelationControl_Base;
98 	class ORelationControl : public ORelationControl_Base
99 	{
100 		friend class OTableListBoxControl;
101 
102         ::std::auto_ptr< ::svt::ListBoxControl> m_pListCell;
103 		TTableConnectionData::value_type		m_pConnData;
104 		const OJoinTableView::OTableWindowMap*	m_pTableMap;
105 		OTableListBoxControl*					m_pBoxControl;
106 		long									m_nDataPos;
107 		Reference< XPropertySet>				m_xSourceDef;
108 		Reference< XPropertySet>				m_xDestDef;
109 
110 
111 		void fillListBox(const Reference< XPropertySet>& _xDest,long nRow,sal_uInt16 nColumnId);
112 		/** returns the column id for the editbrowsebox
113 			@param	_nColId
114 					the column id SOURCE_COLUMN or DEST_COLUMN
115 
116 			@return	the current column id eihter SOURCE_COLUMN or DEST_COLUMN depends on the connection data
117 		*/
118 		sal_uInt16 getColumnIdent( sal_uInt16 _nColId ) const;
119 	public:
120 		ORelationControl( OTableListBoxControl* pParent,const OJoinTableView::OTableWindowMap* _pTableMap );
121 		virtual ~ORelationControl();
122 
123 		/** searches for a connection between these two tables
124 			@param	_pSource
125 					the left table
126 			@param	_pDest
127 					the right window
128 		*/
129 		void setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest);
130 
131 		/** allows to access the connection data from outside
132 
133 			@return rthe connection data
134 		*/
135 		inline TTableConnectionData::value_type getData() const { return m_pConnData; }
136 
137 		void lateInit();
138 
139 	protected:
140 		virtual void Resize();
141 
142 		virtual long PreNotify(NotifyEvent& rNEvt );
143 
144 		virtual sal_Bool IsTabAllowed(sal_Bool bForward) const;
145 
146 		virtual void Init(const TTableConnectionData::value_type& _pConnData);
147 		virtual void Init() { ORelationControl_Base::Init(); }
148 		virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol );
149 		virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol );
150 		virtual void PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColId ) const;
151 		virtual sal_Bool SeekRow( long nRow );
152 		virtual sal_Bool SaveModified();
153 		virtual String GetCellText( long nRow, sal_uInt16 nColId ) const;
154 
155 		virtual void CellModified();
156 
157         DECL_LINK( AsynchDeactivate, void* );
158 	private:
159 
160 		DECL_LINK( AsynchActivate, void* );
161 
162 	};
163 
164     //========================================================================
165 	// class ORelationControl
166 	//========================================================================
167 	DBG_NAME(ORelationControl)
168 	//------------------------------------------------------------------------
169 	ORelationControl::ORelationControl( OTableListBoxControl* pParent ,const OJoinTableView::OTableWindowMap* _pTableMap)
170 		:EditBrowseBox( pParent, EBBF_SMART_TAB_TRAVEL | EBBF_NOROWPICTURE, WB_TABSTOP | /*WB_3DLOOK | */WB_BORDER | BROWSER_AUTOSIZE_LASTCOL)
171 		,m_pTableMap(_pTableMap)
172 		,m_pBoxControl(pParent)
173 		,m_xSourceDef( NULL )
174 		,m_xDestDef( NULL )
175 	{
176 		DBG_CTOR(ORelationControl,NULL);
177 	}
178 
179 	//------------------------------------------------------------------------
180 	ORelationControl::~ORelationControl()
181 	{
182 		DBG_DTOR(ORelationControl,NULL);
183 	}
184 
185 	//------------------------------------------------------------------------
186 	void ORelationControl::Init(const TTableConnectionData::value_type& _pConnData)
187 	{
188 		DBG_CHKTHIS(ORelationControl,NULL);
189 
190 		m_pConnData = _pConnData;
191 		OSL_ENSURE(m_pConnData, "No data supplied!");
192 
193 		m_pConnData->normalizeLines();
194 	}
195 	//------------------------------------------------------------------------------
196 	void ORelationControl::lateInit()
197 	{
198         if ( !m_pConnData.get() )
199             return;
200         m_xSourceDef = m_pConnData->getReferencingTable()->getTable();
201 		m_xDestDef = m_pConnData->getReferencedTable()->getTable();
202 
203 		if ( ColCount() == 0 )
204 		{
205 			InsertDataColumn( SOURCE_COLUMN, m_pConnData->getReferencingTable()->GetWinName(), 100);
206 			InsertDataColumn( DEST_COLUMN, m_pConnData->getReferencedTable()->GetWinName(), 100);
207 				// wenn es die Defs noch nicht gibt, dann muessen sie noch mit SetSource-/-DestDef gesetzt werden !
208 
209 			m_pListCell.reset( new ListBoxControl( &GetDataWindow() ) );
210 
211 			//////////////////////////////////////////////////////////////////////
212 			// set browse mode
213 			SetMode(	BROWSER_COLUMNSELECTION |
214 						BROWSER_HLINESFULL		|
215 						BROWSER_VLINESFULL		|
216 						BROWSER_HIDECURSOR		|
217 						BROWSER_HIDESELECT		|
218 						BROWSER_AUTO_HSCROLL	|
219 						BROWSER_AUTO_VSCROLL);
220 		}
221 		else
222 			// not the first call
223 			RowRemoved(0, GetRowCount());
224 
225 		RowInserted(0, m_pConnData->GetConnLineDataList()->size() + 1, sal_True); // add one extra row
226 	}
227 	//------------------------------------------------------------------------------
228 	void ORelationControl::Resize()
229 	{
230 		DBG_CHKTHIS(ORelationControl,NULL);
231 		EditBrowseBox::Resize();
232 		long nOutputWidth = GetOutputSizePixel().Width();
233 		SetColumnWidth(1, (nOutputWidth / 2));
234 		SetColumnWidth(2, (nOutputWidth / 2));
235 	}
236 
237 	//------------------------------------------------------------------------------
238 	long ORelationControl::PreNotify(NotifyEvent& rNEvt)
239 	{
240 		DBG_CHKTHIS(ORelationControl,NULL);
241 		if (rNEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() )
242 			PostUserEvent(LINK(this, ORelationControl, AsynchDeactivate));
243 		else if (rNEvt.GetType() == EVENT_GETFOCUS)
244 			PostUserEvent(LINK(this, ORelationControl, AsynchActivate));
245 
246 		return EditBrowseBox::PreNotify(rNEvt);
247 	}
248 
249 	//------------------------------------------------------------------------------
250 	IMPL_LINK(ORelationControl, AsynchActivate, void*, EMPTYARG)
251 	{
252 		ActivateCell();
253 		return 0L;
254 	}
255 
256 	//------------------------------------------------------------------------------
257 	IMPL_LINK(ORelationControl, AsynchDeactivate, void*, EMPTYARG)
258 	{
259 		DeactivateCell();
260 		return 0L;
261 	}
262 
263 	//------------------------------------------------------------------------------
264 	sal_Bool ORelationControl::IsTabAllowed(sal_Bool bForward) const
265 	{
266 		DBG_CHKTHIS(ORelationControl,NULL);
267 		long nRow = GetCurRow();
268 		sal_uInt16 nCol = GetCurColumnId();
269 
270 		sal_Bool bRet = !((		( bForward && (nCol == DEST_COLUMN)		&& (nRow == GetRowCount() - 1)))
271 						||	(!bForward && (nCol == SOURCE_COLUMN)	&& (nRow == 0)));
272 
273 		return bRet && EditBrowseBox::IsTabAllowed(bForward);
274 	}
275 
276 	//------------------------------------------------------------------------------
277 	sal_Bool ORelationControl::SaveModified()
278 	{
279 		DBG_CHKTHIS(ORelationControl,NULL);
280         sal_Int32 nRow = GetCurRow();
281 		if ( nRow != BROWSER_ENDOFSELECTION )
282 		{
283             String sFieldName(m_pListCell->GetSelectEntry());
284             OConnectionLineDataVec* pLines = m_pConnData->GetConnLineDataList();
285             if ( pLines->size() <= static_cast<sal_uInt32>(nRow) )
286             {
287                 pLines->push_back(new OConnectionLineData());
288                 nRow = pLines->size() - 1;
289             }
290 
291             OConnectionLineDataRef pConnLineData = (*pLines)[nRow];
292 
293 			switch( getColumnIdent( GetCurColumnId() ) )
294 			{
295 			case SOURCE_COLUMN:
296 				pConnLineData->SetSourceFieldName( sFieldName );
297 				break;
298 			case DEST_COLUMN:
299 				pConnLineData->SetDestFieldName( sFieldName );
300 				break;
301 			}
302 		}
303 
304 		return sal_True;
305 	}
306 	//------------------------------------------------------------------------------
307 	sal_uInt16 ORelationControl::getColumnIdent( sal_uInt16 _nColId ) const
308 	{
309 		sal_uInt16 nId = _nColId;
310 		if ( m_pConnData->getReferencingTable() != m_pBoxControl->getReferencingTable() )
311 			nId = ( _nColId == SOURCE_COLUMN) ? DEST_COLUMN : SOURCE_COLUMN;
312 		return nId;
313 	}
314 
315 	//------------------------------------------------------------------------------
316 	String ORelationControl::GetCellText( long nRow, sal_uInt16 nColId ) const
317 	{
318 		DBG_CHKTHIS(ORelationControl,NULL);
319 		String sText;
320 		if ( m_pConnData->GetConnLineDataList()->size() > static_cast<size_t>(nRow) )
321 		{
322 			OConnectionLineDataRef pConnLineData = (*m_pConnData->GetConnLineDataList())[nRow];
323 			switch( getColumnIdent( nColId ) )
324 			{
325 			case SOURCE_COLUMN:
326 				sText  = pConnLineData->GetSourceFieldName();
327 				break;
328 			case DEST_COLUMN:
329 				sText  = pConnLineData->GetDestFieldName();
330 				break;
331 			}
332 		}
333 		return sText;
334 	}
335 
336 	//------------------------------------------------------------------------------
337 	void ORelationControl::InitController( CellControllerRef& /*rController*/, long nRow, sal_uInt16 nColumnId )
338 	{
339 		DBG_CHKTHIS(ORelationControl,NULL);
340 
341 		rtl::OString sHelpId( HID_RELATIONDIALOG_LEFTFIELDCELL );
342 
343 		Reference< XPropertySet> xDef;
344 		switch ( getColumnIdent(nColumnId) )
345 		{
346 			case SOURCE_COLUMN:
347 				xDef	= m_xSourceDef;
348 				sHelpId = HID_RELATIONDIALOG_LEFTFIELDCELL;
349 				break;
350 			case DEST_COLUMN:
351 				xDef	= m_xDestDef;
352 				sHelpId = HID_RELATIONDIALOG_RIGHTFIELDCELL;
353 				break;
354 			default:
355 				//  ?????????
356 				break;
357 		}
358 
359 		if ( xDef.is() )
360 		{
361 			fillListBox(xDef,nRow,nColumnId);
362 			String sName = GetCellText( nRow, nColumnId );
363 			m_pListCell->SelectEntry( sName );
364             if ( m_pListCell->GetSelectEntry() != sName )
365             {
366                 m_pListCell->InsertEntry( sName );
367                 m_pListCell->SelectEntry( sName );
368             }
369 
370 			m_pListCell->SetHelpId(sHelpId);
371 		}
372 	}
373 
374 	//------------------------------------------------------------------------------
375 	CellController* ORelationControl::GetController( long /*nRow*/, sal_uInt16 /*nColumnId*/ )
376 	{
377 		DBG_CHKTHIS(ORelationControl,NULL);
378 		return new ListBoxCellController( m_pListCell.get() );
379 	}
380 
381 	//------------------------------------------------------------------------------
382 	sal_Bool ORelationControl::SeekRow( long nRow )
383 	{
384 		DBG_CHKTHIS(ORelationControl,NULL);
385 		m_nDataPos = nRow;
386 		return sal_True;
387 	}
388 
389 	//------------------------------------------------------------------------------
390 	void ORelationControl::PaintCell( OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
391 	{
392 		DBG_CHKTHIS(ORelationControl,NULL);
393 		String aText  =const_cast< ORelationControl*>(this)->GetCellText( m_nDataPos, nColumnId );
394 
395 		Point aPos( rRect.TopLeft() );
396 		Size aTextSize( GetDataWindow().GetTextHeight(),GetDataWindow().GetTextWidth( aText ));
397 
398 		if( aPos.X() < rRect.Right() || aPos.X() + aTextSize.Width() > rRect.Right() ||
399 			aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
400 			rDev.SetClipRegion( rRect );
401 
402 		rDev.DrawText( aPos, aText );
403 
404 		if( rDev.IsClipRegion() )
405 			rDev.SetClipRegion();
406 	}
407 	// -----------------------------------------------------------------------------
408 	void ORelationControl::fillListBox(const Reference< XPropertySet>& _xDest,long /*_nRow*/,sal_uInt16 /*nColumnId*/)
409 	{
410 		m_pListCell->Clear();
411 		try
412 		{
413 			if ( _xDest.is() )
414 			{
415 				//sal_Int32 nRows = GetRowCount();
416 				Reference<XColumnsSupplier> xSup(_xDest,UNO_QUERY);
417 				Reference<XNameAccess> xColumns = xSup->getColumns();
418 				Sequence< ::rtl::OUString> aNames = xColumns->getElementNames();
419 				const ::rtl::OUString* pIter = aNames.getConstArray();
420 				const ::rtl::OUString* pEnd = pIter + aNames.getLength();
421 				for(;pIter != pEnd;++pIter)
422 				{
423 					m_pListCell->InsertEntry( *pIter );
424 				}
425 				m_pListCell->InsertEntry(String(), 0);
426 			}
427 		}
428         catch( const Exception& )
429         {
430             DBG_UNHANDLED_EXCEPTION();
431         }
432 	}
433 	// -----------------------------------------------------------------------------
434 	void ORelationControl::setWindowTables(const OTableWindow* _pSource,const OTableWindow* _pDest)
435 	{
436 		// wenn ich hier gerade editiere, ausblenden
437 		sal_Bool bWasEditing = IsEditing();
438 		if ( bWasEditing )
439 			DeactivateCell();
440 
441 		if ( _pSource && _pDest )
442 		{
443 			m_xSourceDef = _pSource->GetTable();
444 			SetColumnTitle(1, _pSource->GetName());
445 
446 
447 			m_xDestDef = _pDest->GetTable();
448 			SetColumnTitle(2, _pDest->GetName());
449 
450 			const OJoinTableView* pView = _pSource->getTableView();
451 			OTableConnection* pConn = pView->GetTabConn(_pSource,_pDest);
452 			if ( pConn && !m_pConnData->GetConnLineDataList()->empty() )
453 			{
454 				m_pConnData->CopyFrom(*pConn->GetData());
455 				m_pBoxControl->getContainer()->notifyConnectionChange();
456 			}
457 			else
458 			{
459 				// no connection found so we clear our data
460 				OConnectionLineDataVec* pLines = m_pConnData->GetConnLineDataList();
461 				::std::for_each(pLines->begin(),
462 								pLines->end(),
463 								OUnaryRefFunctor<OConnectionLineData>( ::std::mem_fun(&OConnectionLineData::Reset))
464 								);
465 
466 				m_pConnData->setReferencingTable(_pSource->GetData());
467 				m_pConnData->setReferencedTable(_pDest->GetData());
468 			}
469 			m_pConnData->normalizeLines();
470 
471 		}
472 		// neu zeichnen
473 		Invalidate();
474 
475 		if ( bWasEditing )
476 		{
477 			GoToRow(0);
478 			ActivateCell();
479 		}
480 	}
481 	//------------------------------------------------------------------------
482 	void ORelationControl::CellModified()
483 	{
484 		DBG_CHKTHIS(ORelationControl,NULL);
485 		EditBrowseBox::CellModified();
486 		SaveModified();
487 		static_cast<OTableListBoxControl*>(GetParent())->NotifyCellChange();
488 	}
489 	//========================================================================
490 	// class OTableListBoxControl
491 DBG_NAME(OTableListBoxControl)
492 
493 //========================================================================
494 
495 OTableListBoxControl::OTableListBoxControl(  Window* _pParent
496 										    ,const ResId& _rResId
497 										    ,const OJoinTableView::OTableWindowMap* _pTableMap
498 										    ,IRelationControlInterface* _pParentDialog)
499 	 : Window(_pParent,_rResId)
500 	 , m_aFL_InvolvedTables(    this, ResId(FL_INVOLVED_TABLES,*_rResId.GetResMgr()))
501 	 , m_lmbLeftTable(			this, ResId(LB_LEFT_TABLE,*_rResId.GetResMgr()))
502 	 , m_lmbRightTable(			this, ResId(LB_RIGHT_TABLE,*_rResId.GetResMgr()))
503 	 , m_aFL_InvolvedFields(    this, ResId(FL_INVOLVED_FIELDS,*_rResId.GetResMgr()))
504 	 , m_pTableMap(_pTableMap)
505 	 , m_pParentDialog(_pParentDialog)
506 	{
507 		m_pRC_Tables = new ORelationControl( this,m_pTableMap );
508 		m_pRC_Tables->SetHelpId(HID_RELDLG_KEYFIELDS);
509 		m_pRC_Tables->Init( );
510         m_pRC_Tables->SetZOrder(&m_lmbRightTable, WINDOW_ZORDER_BEHIND);
511 
512         lateUIInit();
513 
514 		Link aLink(LINK(this, OTableListBoxControl, OnTableChanged));
515 		m_lmbLeftTable.SetSelectHdl(aLink);
516 		m_lmbRightTable.SetSelectHdl(aLink);
517 
518 		FreeResource();
519 		DBG_CTOR(OTableListBoxControl,NULL);
520 	}
521 	// -----------------------------------------------------------------------------
522 	OTableListBoxControl::~OTableListBoxControl()
523 	{
524 		ORelationControl* pTemp = m_pRC_Tables;
525 		m_pRC_Tables = NULL;
526 		delete pTemp;
527         DBG_DTOR(OTableListBoxControl,NULL);
528     }
529 	// -----------------------------------------------------------------------------
530 	void OTableListBoxControl::fillListBoxes()
531 	{
532 		DBG_ASSERT( !m_pTableMap->empty(), "OTableListBoxControl::fillListBoxes: no table window!");
533 		OTableWindow* pInitialLeft = NULL;
534 		OTableWindow* pInitialRight = NULL;
535 
536 		// die Namen aller TabWins einsammeln
537 		OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->begin();
538         OJoinTableView::OTableWindowMap::const_iterator aEnd = m_pTableMap->end();
539 		for(;aIter != aEnd;++aIter)
540 		{
541 			m_lmbLeftTable.InsertEntry(aIter->first);
542 			m_lmbRightTable.InsertEntry(aIter->first);
543 
544 			if (!pInitialLeft)
545 			{
546 				pInitialLeft = aIter->second;
547 				m_strCurrentLeft = aIter->first;
548 			}
549 			else if (!pInitialRight)
550 			{
551 				pInitialRight = aIter->second;
552 				m_strCurrentRight = aIter->first;
553 			}
554 		} // for(;aIter != m_pTableMap->end();++aIter)
555 
556         if ( !pInitialRight )
557         {
558             pInitialRight = pInitialLeft;
559 			m_strCurrentRight = m_strCurrentLeft;
560         }
561 
562 		// die entsprechenden Defs an mein Controls
563 		m_pRC_Tables->setWindowTables(pInitialLeft,pInitialRight);
564 
565 		// die in einer ComboBox ausgewaehlte Tabelle darf nicht in der anderen zur Verfuegung stehen
566 
567 		if ( m_pTableMap->size() > 2 )
568 		{
569 			m_lmbLeftTable.RemoveEntry(m_strCurrentRight);
570 			m_lmbRightTable.RemoveEntry(m_strCurrentLeft);
571 		}
572 
573 		// links das erste, rechts das zweite selektieren
574 		m_lmbLeftTable.SelectEntry(m_strCurrentLeft);
575 		m_lmbRightTable.SelectEntry(m_strCurrentRight);
576 
577 		m_lmbLeftTable.GrabFocus();
578 	}
579 	// -----------------------------------------------------------------------------
580 	IMPL_LINK( OTableListBoxControl, OnTableChanged, ListBox*, pListBox )
581 	{
582 		String strSelected(pListBox->GetSelectEntry());
583 		OTableWindow* pLeft		= NULL;
584 		OTableWindow* pRight	= NULL;
585 
586 		// eine Sonderbehandlung : wenn es nur zwei Tabellen gibt, muss ich bei Wechsel in einer LB auch in der anderen umschalten
587 		if ( m_pTableMap->size() == 2 )
588 		{
589 			ListBox* pOther;
590 			if ( pListBox == &m_lmbLeftTable )
591 				pOther = &m_lmbRightTable;
592 			else
593 				pOther = &m_lmbLeftTable;
594 			pOther->SelectEntryPos(1 - pOther->GetSelectEntryPos());
595 
596 			OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->begin();
597 			OTableWindow* pFirst = aIter->second;
598 			++aIter;
599 			OTableWindow* pSecond = aIter->second;
600 
601 			if ( m_lmbLeftTable.GetSelectEntry() == String(pFirst->GetName()) )
602 			{
603 				pLeft	= pFirst;
604 				pRight	= pSecond;
605 			}
606 			else
607 			{
608 				pLeft	= pSecond;
609 				pRight	= pFirst;
610 			}
611 		}
612 		else
613 		{
614 			// zuerst brauche ich die TableDef zur Tabelle, dazu das TabWin
615 			OJoinTableView::OTableWindowMap::const_iterator aFind = m_pTableMap->find(strSelected);
616 			OTableWindow* pLoop = NULL;
617 			if( aFind != m_pTableMap->end() )
618 				pLoop = aFind->second;
619 			DBG_ASSERT(pLoop != NULL, "ORelationDialog::OnTableChanged : ungueltiger Eintrag in ListBox !");
620 				// da ich die ListBoxen selber mit eben diesen Tabellennamen, mit denen ich sie jetzt vergleiche, gefuellt habe,
621 				// MUSS ich strSelected finden
622 			if (pListBox == &m_lmbLeftTable)
623 			{
624 				// den vorher links selektierten Eintrag wieder rein rechts
625 				m_lmbRightTable.InsertEntry(m_strCurrentLeft);
626 				// und den jetzt selektierten raus
627 				m_lmbRightTable.RemoveEntry(strSelected);
628 				m_strCurrentLeft	= strSelected;
629 
630 				pLeft = pLoop;
631 
632 				OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_lmbRightTable.GetSelectEntry());
633 				OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
634 				if ( aIter != m_pTableMap->end() )
635 					pRight = aIter->second;
636 
637 				m_lmbLeftTable.GrabFocus();
638 			}
639 			else
640 			{
641 				// den vorher rechts selektierten Eintrag wieder rein links
642 				m_lmbLeftTable.InsertEntry(m_strCurrentRight);
643 				// und den jetzt selektierten raus
644 				m_lmbLeftTable.RemoveEntry(strSelected);
645 				m_strCurrentRight = strSelected;
646 
647 				pRight = pLoop;
648 				OJoinTableView::OTableWindowMap::const_iterator aIter = m_pTableMap->find(m_lmbLeftTable.GetSelectEntry());
649 				OSL_ENSURE( aIter != m_pTableMap->end(), "Invalid name");
650 				if ( aIter != m_pTableMap->end() )
651 					pLeft = aIter->second;
652 			}
653 		}
654 
655 		pListBox->GrabFocus();
656 
657 		m_pRC_Tables->setWindowTables(pLeft,pRight);
658 
659 		NotifyCellChange();
660 		return 0;
661 	}
662 	// -----------------------------------------------------------------------------
663 	void OTableListBoxControl::NotifyCellChange()
664 	{
665 		// den Ok-Button en- oder disablen, je nachdem, ob ich eine gueltige Situation habe
666         TTableConnectionData::value_type pConnData = m_pRC_Tables->getData();
667 		const OConnectionLineDataVec* pLines = pConnData->GetConnLineDataList();
668 		m_pParentDialog->setValid(!pLines->empty());
669 
670 		if ( pLines->size() >= static_cast<sal_uInt32>(m_pRC_Tables->GetRowCount()) )
671 		{
672 			m_pRC_Tables->DeactivateCell();
673 			m_pRC_Tables->RowInserted(m_pRC_Tables->GetRowCount(), pLines->size() - static_cast<sal_uInt32>(m_pRC_Tables->GetRowCount()) + 1, sal_True);
674 			m_pRC_Tables->ActivateCell();
675 		}
676 	}
677 	// -----------------------------------------------------------------------------
678 	void fillEntryAndDisable(ListBox& _rListBox,const String& _sEntry)
679 	{
680 		_rListBox.InsertEntry(_sEntry);
681 		_rListBox.SelectEntryPos(0);
682 		_rListBox.Disable();
683 	}
684 	// -----------------------------------------------------------------------------
685     void OTableListBoxControl::fillAndDisable(const TTableConnectionData::value_type& _pConnectionData)
686 	{
687 		fillEntryAndDisable(m_lmbLeftTable,_pConnectionData->getReferencingTable()->GetWinName());
688 		fillEntryAndDisable(m_lmbRightTable,_pConnectionData->getReferencedTable()->GetWinName());
689 	}
690 	// -----------------------------------------------------------------------------
691 	void OTableListBoxControl::Init(const TTableConnectionData::value_type& _pConnData)
692 	{
693 		m_pRC_Tables->Init(_pConnData);
694 	}
695 	// -----------------------------------------------------------------------------
696 	void OTableListBoxControl::lateUIInit(Window* _pTableSeparator)
697 	{
698         const sal_Int32 nDiff = LogicToPixel( Point(0,6), MAP_APPFONT ).Y();
699         Point aDlgPoint = LogicToPixel( Point(12,43), MAP_APPFONT );
700         if ( _pTableSeparator )
701         {
702             _pTableSeparator->SetZOrder(&m_lmbRightTable, WINDOW_ZORDER_BEHIND);
703             m_pRC_Tables->SetZOrder(_pTableSeparator, WINDOW_ZORDER_BEHIND);
704             //aDlgPoint = m_pTableSeparator->GetPosPixel() + Point(0,aSize.Height()) + LogicToPixel( Point(0,6), MAP_APPFONT );
705             _pTableSeparator->SetPosPixel(Point(0,m_aFL_InvolvedFields.GetPosPixel().Y()));
706             const Size aSize = _pTableSeparator->GetSizePixel();
707             aDlgPoint.Y() = _pTableSeparator->GetPosPixel().Y() + aSize.Height();
708             m_aFL_InvolvedFields.SetPosPixel(Point(m_aFL_InvolvedFields.GetPosPixel().X(),aDlgPoint.Y()));
709             aDlgPoint.Y() += nDiff + m_aFL_InvolvedFields.GetSizePixel().Height();
710         }
711         //////////////////////////////////////////////////////////////////////
712 		// positing BrowseBox control
713         const Size aCurrentSize = GetSizePixel();
714 		Size aDlgSize = LogicToPixel( Size(24,0), MAP_APPFONT );
715 		aDlgSize.Width() = aCurrentSize.Width() - aDlgSize.Width();
716         aDlgSize.Height() = aCurrentSize.Height() - aDlgPoint.Y() - nDiff;
717 
718 		m_pRC_Tables->SetPosSizePixel( aDlgPoint, aDlgSize );
719 		m_pRC_Tables->Show();
720 
721         lateInit();
722     }
723     // -----------------------------------------------------------------------------
724 	void OTableListBoxControl::lateInit()
725 	{
726 		m_pRC_Tables->lateInit();
727 	}
728 	// -----------------------------------------------------------------------------
729 	sal_Bool OTableListBoxControl::SaveModified()
730 	{
731 		sal_Bool bRet = m_pRC_Tables->SaveModified();
732 		m_pRC_Tables->getData()->normalizeLines();
733 		return bRet;
734 	}
735 	// -----------------------------------------------------------------------------
736 	TTableWindowData::value_type OTableListBoxControl::getReferencingTable()	const
737 	{
738         return m_pRC_Tables->getData()->getReferencingTable();
739 	}
740 	// -----------------------------------------------------------------------------
741     void OTableListBoxControl::enableRelation(bool _bEnable)
742     {
743         if ( !_bEnable )
744             PostUserEvent(LINK(m_pRC_Tables, ORelationControl, AsynchDeactivate));
745         m_pRC_Tables->Enable(_bEnable);
746 
747     }
748 	// -----------------------------------------------------------------------------
749 }
750 // -----------------------------------------------------------------------------
751 
752