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_TABLECONNECTION_HXX
27 #include "TableConnection.hxx"
28 #endif
29 #ifndef DBAUI_CONNECTIONLINE_HXX
30 #include "ConnectionLine.hxx"
31 #endif
32 #ifndef DBAUI_TABLECONNECTIONDATA_HXX
33 #include "TableConnectionData.hxx"
34 #endif
35 #ifndef DBAUI_JOINTABLEVIEW_HXX
36 #include "JoinTableView.hxx"
37 #endif
38 #ifndef _COMPHELPER_STLTYPES_HXX_
39 #include <comphelper/stl_types.hxx>
40 #endif
41 #ifndef DBACCESS_CONNECTIONLINEACCESS_HXX
42 #include "ConnectionLineAccess.hxx"
43 #endif
44 #include <algorithm>
45 
46 
47 using namespace dbaui;
48 using namespace comphelper;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::accessibility;
51 
52 //========================================================================
53 // class OTableConnection
54 //========================================================================
55 namespace dbaui
56 {
57 	DBG_NAME(OTableConnection)
58 	//------------------------------------------------------------------------
59     OTableConnection::OTableConnection( OJoinTableView* _pContainer,const TTableConnectionData::value_type& _pTabConnData )
60 		:Window(_pContainer)
61 		,m_pData( _pTabConnData )
62 		,m_pParent( _pContainer )
63 		,m_bSelected( sal_False )
64 	{
65 		DBG_CTOR(OTableConnection,NULL);
66 		Init();
67 		Show();
68 	}
69 
70 	//------------------------------------------------------------------------
71 	OTableConnection::OTableConnection( const OTableConnection& _rConn ) : Window(_rConn.m_pParent)
72         ,m_pData(_rConn.GetData()->NewInstance())
73 	{
74 		DBG_CTOR(OTableConnection,NULL);
75 		*this = _rConn;
76 	}
77 
78 	//------------------------------------------------------------------------
79 	void OTableConnection::Init()
80 	{
81 		//////////////////////////////////////////////////////////////////////
82 		// Linienliste mit Defaults initialisieren
83 		OConnectionLineDataVec* pLineData = GetData()->GetConnLineDataList();
84 		OConnectionLineDataVec::const_iterator aIter = pLineData->begin();
85         OConnectionLineDataVec::const_iterator aEnd = pLineData->end();
86 		m_vConnLine.reserve(pLineData->size());
87 		for(;aIter != aEnd;++aIter)
88 			m_vConnLine.push_back( new OConnectionLine(this, *aIter) );
89 	}
90 
91 	//------------------------------------------------------------------------
92 	OConnectionLine* OTableConnection::CreateConnLine( const OConnectionLine& rConnLine )
93 	{
94 		return new OConnectionLine( rConnLine );
95 	}
96 	// -----------------------------------------------------------------------------
97 	void OTableConnection::clearLineData()
98 	{
99         ::std::vector<OConnectionLine*>::iterator aLineEnd = m_vConnLine.end();
100 		for(::std::vector<OConnectionLine*>::iterator aLineIter = m_vConnLine.begin();aLineIter != aLineEnd;++aLineIter)
101 			delete *aLineIter;
102 		m_vConnLine.clear();
103 	}
104 	//------------------------------------------------------------------------
105 	void OTableConnection::UpdateLineList()
106 	{
107 		//////////////////////////////////////////////////////////////////////
108 		// Linienliste loeschen
109 		clearLineData();
110 
111 		Init();
112 	}
113 
114 	//------------------------------------------------------------------------
115 	OTableConnection& OTableConnection::operator=( const OTableConnection& rConn )
116 	{
117 		if( &rConn == this )
118 			return *this;
119 
120 		// Linienliste loeschen
121 		clearLineData();
122 
123 		// Linienliste kopieren
124 		if(! rConn.GetConnLineList()->empty() )
125 		{
126 			const ::std::vector<OConnectionLine*>* pLine = rConn.GetConnLineList();
127 			::std::vector<OConnectionLine*>::const_iterator aIter = pLine->begin();
128             ::std::vector<OConnectionLine*>::const_iterator aEnd = pLine->end();
129 			m_vConnLine.reserve(pLine->size());
130 			for(;aIter != aEnd;++aIter)
131 				m_vConnLine.push_back( CreateConnLine( **aIter ));
132 		}
133 
134 		// da mir die Daten nicht gehoeren, loesche ich die alten nicht
135 		m_pData->CopyFrom(*rConn.GetData());
136 			// CopyFrom ist virtuell, damit ist es kein Problem, wenn m_pData von einem von OTableConnectionData abgeleiteten Typ ist
137 
138 		m_bSelected = rConn.m_bSelected;
139 		m_pParent = rConn.m_pParent;
140 
141 		return *this;
142 	}
143 
144 
145 	//------------------------------------------------------------------------
146 	bool OTableConnection::RecalcLines()
147 	{
148 		// call RecalcLines on each line
149 		::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),::std::mem_fun(&OConnectionLine::RecalcLine));
150 		return true;
151 	}
152 	//------------------------------------------------------------------------
153 	OTableWindow* OTableConnection::GetSourceWin() const
154 	{
155         TTableWindowData::value_type pRef = GetData()->getReferencingTable();
156         OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
157         if ( !pRet )
158         {
159             pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
160         }
161 		return pRet;
162 	}
163 	//------------------------------------------------------------------------
164 	OTableWindow* OTableConnection::GetDestWin() const
165 	{
166         TTableWindowData::value_type pRef = GetData()->getReferencedTable();
167         OTableWindow* pRet = m_pParent->GetTabWindow( pRef->GetWinName() );
168         if ( !pRet )
169         {
170             pRet = m_pParent->GetTabWindow( pRef->GetComposedName() );
171         }
172 		return pRet;
173 	}
174 
175 	//------------------------------------------------------------------------
176 	void OTableConnection::Select()
177 	{
178 		m_bSelected = sal_True;
179 		m_pParent->Invalidate( GetBoundingRect(), INVALIDATE_NOCHILDREN);
180 	}
181 
182 	//------------------------------------------------------------------------
183 	void OTableConnection::Deselect()
184 	{
185 		m_bSelected = sal_False;
186 		InvalidateConnection();
187 	}
188 
189 	//------------------------------------------------------------------------
190 	sal_Bool OTableConnection::CheckHit( const Point& rMousePos ) const
191 	{
192 		//////////////////////////////////////////////////////////////////////
193 		// check if the point hit our line
194 		::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(m_vConnLine.begin(),
195 																		 m_vConnLine.end(),
196 																		 ::std::bind2nd(TConnectionLineCheckHitFunctor(),rMousePos));
197 		return aIter != m_vConnLine.end();
198 	}
199 
200 	//------------------------------------------------------------------------
201 	bool OTableConnection::InvalidateConnection()
202 	{
203 		Rectangle rcBounding = GetBoundingRect();
204 		rcBounding.Bottom() += 1;
205 		rcBounding.Right() += 1;
206 			// ich glaube, dass sich Invalidate und Draw(Rectangle) nicht konsistent verhalten : jedenfalls waere dadurch zu
207 			// erklaeren, warum ohne diesen Fake hier beim Loeschen einer Connection ein Strich an ihrem unteren Ende stehen bleibt :
208 			// Invalidate erfasst dabei offensichtlich eine Pixelzeile weniger als Draw.
209 			// Oder alles haengt ganz anders zusammen ... jedenfalls klappt es so ...
210 		m_pParent->Invalidate( rcBounding, INVALIDATE_NOCHILDREN );
211 
212 		return true;
213 	}
214 
215 	//------------------------------------------------------------------------
216 	Rectangle OTableConnection::GetBoundingRect() const
217 	{
218 		//////////////////////////////////////////////////////////////////////
219 		// Aus allen Linien das umgebende Rechteck bestimmen
220 		Rectangle aBoundingRect( Point(0,0), Point(0,0) );
221 		Rectangle aTempRect;
222         ::std::vector<OConnectionLine*>::const_iterator aEnd = m_vConnLine.end();
223 		for(::std::vector<OConnectionLine*>::const_iterator aIter = m_vConnLine.begin();aIter != aEnd;++aIter)
224 		{
225 			aTempRect = (*aIter)->GetBoundingRect();
226 
227 			//////////////////////////////////////////////////////////////////////
228 			// Ist das BoundingRect dieser Linie gueltig?
229 			if( (aTempRect.GetWidth()!=1) && (aTempRect.GetHeight()!=1) )
230 			{
231 				if( (aBoundingRect.GetWidth()==1) && (aBoundingRect.GetHeight()==1) )
232 					aBoundingRect = aTempRect;
233 				else
234 					aBoundingRect.Union( aTempRect );
235 			}
236 		}
237 
238 		return aBoundingRect;
239 	}
240 
241 	//------------------------------------------------------------------------
242 	void OTableConnection::Draw( const Rectangle& /*rRect*/ )
243 	{
244 		//////////////////////////////////////////////////////////////////////
245 		// Linien zeichnen
246 		::std::for_each(m_vConnLine.begin(),m_vConnLine.end(),TConnectionLineDrawFunctor(m_pParent));
247 	}
248 	// -----------------------------------------------------------------------------
249 }
250 
251 
252 
253