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