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