1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_dbaccess.hxx"
26*b1cdbd2cSJim Jagielski #ifndef DBAUI_TABLECONNECTION_HXX
27*b1cdbd2cSJim Jagielski #include "TableConnection.hxx"
28*b1cdbd2cSJim Jagielski #endif
29*b1cdbd2cSJim Jagielski #ifndef DBAUI_CONNECTIONLINE_HXX
30*b1cdbd2cSJim Jagielski #include "ConnectionLine.hxx"
31*b1cdbd2cSJim Jagielski #endif
32*b1cdbd2cSJim Jagielski #ifndef DBAUI_TABLECONNECTIONDATA_HXX
33*b1cdbd2cSJim Jagielski #include "TableConnectionData.hxx"
34*b1cdbd2cSJim Jagielski #endif
35*b1cdbd2cSJim Jagielski #ifndef DBAUI_JOINTABLEVIEW_HXX
36*b1cdbd2cSJim Jagielski #include "JoinTableView.hxx"
37*b1cdbd2cSJim Jagielski #endif
38*b1cdbd2cSJim Jagielski #ifndef _COMPHELPER_STLTYPES_HXX_
39*b1cdbd2cSJim Jagielski #include <comphelper/stl_types.hxx>
40*b1cdbd2cSJim Jagielski #endif
41*b1cdbd2cSJim Jagielski #ifndef DBACCESS_CONNECTIONLINEACCESS_HXX
42*b1cdbd2cSJim Jagielski #include "ConnectionLineAccess.hxx"
43*b1cdbd2cSJim Jagielski #endif
44*b1cdbd2cSJim Jagielski #include <algorithm>
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski 
47*b1cdbd2cSJim Jagielski using namespace dbaui;
48*b1cdbd2cSJim Jagielski using namespace comphelper;
49*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::uno;
50*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::accessibility;
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski //========================================================================
53*b1cdbd2cSJim Jagielski // class OTableConnection
54*b1cdbd2cSJim Jagielski //========================================================================
55*b1cdbd2cSJim Jagielski namespace dbaui
56*b1cdbd2cSJim Jagielski {
DBG_NAME(OTableConnection)57*b1cdbd2cSJim Jagielski 	DBG_NAME(OTableConnection)
58*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
59*b1cdbd2cSJim Jagielski     OTableConnection::OTableConnection( OJoinTableView* _pContainer,const TTableConnectionData::value_type& _pTabConnData )
60*b1cdbd2cSJim Jagielski 		:Window(_pContainer)
61*b1cdbd2cSJim Jagielski 		,m_pData( _pTabConnData )
62*b1cdbd2cSJim Jagielski 		,m_pParent( _pContainer )
63*b1cdbd2cSJim Jagielski 		,m_bSelected( sal_False )
64*b1cdbd2cSJim Jagielski 	{
65*b1cdbd2cSJim Jagielski 		DBG_CTOR(OTableConnection,NULL);
66*b1cdbd2cSJim Jagielski 		Init();
67*b1cdbd2cSJim Jagielski 		Show();
68*b1cdbd2cSJim Jagielski 	}
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
OTableConnection(const OTableConnection & _rConn)71*b1cdbd2cSJim Jagielski 	OTableConnection::OTableConnection( const OTableConnection& _rConn ) : Window(_rConn.m_pParent)
72*b1cdbd2cSJim Jagielski         ,m_pData(_rConn.GetData()->NewInstance())
73*b1cdbd2cSJim Jagielski 	{
74*b1cdbd2cSJim Jagielski 		DBG_CTOR(OTableConnection,NULL);
75*b1cdbd2cSJim Jagielski 		*this = _rConn;
76*b1cdbd2cSJim Jagielski 	}
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
Init()79*b1cdbd2cSJim Jagielski 	void OTableConnection::Init()
80*b1cdbd2cSJim Jagielski 	{
81*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////
82*b1cdbd2cSJim Jagielski 		// Linienliste mit Defaults initialisieren
83*b1cdbd2cSJim Jagielski 		OConnectionLineDataVec* pLineData = GetData()->GetConnLineDataList();
84*b1cdbd2cSJim Jagielski 		OConnectionLineDataVec::const_iterator aIter = pLineData->begin();
85*b1cdbd2cSJim Jagielski         OConnectionLineDataVec::const_iterator aEnd = pLineData->end();
86*b1cdbd2cSJim Jagielski 		m_vConnLine.reserve(pLineData->size());
87*b1cdbd2cSJim Jagielski 		for(;aIter != aEnd;++aIter)
88*b1cdbd2cSJim Jagielski 			m_vConnLine.push_back( new OConnectionLine(this, *aIter) );
89*b1cdbd2cSJim Jagielski 	}
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
CreateConnLine(const OConnectionLine & rConnLine)92*b1cdbd2cSJim Jagielski 	OConnectionLine* OTableConnection::CreateConnLine( const OConnectionLine& rConnLine )
93*b1cdbd2cSJim Jagielski 	{
94*b1cdbd2cSJim Jagielski 		return new OConnectionLine( rConnLine );
95*b1cdbd2cSJim Jagielski 	}
96*b1cdbd2cSJim Jagielski 	// -----------------------------------------------------------------------------
clearLineData()97*b1cdbd2cSJim Jagielski 	void OTableConnection::clearLineData()
98*b1cdbd2cSJim Jagielski 	{
99*b1cdbd2cSJim Jagielski         ::std::vector<OConnectionLine*>::iterator aLineEnd = m_vConnLine.end();
100*b1cdbd2cSJim Jagielski 		for(::std::vector<OConnectionLine*>::iterator aLineIter = m_vConnLine.begin();aLineIter != aLineEnd;++aLineIter)
101*b1cdbd2cSJim Jagielski 			delete *aLineIter;
102*b1cdbd2cSJim Jagielski 		m_vConnLine.clear();
103*b1cdbd2cSJim Jagielski 	}
104*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
UpdateLineList()105*b1cdbd2cSJim Jagielski 	void OTableConnection::UpdateLineList()
106*b1cdbd2cSJim Jagielski 	{
107*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////
108*b1cdbd2cSJim Jagielski 		// Linienliste loeschen
109*b1cdbd2cSJim Jagielski 		clearLineData();
110*b1cdbd2cSJim Jagielski 
111*b1cdbd2cSJim Jagielski 		Init();
112*b1cdbd2cSJim Jagielski 	}
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
operator =(const OTableConnection & rConn)115*b1cdbd2cSJim Jagielski 	OTableConnection& OTableConnection::operator=( const OTableConnection& rConn )
116*b1cdbd2cSJim Jagielski 	{
117*b1cdbd2cSJim Jagielski 		if( &rConn == this )
118*b1cdbd2cSJim Jagielski 			return *this;
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski 		// Linienliste loeschen
121*b1cdbd2cSJim Jagielski 		clearLineData();
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski 		// Linienliste kopieren
124*b1cdbd2cSJim Jagielski 		if(! rConn.GetConnLineList()->empty() )
125*b1cdbd2cSJim Jagielski 		{
126*b1cdbd2cSJim Jagielski 			const ::std::vector<OConnectionLine*>* pLine = rConn.GetConnLineList();
127*b1cdbd2cSJim Jagielski 			::std::vector<OConnectionLine*>::const_iterator aIter = pLine->begin();
128*b1cdbd2cSJim Jagielski             ::std::vector<OConnectionLine*>::const_iterator aEnd = pLine->end();
129*b1cdbd2cSJim Jagielski 			m_vConnLine.reserve(pLine->size());
130*b1cdbd2cSJim Jagielski 			for(;aIter != aEnd;++aIter)
131*b1cdbd2cSJim Jagielski 				m_vConnLine.push_back( CreateConnLine( **aIter ));
132*b1cdbd2cSJim Jagielski 		}
133*b1cdbd2cSJim Jagielski 
134*b1cdbd2cSJim Jagielski 		// da mir die Daten nicht gehoeren, loesche ich die alten nicht
135*b1cdbd2cSJim Jagielski 		m_pData->CopyFrom(*rConn.GetData());
136*b1cdbd2cSJim Jagielski 			// CopyFrom ist virtuell, damit ist es kein Problem, wenn m_pData von einem von OTableConnectionData abgeleiteten Typ ist
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski 		m_bSelected = rConn.m_bSelected;
139*b1cdbd2cSJim Jagielski 		m_pParent = rConn.m_pParent;
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski 		return *this;
142*b1cdbd2cSJim Jagielski 	}
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski 
145*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
RecalcLines()146*b1cdbd2cSJim Jagielski 	bool OTableConnection::RecalcLines()
147*b1cdbd2cSJim Jagielski 	{
148*b1cdbd2cSJim Jagielski 		// call RecalcLines on each line
149*b1cdbd2cSJim Jagielski 		::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),::std::mem_fun(&OConnectionLine::RecalcLine));
150*b1cdbd2cSJim Jagielski 		return true;
151*b1cdbd2cSJim Jagielski 	}
152*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
GetSourceWin() const153*b1cdbd2cSJim Jagielski 	OTableWindow* OTableConnection::GetSourceWin() const
154*b1cdbd2cSJim Jagielski 	{
155*b1cdbd2cSJim Jagielski         TTableWindowData::value_type pRef = GetData()->getReferencingTable();
156*b1cdbd2cSJim Jagielski         OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
157*b1cdbd2cSJim Jagielski         if ( !pRet )
158*b1cdbd2cSJim Jagielski         {
159*b1cdbd2cSJim Jagielski             pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
160*b1cdbd2cSJim Jagielski         }
161*b1cdbd2cSJim Jagielski 		return pRet;
162*b1cdbd2cSJim Jagielski 	}
163*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
GetDestWin() const164*b1cdbd2cSJim Jagielski 	OTableWindow* OTableConnection::GetDestWin() const
165*b1cdbd2cSJim Jagielski 	{
166*b1cdbd2cSJim Jagielski         TTableWindowData::value_type pRef = GetData()->getReferencedTable();
167*b1cdbd2cSJim Jagielski         OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
168*b1cdbd2cSJim Jagielski         if ( !pRet )
169*b1cdbd2cSJim Jagielski         {
170*b1cdbd2cSJim Jagielski             pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
171*b1cdbd2cSJim Jagielski         }
172*b1cdbd2cSJim Jagielski 		return pRet;
173*b1cdbd2cSJim Jagielski 	}
174*b1cdbd2cSJim Jagielski 
175*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
Select()176*b1cdbd2cSJim Jagielski 	void OTableConnection::Select()
177*b1cdbd2cSJim Jagielski 	{
178*b1cdbd2cSJim Jagielski 		m_bSelected = sal_True;
179*b1cdbd2cSJim Jagielski 		m_pParent->Invalidate( GetBoundingRect(), INVALIDATE_NOCHILDREN);
180*b1cdbd2cSJim Jagielski 	}
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
Deselect()183*b1cdbd2cSJim Jagielski 	void OTableConnection::Deselect()
184*b1cdbd2cSJim Jagielski 	{
185*b1cdbd2cSJim Jagielski 		m_bSelected = sal_False;
186*b1cdbd2cSJim Jagielski 		InvalidateConnection();
187*b1cdbd2cSJim Jagielski 	}
188*b1cdbd2cSJim Jagielski 
189*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
CheckHit(const Point & rMousePos) const190*b1cdbd2cSJim Jagielski 	sal_Bool OTableConnection::CheckHit( const Point& rMousePos ) const
191*b1cdbd2cSJim Jagielski 	{
192*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////
193*b1cdbd2cSJim Jagielski 		// check if the point hit our line
194*b1cdbd2cSJim Jagielski 		::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(m_vConnLine.begin(),
195*b1cdbd2cSJim Jagielski 																		 m_vConnLine.end(),
196*b1cdbd2cSJim Jagielski 																		 ::std::bind2nd(TConnectionLineCheckHitFunctor(),rMousePos));
197*b1cdbd2cSJim Jagielski 		return aIter != m_vConnLine.end();
198*b1cdbd2cSJim Jagielski 	}
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
InvalidateConnection()201*b1cdbd2cSJim Jagielski 	bool OTableConnection::InvalidateConnection()
202*b1cdbd2cSJim Jagielski 	{
203*b1cdbd2cSJim Jagielski 		Rectangle rcBounding = GetBoundingRect();
204*b1cdbd2cSJim Jagielski 		rcBounding.Bottom() += 1;
205*b1cdbd2cSJim Jagielski 		rcBounding.Right() += 1;
206*b1cdbd2cSJim Jagielski 			// ich glaube, dass sich Invalidate und Draw(Rectangle) nicht konsistent verhalten : jedenfalls waere dadurch zu
207*b1cdbd2cSJim Jagielski 			// erklaeren, warum ohne diesen Fake hier beim Loeschen einer Connection ein Strich an ihrem unteren Ende stehen bleibt :
208*b1cdbd2cSJim Jagielski 			// Invalidate erfasst dabei offensichtlich eine Pixelzeile weniger als Draw.
209*b1cdbd2cSJim Jagielski 			// Oder alles haengt ganz anders zusammen ... jedenfalls klappt es so ...
210*b1cdbd2cSJim Jagielski 		m_pParent->Invalidate( rcBounding, INVALIDATE_NOCHILDREN );
211*b1cdbd2cSJim Jagielski 
212*b1cdbd2cSJim Jagielski 		return true;
213*b1cdbd2cSJim Jagielski 	}
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
GetBoundingRect() const216*b1cdbd2cSJim Jagielski 	Rectangle OTableConnection::GetBoundingRect() const
217*b1cdbd2cSJim Jagielski 	{
218*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////
219*b1cdbd2cSJim Jagielski 		// Aus allen Linien das umgebende Rechteck bestimmen
220*b1cdbd2cSJim Jagielski 		Rectangle aBoundingRect( Point(0,0), Point(0,0) );
221*b1cdbd2cSJim Jagielski 		Rectangle aTempRect;
222*b1cdbd2cSJim Jagielski         ::std::vector<OConnectionLine*>::const_iterator aEnd = m_vConnLine.end();
223*b1cdbd2cSJim Jagielski 		for(::std::vector<OConnectionLine*>::const_iterator aIter = m_vConnLine.begin();aIter != aEnd;++aIter)
224*b1cdbd2cSJim Jagielski 		{
225*b1cdbd2cSJim Jagielski 			aTempRect = (*aIter)->GetBoundingRect();
226*b1cdbd2cSJim Jagielski 
227*b1cdbd2cSJim Jagielski 			//////////////////////////////////////////////////////////////////////
228*b1cdbd2cSJim Jagielski 			// Ist das BoundingRect dieser Linie gueltig?
229*b1cdbd2cSJim Jagielski 			if( (aTempRect.GetWidth()!=1) && (aTempRect.GetHeight()!=1) )
230*b1cdbd2cSJim Jagielski 			{
231*b1cdbd2cSJim Jagielski 				if( (aBoundingRect.GetWidth()==1) && (aBoundingRect.GetHeight()==1) )
232*b1cdbd2cSJim Jagielski 					aBoundingRect = aTempRect;
233*b1cdbd2cSJim Jagielski 				else
234*b1cdbd2cSJim Jagielski 					aBoundingRect.Union( aTempRect );
235*b1cdbd2cSJim Jagielski 			}
236*b1cdbd2cSJim Jagielski 		}
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski 		return aBoundingRect;
239*b1cdbd2cSJim Jagielski 	}
240*b1cdbd2cSJim Jagielski 
241*b1cdbd2cSJim Jagielski 	//------------------------------------------------------------------------
Draw(const Rectangle &)242*b1cdbd2cSJim Jagielski 	void OTableConnection::Draw( const Rectangle& /*rRect*/ )
243*b1cdbd2cSJim Jagielski 	{
244*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////
245*b1cdbd2cSJim Jagielski 		// Linien zeichnen
246*b1cdbd2cSJim Jagielski 		::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),TConnectionLineDrawFunctor(m_pParent));
247*b1cdbd2cSJim Jagielski 	}
248*b1cdbd2cSJim Jagielski 	// -----------------------------------------------------------------------------
249*b1cdbd2cSJim Jagielski }
250*b1cdbd2cSJim Jagielski 
251*b1cdbd2cSJim Jagielski 
252*b1cdbd2cSJim Jagielski 
253