Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "JoinTableView.hxx"
21 : #include <osl/diagnose.h>
22 : #include "querycontroller.hxx"
23 : #include "JoinDesignView.hxx"
24 : #include "dbu_qry.hrc"
25 : #include "TableWindow.hxx"
26 : #include "TableWindowListBox.hxx"
27 : #include "TableConnection.hxx"
28 : #include "TableConnectionData.hxx"
29 : #include "ConnectionLine.hxx"
30 : #include "ConnectionLineData.hxx"
31 : #include "browserids.hxx"
32 : #include <svl/urlbmk.hxx>
33 : #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
34 : #include "QueryMoveTabWinUndoAct.hxx"
35 : #include "QuerySizeTabWinUndoAct.hxx"
36 : #include <vcl/svapp.hxx>
37 : #include <vcl/settings.hxx>
38 : #include "TableWindowData.hxx"
39 : #include "JAccess.hxx"
40 : #include <com/sun/star/accessibility/XAccessible.hpp>
41 : #include <com/sun/star/accessibility/AccessibleRole.hpp>
42 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
43 : #include "UITools.hxx"
44 : #include <cppuhelper/exc_hlp.hxx>
45 : #include <comphelper/processfactory.hxx>
46 : #include <tools/diagnose_ex.h>
47 : #include <boost/bind.hpp>
48 : #include <boost/scoped_ptr.hpp>
49 : #include <algorithm>
50 : #include <functional>
51 :
52 : using namespace dbaui;
53 : using namespace ::com::sun::star::uno;
54 : using namespace ::com::sun::star::sdbc;
55 : using namespace ::com::sun::star::accessibility;
56 : using namespace ::com::sun::star::container;
57 : using namespace ::com::sun::star::lang;
58 :
59 : #define LINE_SIZE 50
60 : // Constants for the window layout
61 : #define TABWIN_SPACING_X 17
62 : #define TABWIN_SPACING_Y 17
63 :
64 : #define TABWIN_WIDTH_STD 120
65 : #define TABWIN_HEIGHT_STD 120
66 :
67 0 : OScrollWindowHelper::OScrollWindowHelper( vcl::Window* pParent) : Window( pParent)
68 : ,m_aHScrollBar( VclPtr<ScrollBar>::Create(this, WB_HSCROLL|WB_REPEAT|WB_DRAG) )
69 : ,m_aVScrollBar( VclPtr<ScrollBar>::Create(this, WB_VSCROLL|WB_REPEAT|WB_DRAG) )
70 : ,m_pCornerWindow(VclPtr<ScrollBarBox>::Create(this, WB_3DLOOK))
71 0 : ,m_pTableView(NULL)
72 : {
73 :
74 : // ScrollBars
75 :
76 0 : GetHScrollBar().SetRange( Range(0, 1000) );
77 0 : GetVScrollBar().SetRange( Range(0, 1000) );
78 :
79 0 : GetHScrollBar().SetLineSize( LINE_SIZE );
80 0 : GetVScrollBar().SetLineSize( LINE_SIZE );
81 :
82 0 : GetHScrollBar().Show();
83 0 : GetVScrollBar().Show();
84 0 : m_pCornerWindow->Show();
85 :
86 : // normally we should be SCROLL_PANE
87 0 : SetAccessibleRole(AccessibleRole::SCROLL_PANE);
88 0 : }
89 :
90 0 : OScrollWindowHelper::~OScrollWindowHelper()
91 : {
92 0 : disposeOnce();
93 0 : }
94 :
95 0 : void OScrollWindowHelper::dispose()
96 : {
97 0 : m_aHScrollBar.disposeAndClear();
98 0 : m_aVScrollBar.disposeAndClear();
99 0 : m_pCornerWindow.disposeAndClear();
100 0 : m_pTableView.clear();
101 0 : vcl::Window::dispose();
102 0 : }
103 :
104 0 : void OScrollWindowHelper::setTableView(OJoinTableView* _pTableView)
105 : {
106 0 : m_pTableView = _pTableView;
107 : // ScrollBars
108 0 : GetHScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
109 0 : GetVScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
110 0 : }
111 :
112 0 : void OScrollWindowHelper::resetRange(const Point& _aSize)
113 : {
114 0 : Point aPos = PixelToLogic(_aSize);
115 0 : GetHScrollBar().SetRange( Range(0, aPos.X() + TABWIN_SPACING_X) );
116 0 : GetVScrollBar().SetRange( Range(0, aPos.Y() + TABWIN_SPACING_Y) );
117 0 : }
118 :
119 0 : void OScrollWindowHelper::Resize()
120 : {
121 0 : Window::Resize();
122 :
123 0 : Size aTotalOutputSize = GetOutputSizePixel();
124 0 : long nHScrollHeight = GetHScrollBar().GetSizePixel().Height();
125 0 : long nVScrollWidth = GetVScrollBar().GetSizePixel().Width();
126 :
127 0 : GetHScrollBar().SetPosSizePixel(
128 0 : Point( 0, aTotalOutputSize.Height()-nHScrollHeight ),
129 0 : Size( aTotalOutputSize.Width()-nVScrollWidth, nHScrollHeight )
130 0 : );
131 :
132 0 : GetVScrollBar().SetPosSizePixel(
133 0 : Point( aTotalOutputSize.Width()-nVScrollWidth, 0 ),
134 0 : Size( nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight )
135 0 : );
136 :
137 0 : m_pCornerWindow->SetPosSizePixel(
138 0 : Point( aTotalOutputSize.Width() - nVScrollWidth, aTotalOutputSize.Height() - nHScrollHeight),
139 : Size( nVScrollWidth, nHScrollHeight )
140 0 : );
141 :
142 0 : GetHScrollBar().SetPageSize( aTotalOutputSize.Width() );
143 0 : GetHScrollBar().SetVisibleSize( aTotalOutputSize.Width() );
144 :
145 0 : GetVScrollBar().SetPageSize( aTotalOutputSize.Height() );
146 0 : GetVScrollBar().SetVisibleSize( aTotalOutputSize.Height() );
147 :
148 : // adjust the ranges of the scrollbars if necessary
149 0 : long lRange = GetHScrollBar().GetRange().Max() - GetHScrollBar().GetRange().Min();
150 0 : if (m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() > lRange)
151 0 : GetHScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() + GetHScrollBar().GetRange().Min());
152 :
153 0 : lRange = GetVScrollBar().GetRange().Max() - GetVScrollBar().GetRange().Min();
154 0 : if (m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() > lRange)
155 0 : GetVScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() + GetVScrollBar().GetRange().Min());
156 :
157 0 : m_pTableView->SetPosSizePixel(Point( 0, 0 ),Size( aTotalOutputSize.Width()-nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight ));
158 0 : }
159 :
160 : // class OJoinTableView
161 :
162 0 : OJoinTableView::OJoinTableView( vcl::Window* pParent, OJoinDesignView* pView )
163 : :Window( pParent,WB_BORDER )
164 : ,DropTargetHelper(this)
165 : ,m_aDragOffset( Point(0,0) )
166 : ,m_aScrollOffset( Point(0,0) )
167 : ,m_pDragWin( NULL )
168 : ,m_pSizingWin( NULL )
169 : ,m_pSelectedConn( NULL )
170 : ,m_bTrackingInitiallyMoved(false)
171 : ,m_pLastFocusTabWin(NULL)
172 : ,m_pView( pView )
173 0 : ,m_pAccessible(NULL)
174 : {
175 0 : SetSizePixel( Size(1000, 1000) );
176 :
177 0 : InitColors();
178 :
179 0 : m_aDragScrollIdle.SetIdleHdl(LINK(this, OJoinTableView, OnDragScrollTimer));
180 0 : }
181 :
182 0 : OJoinTableView::~OJoinTableView()
183 : {
184 0 : disposeOnce();
185 0 : }
186 :
187 0 : void OJoinTableView::dispose()
188 : {
189 0 : if( m_pAccessible )
190 : {
191 0 : m_pAccessible->clearTableView();
192 0 : m_pAccessible = NULL;
193 : }
194 : // delete lists
195 0 : clearLayoutInformation();
196 0 : m_pDragWin.clear();
197 0 : m_pSizingWin.clear();
198 0 : m_pSelectedConn.clear();
199 0 : m_pLastFocusTabWin.clear();
200 0 : m_pView.clear();
201 0 : vcl::Window::dispose();
202 0 : }
203 :
204 0 : IMPL_LINK( OJoinTableView, ScrollHdl, ScrollBar*, pScrollBar )
205 : {
206 : // move all windows
207 0 : ScrollPane( pScrollBar->GetDelta(), (pScrollBar == &GetHScrollBar()), false );
208 :
209 0 : return 0;
210 : }
211 :
212 0 : void OJoinTableView::Resize()
213 : {
214 0 : Window::Resize();
215 0 : m_aOutputSize = GetSizePixel();
216 :
217 : // tab win positions may not be up-to-date
218 0 : if (m_aTableMap.empty())
219 : // no tab wins ...
220 0 : return;
221 :
222 : // we have at least one table so resize it
223 0 : m_aScrollOffset.X() = GetHScrollBar().GetThumbPos();
224 0 : m_aScrollOffset.Y() = GetVScrollBar().GetThumbPos();
225 :
226 0 : OTableWindow* pCheck = m_aTableMap.begin()->second;
227 0 : Point aRealPos = pCheck->GetPosPixel();
228 0 : Point aAssumedPos = pCheck->GetData()->GetPosition() - GetScrollOffset();
229 :
230 0 : if (aRealPos == aAssumedPos)
231 : // all ok
232 0 : return;
233 :
234 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
235 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
236 0 : for(;aIter != aEnd;++aIter)
237 : {
238 0 : OTableWindow* pCurrent = aIter->second;
239 0 : Point aPos(pCurrent->GetData()->GetPosition() - GetScrollOffset());
240 0 : pCurrent->SetPosPixel(aPos);
241 : }
242 : }
243 :
244 0 : sal_uLong OJoinTableView::GetTabWinCount()
245 : {
246 0 : return m_aTableMap.size();
247 : }
248 :
249 0 : bool OJoinTableView::RemoveConnection( OTableConnection* _pConn,bool _bDelete )
250 : {
251 0 : DeselectConn(_pConn);
252 :
253 : // to force a redraw
254 0 : _pConn->InvalidateConnection();
255 :
256 0 : m_pView->getController().removeConnectionData( _pConn->GetData() );
257 :
258 : m_vTableConnection.erase(
259 0 : ::std::find(m_vTableConnection.begin(),m_vTableConnection.end(),_pConn) );
260 :
261 0 : modified();
262 0 : if ( m_pAccessible )
263 : m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
264 : makeAny(_pConn->GetAccessible()),
265 0 : Any());
266 0 : if ( _bDelete )
267 0 : _pConn->disposeOnce();
268 :
269 0 : return true;
270 : }
271 :
272 0 : OTableWindow* OJoinTableView::GetTabWindow( const OUString& rName )
273 : {
274 0 : OTableWindowMap::iterator aIter = m_aTableMap.find(rName);
275 :
276 0 : return aIter == m_aTableMap.end() ? nullptr : aIter->second;
277 : }
278 :
279 0 : TTableWindowData::value_type OJoinTableView::createTableWindowData(const OUString& _rComposedName
280 : ,const OUString& _sTableName
281 : ,const OUString& _rWinName)
282 : {
283 0 : TTableWindowData::value_type pData( CreateImpl(_rComposedName, _sTableName,_rWinName) );
284 0 : OJoinDesignView* pParent = getDesignView();
285 : try
286 : {
287 0 : if ( !pData->init(pParent->getController().getConnection(),allowQueries()) )
288 : {
289 0 : if ( pData->isValid() )
290 0 : onNoColumns_throw();
291 : else
292 0 : pData.reset();
293 : }
294 : }
295 0 : catch ( const SQLException& )
296 : {
297 : ::dbaui::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ),
298 0 : pParent, pParent->getController().getORB() );
299 : }
300 0 : catch( const WrappedTargetException& e )
301 : {
302 0 : SQLException aSql;
303 0 : if ( e.TargetException >>= aSql )
304 0 : ::dbaui::showError( ::dbtools::SQLExceptionInfo( aSql ), pParent, pParent->getController().getORB() );
305 : }
306 0 : catch( const Exception& )
307 : {
308 : DBG_UNHANDLED_EXCEPTION();
309 : }
310 0 : return pData;
311 : }
312 :
313 0 : OTableWindowData* OJoinTableView::CreateImpl(const OUString& _rComposedName
314 : ,const OUString& _sTableName
315 : ,const OUString& _rWinName)
316 : {
317 0 : return new OTableWindowData( NULL,_rComposedName,_sTableName, _rWinName );
318 : }
319 :
320 0 : void OJoinTableView::AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool /*bNewTable*/)
321 : {
322 : OSL_ENSURE(!_rComposedName.isEmpty(),"There must be a table name supplied!");
323 :
324 0 : TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName ));
325 :
326 : // insert new window in window list
327 0 : VclPtr<OTableWindow> pNewTabWin = createWindow( pNewTabWinData );
328 0 : if ( pNewTabWin->Init() )
329 : {
330 0 : m_pView->getController().getTableWindowData().push_back( pNewTabWinData);
331 : // when we already have a table with this name insert the full qualified one instead
332 0 : if(m_aTableMap.find(rWinName) != m_aTableMap.end())
333 0 : m_aTableMap[_rComposedName] = pNewTabWin;
334 : else
335 0 : m_aTableMap[rWinName] = pNewTabWin;
336 :
337 0 : SetDefaultTabWinPosSize( pNewTabWin );
338 0 : pNewTabWin->Show();
339 :
340 0 : modified();
341 0 : if ( m_pAccessible )
342 : m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
343 : Any(),
344 0 : makeAny(pNewTabWin->GetAccessible()));
345 : }
346 : else
347 : {
348 0 : pNewTabWin->clearListBox();
349 0 : pNewTabWin.disposeAndClear();
350 0 : }
351 0 : }
352 :
353 0 : void OJoinTableView::RemoveTabWin( OTableWindow* pTabWin )
354 : {
355 : // first delete all connections of this window to others
356 0 : bool bRemove = true;
357 0 : TTableWindowData::value_type pData = pTabWin->GetData();
358 0 : sal_Int32 nCount = m_vTableConnection.size();
359 0 : auto aIter = m_vTableConnection.rbegin();
360 0 : while(aIter != m_vTableConnection.rend() && bRemove)
361 : {
362 0 : OTableConnection* pTabConn = (*aIter);
363 0 : if(
364 0 : ( pData == pTabConn->GetData()->getReferencingTable()) ||
365 0 : ( pData == pTabConn->GetData()->getReferencedTable())
366 : )
367 : {
368 0 : bRemove = RemoveConnection( pTabConn ,true);
369 0 : aIter = m_vTableConnection.rbegin();
370 : }
371 : else
372 0 : ++aIter;
373 : }
374 :
375 : // then delete the window itself
376 0 : if ( bRemove )
377 : {
378 0 : if ( m_pAccessible )
379 : m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
380 : makeAny(pTabWin->GetAccessible()),Any()
381 0 : );
382 :
383 0 : pTabWin->Hide();
384 0 : OJoinController& rController = m_pView->getController();
385 0 : TTableWindowData::iterator aFind = ::std::find(rController.getTableWindowData().begin(), rController.getTableWindowData().end(), pData);
386 0 : if(aFind != rController.getTableWindowData().end())
387 : {
388 0 : rController.getTableWindowData().erase(aFind);
389 0 : rController.setModified(sal_True);
390 : }
391 :
392 0 : if ( !m_aTableMap.erase( pTabWin->GetWinName() ) )
393 0 : m_aTableMap.erase( pTabWin->GetComposedName() );
394 :
395 0 : if (pTabWin == m_pLastFocusTabWin)
396 0 : m_pLastFocusTabWin = NULL;
397 :
398 0 : pTabWin->clearListBox();
399 0 : pTabWin->disposeOnce();
400 : }
401 :
402 0 : if ( (sal_Int32)m_vTableConnection.size() < (nCount-1) ) // if some connections could be removed
403 0 : modified();
404 0 : }
405 :
406 : namespace
407 : {
408 0 : bool isScrollAllowed( OJoinTableView* _pView,long nDelta, bool bHoriz)
409 : {
410 : // adjust ScrollBar-Positions
411 0 : ScrollBar& rBar = bHoriz ? _pView->GetHScrollBar() : _pView->GetVScrollBar() ;
412 :
413 0 : long nOldThumbPos = rBar.GetThumbPos();
414 0 : long nNewThumbPos = nOldThumbPos + nDelta;
415 0 : if( nNewThumbPos < 0 )
416 0 : nNewThumbPos = 0;
417 0 : else if( nNewThumbPos > rBar.GetRangeMax() )
418 0 : nNewThumbPos = rBar.GetRangeMax();
419 :
420 0 : if ( bHoriz )
421 : {
422 0 : if( nNewThumbPos == _pView->GetScrollOffset().X() )
423 0 : return false;
424 : }
425 0 : else if ( nNewThumbPos == _pView->GetScrollOffset().Y() )
426 0 : return false;
427 :
428 0 : return true;
429 : }
430 0 : bool getMovementImpl(OJoinTableView* _pView,const Point& _rPoint,const Size& _rSize,long& _nScrollX,long& _nScrollY)
431 : {
432 0 : _nScrollY = _nScrollX = 0;
433 : // data about the tab win
434 0 : Point aUpperLeft = _rPoint;
435 : // normalize with respect to visibility
436 0 : aUpperLeft -= _pView->GetScrollOffset();
437 0 : Point aLowerRight(aUpperLeft.X() + _rSize.Width(), aUpperLeft.Y() + _rSize.Height());
438 :
439 : // data about ourself
440 0 : Size aSize = _pView->getRealOutputSize(); //GetOutputSizePixel();
441 :
442 0 : bool bVisible = true;
443 0 : bool bFitsHor = (aUpperLeft.X() >= 0) && (aLowerRight.X() <= aSize.Width());
444 0 : bool bFitsVert= (aUpperLeft.Y() >= 0) && (aLowerRight.Y() <= aSize.Height());
445 0 : if (!bFitsHor || !bFitsVert)
446 : {
447 0 : if (!bFitsHor)
448 : {
449 : // ensure the visibility of the right border
450 0 : if ( aLowerRight.X() > aSize.Width() )
451 0 : _nScrollX = aLowerRight.X() - aSize.Width() + TABWIN_SPACING_X;
452 :
453 : // ensure the visibility of the left border (higher priority)
454 0 : if ( aUpperLeft.X() < 0 )
455 0 : _nScrollX = aUpperLeft.X() - TABWIN_SPACING_X;
456 : }
457 :
458 0 : if (!bFitsVert)
459 : {
460 : // lower border
461 0 : if ( aLowerRight.Y() > aSize.Height() )
462 0 : _nScrollY = aLowerRight.Y() - aSize.Height() + TABWIN_SPACING_Y;
463 : // upper border
464 0 : if ( aUpperLeft.Y() < 0 )
465 0 : _nScrollY = aUpperLeft.Y() - TABWIN_SPACING_Y;
466 : }
467 :
468 0 : if ( _nScrollX ) // aSize.Width() > _rSize.Width() &&
469 0 : bVisible = isScrollAllowed(_pView,_nScrollX, true);
470 :
471 0 : if ( _nScrollY ) // aSize.Height() > _rSize.Height() &&
472 0 : bVisible = bVisible && isScrollAllowed(_pView,_nScrollY, false);
473 :
474 0 : if ( bVisible )
475 : {
476 0 : sal_Int32 nHRangeMax = _pView->GetHScrollBar().GetRangeMax();
477 0 : sal_Int32 nVRangeMax = _pView->GetVScrollBar().GetRangeMax();
478 :
479 0 : if ( aSize.Width() + _pView->GetHScrollBar().GetThumbPos() + _nScrollX > nHRangeMax )
480 0 : bVisible = false;
481 0 : if ( bVisible && aSize.Height() + _pView->GetVScrollBar().GetThumbPos() + _nScrollY > nVRangeMax )
482 0 : bVisible = false;
483 : }
484 : }
485 :
486 0 : return bVisible;
487 : }
488 : } // end of ano namespace
489 :
490 0 : bool OJoinTableView::isMovementAllowed(const Point& _rPoint,const Size& _rSize)
491 : {
492 : long nX,nY;
493 0 : return getMovementImpl(this,_rPoint,_rSize,nX,nY);
494 : }
495 :
496 0 : void OJoinTableView::EnsureVisible(const OTableWindow* _pWin)
497 : {
498 : // data about the tab win
499 0 : TTableWindowData::value_type pData = _pWin->GetData();
500 0 : EnsureVisible( pData->GetPosition() , pData->GetSize());
501 0 : Invalidate(InvalidateFlags::NoChildren);
502 0 : }
503 :
504 0 : void OJoinTableView::EnsureVisible(const Point& _rPoint,const Size& _rSize)
505 : {
506 : long nScrollX,nScrollY;
507 :
508 0 : if ( getMovementImpl(this,_rPoint,_rSize,nScrollX,nScrollY) )
509 : {
510 0 : bool bVisible = true;
511 0 : if (nScrollX)
512 0 : bVisible = ScrollPane(nScrollX, true, true);
513 :
514 0 : if (nScrollY && bVisible)
515 0 : ScrollPane(nScrollY, false, true);
516 : }
517 0 : }
518 :
519 0 : void OJoinTableView::SetDefaultTabWinPosSize( OTableWindow* pTabWin )
520 : {
521 : // determine position:
522 : // the window is divided into lines with height TABWIN_SPACING_Y+TABWIN_HEIGHT_STD.
523 : // Then for each line is checked, if there is space for another window.
524 : // If there is no space, the next line is checked.
525 0 : Size aOutSize = GetSizePixel();
526 0 : Point aNewPos( 0,0 );
527 0 : sal_uInt16 nRow = 0;
528 0 : bool bEnd = false;
529 0 : while( !bEnd )
530 : {
531 : // Set new position to start of line
532 0 : aNewPos.X() = TABWIN_SPACING_X;
533 0 : aNewPos.Y() = (nRow+1) * TABWIN_SPACING_Y;
534 :
535 : // determine rectangle for the corresponding line
536 0 : Rectangle aRowRect( Point(0,0), aOutSize );
537 0 : aRowRect.Top() = nRow * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD );
538 0 : aRowRect.Bottom() = (nRow+1) * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD );
539 :
540 : // check occupied areas of this line
541 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
542 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
543 0 : for(;aIter != aEnd;++aIter)
544 : {
545 0 : OTableWindow* pOtherTabWin = aIter->second;
546 0 : Rectangle aOtherTabWinRect( pOtherTabWin->GetPosPixel(), pOtherTabWin->GetSizePixel() );
547 :
548 0 : if(
549 0 : ( (aOtherTabWinRect.Top()>aRowRect.Top()) && (aOtherTabWinRect.Top()<aRowRect.Bottom()) ) ||
550 0 : ( (aOtherTabWinRect.Bottom()>aRowRect.Top()) && (aOtherTabWinRect.Bottom()<aRowRect.Bottom()) )
551 : )
552 : {
553 : // TabWin is in the line
554 0 : if( aOtherTabWinRect.Right()>aNewPos.X() )
555 0 : aNewPos.X() = aOtherTabWinRect.Right() + TABWIN_SPACING_X;
556 : }
557 : }
558 :
559 : // Is there space left in this line?
560 0 : if( (aNewPos.X()+TABWIN_WIDTH_STD)<aRowRect.Right() )
561 : {
562 0 : aNewPos.Y() = aRowRect.Top() + TABWIN_SPACING_Y;
563 0 : bEnd = true;
564 : }
565 : else
566 : {
567 0 : if( (aRowRect.Bottom()+aRowRect.GetHeight()) > aOutSize.Height() )
568 : {
569 : // insert it in the first row
570 0 : sal_Int32 nCount = m_aTableMap.size() % (nRow+1);
571 0 : ++nCount;
572 0 : aNewPos.Y() = nCount * TABWIN_SPACING_Y + (nCount-1)*CalcZoom(TABWIN_HEIGHT_STD);
573 0 : bEnd = true;
574 : }
575 : else
576 0 : nRow++;
577 :
578 : }
579 : }
580 :
581 : // determine size
582 0 : Size aNewSize( CalcZoom(TABWIN_WIDTH_STD), CalcZoom(TABWIN_HEIGHT_STD) );
583 :
584 : // check if the new position in inside the scrollbars ranges
585 0 : Point aBottom(aNewPos);
586 0 : aBottom.X() += aNewSize.Width();
587 0 : aBottom.Y() += aNewSize.Height();
588 :
589 0 : if(!GetHScrollBar().GetRange().IsInside(aBottom.X()))
590 0 : GetHScrollBar().SetRange( Range(0, aBottom.X()) );
591 0 : if(!GetVScrollBar().GetRange().IsInside(aBottom.Y()))
592 0 : GetVScrollBar().SetRange( Range(0, aBottom.Y()) );
593 :
594 0 : pTabWin->SetPosSizePixel( aNewPos, aNewSize );
595 0 : }
596 :
597 0 : void OJoinTableView::DataChanged(const DataChangedEvent& rDCEvt)
598 : {
599 0 : if (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
600 : {
601 : // consider the worst case: the colors changed, so adjust me
602 0 : InitColors();
603 0 : Invalidate(InvalidateFlags::NoChildren);
604 : // due to the Invalidate, the connections are redrawn, so that they are also pictured in the new colors
605 : }
606 0 : }
607 :
608 0 : void OJoinTableView::InitColors()
609 : {
610 : // the colors for the illustration should be the system colors
611 0 : StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
612 0 : SetBackground(Wallpaper(Color(aSystemStyle.GetDialogColor())));
613 0 : }
614 :
615 0 : void OJoinTableView::BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos )
616 : {
617 :
618 0 : if (m_pView->getController().isReadOnly())
619 0 : return;
620 :
621 0 : m_pDragWin = pTabWin;
622 0 : SetPointer(Pointer(PointerStyle::Move));
623 0 : Point aMousePos = ScreenToOutputPixel( rMousePos );
624 0 : m_aDragOffset = aMousePos - pTabWin->GetPosPixel();
625 0 : m_pDragWin->SetZOrder(NULL, ZOrderFlags::First);
626 0 : m_bTrackingInitiallyMoved = false;
627 0 : StartTracking();
628 : }
629 :
630 0 : void OJoinTableView::NotifyTitleClicked( OTableWindow* pTabWin, const Point& rMousePos )
631 : {
632 0 : DeselectConn(GetSelectedConn());
633 0 : BeginChildMove(pTabWin, rMousePos);
634 0 : }
635 :
636 0 : void OJoinTableView::BeginChildSizing( OTableWindow* pTabWin, const Pointer& rPointer )
637 : {
638 :
639 0 : if (m_pView->getController().isReadOnly())
640 0 : return;
641 :
642 0 : SetPointer( rPointer );
643 0 : m_pSizingWin = pTabWin;
644 0 : StartTracking();
645 : }
646 :
647 0 : bool OJoinTableView::ScrollPane( long nDelta, bool bHoriz, bool bPaintScrollBars )
648 : {
649 0 : bool bRet = true;
650 :
651 : // adjust ScrollBar-Positions
652 0 : if( bPaintScrollBars )
653 : {
654 0 : if( bHoriz )
655 : {
656 0 : long nOldThumbPos = GetHScrollBar().GetThumbPos();
657 0 : long nNewThumbPos = nOldThumbPos + nDelta;
658 0 : if( nNewThumbPos < 0 )
659 : {
660 0 : nNewThumbPos = 0;
661 0 : bRet = false;
662 : }
663 0 : if( nNewThumbPos > GetHScrollBar().GetRange().Max() )
664 : {
665 0 : nNewThumbPos = GetHScrollBar().GetRange().Max();
666 0 : bRet = false;
667 : }
668 0 : GetHScrollBar().SetThumbPos( nNewThumbPos );
669 0 : nDelta = GetHScrollBar().GetThumbPos() - nOldThumbPos;
670 : }
671 : else
672 : {
673 0 : long nOldThumbPos = GetVScrollBar().GetThumbPos();
674 0 : long nNewThumbPos = nOldThumbPos+nDelta;
675 0 : if( nNewThumbPos < 0 )
676 : {
677 0 : nNewThumbPos = 0;
678 0 : bRet = false;
679 : }
680 0 : if( nNewThumbPos > GetVScrollBar().GetRange().Max() )
681 : {
682 0 : nNewThumbPos = GetVScrollBar().GetRange().Max();
683 0 : bRet = false;
684 : }
685 0 : GetVScrollBar().SetThumbPos( nNewThumbPos );
686 0 : nDelta = GetVScrollBar().GetThumbPos() - nOldThumbPos;
687 : }
688 : }
689 :
690 : // If ScrollOffset hitting borders, no redrawing.
691 0 : if( (GetHScrollBar().GetThumbPos()==m_aScrollOffset.X()) &&
692 0 : (GetVScrollBar().GetThumbPos()==m_aScrollOffset.Y()) )
693 0 : return false;
694 :
695 : // set ScrollOffset anew
696 0 : if (bHoriz)
697 0 : m_aScrollOffset.X() = GetHScrollBar().GetThumbPos();
698 : else
699 0 : m_aScrollOffset.Y() = GetVScrollBar().GetThumbPos();
700 :
701 : // move all windows
702 : OTableWindow* pTabWin;
703 0 : Point aPos;
704 :
705 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
706 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
707 0 : for(;aIter != aEnd;++aIter)
708 : {
709 0 : pTabWin = aIter->second;
710 0 : aPos = pTabWin->GetPosPixel();
711 :
712 0 : if( bHoriz )
713 0 : aPos.X() -= nDelta;
714 0 : else aPos.Y() -= nDelta;
715 :
716 0 : pTabWin->SetPosPixel( aPos );
717 : }
718 :
719 0 : Invalidate(); // InvalidateFlags::NoChildren
720 :
721 0 : return bRet;
722 : }
723 :
724 0 : void OJoinTableView::Tracking( const TrackingEvent& rTEvt )
725 : {
726 0 : HideTracking();
727 :
728 0 : if (rTEvt.IsTrackingEnded())
729 : {
730 0 : if( m_pDragWin )
731 : {
732 0 : if (m_aDragScrollIdle.IsActive())
733 0 : m_aDragScrollIdle.Stop();
734 :
735 : // adjust position of child after moving
736 : // windows are not allowed to leave display range
737 0 : Point aDragWinPos = rTEvt.GetMouseEvent().GetPosPixel() - m_aDragOffset;
738 0 : Size aDragWinSize = m_pDragWin->GetSizePixel();
739 0 : if( aDragWinPos.X() < 0 )
740 0 : aDragWinPos.X() = 0;
741 0 : if( aDragWinPos.Y() < 0 )
742 0 : aDragWinPos.Y() = 0;
743 0 : if( (aDragWinPos.X() + aDragWinSize.Width()) > m_aOutputSize.Width() )
744 0 : aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width() - 1;
745 0 : if( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() )
746 0 : aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height() - 1;
747 0 : if( aDragWinPos.X() < 0 )
748 0 : aDragWinPos.X() = 0;
749 0 : if( aDragWinPos.Y() < 0 )
750 0 : aDragWinPos.Y() = 0;
751 : // TODO : don't position window anew, if it is leaving range, but just expand the range
752 :
753 : // position window
754 0 : EndTracking();
755 0 : m_pDragWin->SetZOrder(NULL, ZOrderFlags::First);
756 : // check, if I really moved
757 : // (this prevents setting the modified-Flag, when there actually was no change0
758 0 : TTableWindowData::value_type pData = m_pDragWin->GetData();
759 0 : if ( ! (pData && pData->HasPosition() && (pData->GetPosition() == aDragWinPos)))
760 : {
761 : // old logic coordinates
762 0 : Point ptOldPos = m_pDragWin->GetPosPixel() + Point(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
763 : // new positioning
764 0 : m_pDragWin->SetPosPixel(aDragWinPos);
765 0 : TabWinMoved(m_pDragWin, ptOldPos);
766 :
767 0 : m_pDragWin->GrabFocus();
768 : }
769 0 : m_pDragWin = NULL;
770 0 : SetPointer(Pointer(PointerStyle::Arrow));
771 : }
772 : // else we handle the resizing
773 0 : else if( m_pSizingWin )
774 : {
775 0 : SetPointer( Pointer() );
776 0 : EndTracking();
777 :
778 : // old physical coordinates
779 :
780 0 : Size szOld = m_pSizingWin->GetSizePixel();
781 0 : Point ptOld = m_pSizingWin->GetPosPixel();
782 0 : Size aNewSize(CalcZoom(m_aSizingRect.GetSize().Width()),CalcZoom(m_aSizingRect.GetSize().Height()));
783 0 : m_pSizingWin->SetPosSizePixel( m_aSizingRect.TopLeft(), aNewSize );
784 0 : TabWinSized(m_pSizingWin, ptOld, szOld);
785 :
786 0 : m_pSizingWin->Invalidate( m_aSizingRect );
787 0 : m_pSizingWin = NULL;
788 : }
789 : }
790 0 : else if (rTEvt.IsTrackingCanceled())
791 : {
792 0 : if (m_aDragScrollIdle.IsActive())
793 0 : m_aDragScrollIdle.Stop();
794 0 : EndTracking();
795 : }
796 : else
797 : {
798 0 : if( m_pDragWin )
799 : {
800 0 : m_ptPrevDraggingPos = rTEvt.GetMouseEvent().GetPosPixel();
801 : // scroll at window borders
802 0 : ScrollWhileDragging();
803 : }
804 :
805 0 : if( m_pSizingWin )
806 : {
807 0 : Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
808 0 : m_aSizingRect = m_pSizingWin->getSizingRect(aMousePos,m_aOutputSize);
809 0 : Update();
810 0 : ShowTracking( m_aSizingRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
811 : }
812 : }
813 0 : }
814 :
815 0 : void OJoinTableView::ConnDoubleClicked( OTableConnection* /*pConnection*/ )
816 : {
817 0 : }
818 :
819 0 : void OJoinTableView::MouseButtonDown( const MouseEvent& rEvt )
820 : {
821 0 : GrabFocus();
822 0 : Window::MouseButtonDown(rEvt);
823 0 : }
824 :
825 0 : void OJoinTableView::MouseButtonUp( const MouseEvent& rEvt )
826 : {
827 0 : Window::MouseButtonUp(rEvt);
828 : // Has a connection been selected?
829 0 : if( !m_vTableConnection.empty() )
830 : {
831 0 : DeselectConn(GetSelectedConn());
832 :
833 0 : auto aIter = m_vTableConnection.begin();
834 0 : auto aEnd = m_vTableConnection.end();
835 0 : for(;aIter != aEnd;++aIter)
836 : {
837 0 : if( (*aIter)->CheckHit(rEvt.GetPosPixel()) )
838 : {
839 0 : SelectConn((*aIter));
840 :
841 : // Double-click
842 0 : if( rEvt.GetClicks() == 2 )
843 0 : ConnDoubleClicked( (*aIter) );
844 :
845 0 : break;
846 : }
847 : }
848 : }
849 0 : }
850 :
851 0 : void OJoinTableView::KeyInput( const KeyEvent& rEvt )
852 : {
853 0 : sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
854 0 : bool bShift = rEvt.GetKeyCode().IsShift();
855 0 : bool bCtrl = rEvt.GetKeyCode().IsMod1();
856 :
857 0 : if( !bCtrl && !bShift && (nCode==KEY_DELETE) )
858 : {
859 0 : if (GetSelectedConn())
860 0 : RemoveConnection( GetSelectedConn() ,true);
861 : }
862 : else
863 0 : Window::KeyInput( rEvt );
864 0 : }
865 :
866 0 : void OJoinTableView::DeselectConn(OTableConnection* pConn)
867 : {
868 0 : if (!pConn || !pConn->IsSelected())
869 0 : return;
870 :
871 : // deselect the corresponding entries in the ListBox of the table window
872 0 : OTableWindow* pWin = pConn->GetSourceWin();
873 0 : if (pWin && pWin->GetListBox())
874 0 : pWin->GetListBox()->SelectAll(false);
875 :
876 0 : pWin = pConn->GetDestWin();
877 0 : if (pWin && pWin->GetListBox())
878 0 : pWin->GetListBox()->SelectAll(false);
879 :
880 0 : pConn->Deselect();
881 0 : m_pSelectedConn = NULL;
882 : }
883 :
884 0 : void OJoinTableView::SelectConn(OTableConnection* pConn)
885 : {
886 0 : DeselectConn(GetSelectedConn());
887 :
888 0 : pConn->Select();
889 0 : m_pSelectedConn = pConn;
890 0 : GrabFocus(); // has to be called here because a table window may still be focused
891 :
892 : // select the concerned entries in the windows
893 0 : OTableWindow* pConnSource = pConn->GetSourceWin();
894 0 : OTableWindow* pConnDest = pConn->GetDestWin();
895 0 : if (pConnSource && pConnDest)
896 : {
897 0 : OTableWindowListBox* pSourceBox = pConnSource->GetListBox();
898 0 : OTableWindowListBox* pDestBox = pConnDest->GetListBox();
899 0 : if (pSourceBox && pDestBox)
900 : {
901 0 : pSourceBox->SelectAll(false);
902 0 : pDestBox->SelectAll(false);
903 :
904 0 : SvTreeListEntry* pFirstSourceVisible = pSourceBox->GetFirstEntryInView();
905 0 : SvTreeListEntry* pFirstDestVisible = pDestBox->GetFirstEntryInView();
906 :
907 0 : const ::std::vector<OConnectionLine*>& rLines = pConn->GetConnLineList();
908 0 : ::std::vector<OConnectionLine*>::const_reverse_iterator aIter = rLines.rbegin();
909 0 : for(;aIter != rLines.rend();++aIter)
910 : {
911 0 : if ((*aIter)->IsValid())
912 : {
913 0 : SvTreeListEntry* pSourceEntry = pSourceBox->GetEntryFromText((*aIter)->GetData()->GetSourceFieldName());
914 0 : if (pSourceEntry)
915 : {
916 0 : pSourceBox->Select(pSourceEntry, true);
917 0 : pSourceBox->MakeVisible(pSourceEntry);
918 : }
919 :
920 0 : SvTreeListEntry* pDestEntry = pDestBox->GetEntryFromText((*aIter)->GetData()->GetDestFieldName());
921 0 : if (pDestEntry)
922 : {
923 0 : pDestBox->Select(pDestEntry, true);
924 0 : pDestBox->MakeVisible(pDestEntry);
925 : }
926 :
927 : }
928 : }
929 :
930 0 : if ((pFirstSourceVisible != pSourceBox->GetFirstEntryInView())
931 0 : || (pFirstDestVisible != pDestBox->GetFirstEntryInView()))
932 : // scrolling was done -> redraw
933 0 : Invalidate(InvalidateFlags::NoChildren);
934 : }
935 : }
936 0 : }
937 :
938 0 : void OJoinTableView::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
939 : {
940 0 : DrawConnections(rRenderContext, rRect);
941 0 : }
942 :
943 0 : void OJoinTableView::InvalidateConnections()
944 : {
945 : // draw Joins
946 0 : for (auto & conn : m_vTableConnection)
947 0 : conn->InvalidateConnection();
948 0 : }
949 :
950 0 : void OJoinTableView::DrawConnections(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
951 : {
952 : // draw Joins
953 0 : for(auto connection : m_vTableConnection)
954 0 : connection->Draw(rRenderContext, rRect);
955 : // finally redraw the selected one above all others
956 0 : if (GetSelectedConn())
957 0 : GetSelectedConn()->Draw(rRenderContext, rRect);
958 0 : }
959 :
960 0 : ::std::vector<VclPtr<OTableConnection> >::const_iterator OJoinTableView::getTableConnections(const OTableWindow* _pFromWin) const
961 : {
962 : return ::std::find_if( m_vTableConnection.begin(),
963 : m_vTableConnection.end(),
964 0 : ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin));
965 : }
966 :
967 0 : sal_Int32 OJoinTableView::getConnectionCount(const OTableWindow* _pFromWin) const
968 : {
969 : return ::std::count_if( m_vTableConnection.begin(),
970 : m_vTableConnection.end(),
971 0 : ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin));
972 : }
973 :
974 0 : bool OJoinTableView::ExistsAConn(const OTableWindow* pFrom) const
975 : {
976 0 : return getTableConnections(pFrom) != m_vTableConnection.end();
977 : }
978 :
979 0 : void OJoinTableView::ClearAll()
980 : {
981 0 : SetUpdateMode(false);
982 :
983 0 : HideTabWins();
984 :
985 : // and the same with the Connections
986 0 : auto aIter = m_vTableConnection.begin();
987 0 : auto aEnd = m_vTableConnection.end();
988 0 : for(;aIter != aEnd;++aIter)
989 0 : RemoveConnection( *aIter ,true);
990 0 : m_vTableConnection.clear();
991 :
992 0 : m_pLastFocusTabWin = NULL;
993 0 : m_pSelectedConn = NULL;
994 :
995 : // scroll to the upper left
996 0 : ScrollPane(-GetScrollOffset().X(), true, true);
997 0 : ScrollPane(-GetScrollOffset().Y(), false, true);
998 0 : Invalidate();
999 0 : }
1000 :
1001 0 : bool OJoinTableView::ScrollWhileDragging()
1002 : {
1003 : OSL_ENSURE(m_pDragWin != nullptr, "OJoinTableView::ScrollWhileDragging must not be called when a window is being dragged !");
1004 :
1005 : // kill the timer
1006 0 : if (m_aDragScrollIdle.IsActive())
1007 0 : m_aDragScrollIdle.Stop();
1008 :
1009 0 : Point aDragWinPos = m_ptPrevDraggingPos - m_aDragOffset;
1010 0 : Size aDragWinSize = m_pDragWin->GetSizePixel();
1011 0 : Point aLowerRight(aDragWinPos.X() + aDragWinSize.Width(), aDragWinPos.Y() + aDragWinSize.Height());
1012 :
1013 0 : if (!m_bTrackingInitiallyMoved && (aDragWinPos == m_pDragWin->GetPosPixel()))
1014 0 : return true;
1015 :
1016 : // avoid illustration errors (when scrolling with active TrackingRect)
1017 0 : HideTracking();
1018 :
1019 0 : bool bScrolling = false;
1020 0 : bool bNeedScrollTimer = false;
1021 :
1022 : // scroll at window borders
1023 : // TODO : only catch, if window would disappear completely (don't, if there is still a pixel visible)
1024 0 : if( aDragWinPos.X() < 5 )
1025 : {
1026 0 : bScrolling = ScrollPane( -LINE_SIZE, true, true );
1027 0 : if( !bScrolling && (aDragWinPos.X()<0) )
1028 0 : aDragWinPos.X() = 0;
1029 :
1030 : // do I need further (timer controlled) scrolling ?
1031 0 : bNeedScrollTimer = bScrolling && (aDragWinPos.X() < 5);
1032 : }
1033 :
1034 0 : if( aLowerRight.X() > m_aOutputSize.Width() - 5 )
1035 : {
1036 0 : bScrolling = ScrollPane( LINE_SIZE, true, true ) ;
1037 0 : if( !bScrolling && ( aLowerRight.X() > m_aOutputSize.Width() ) )
1038 0 : aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width();
1039 :
1040 : // do I need further (timer controlled) scrolling ?
1041 0 : bNeedScrollTimer = bScrolling && (aLowerRight.X() > m_aOutputSize.Width() - 5);
1042 : }
1043 :
1044 0 : if( aDragWinPos.Y() < 5 )
1045 : {
1046 0 : bScrolling = ScrollPane( -LINE_SIZE, false, true );
1047 0 : if( !bScrolling && (aDragWinPos.Y()<0) )
1048 0 : aDragWinPos.Y() = 0;
1049 :
1050 0 : bNeedScrollTimer = bScrolling && (aDragWinPos.Y() < 5);
1051 : }
1052 :
1053 0 : if( aLowerRight.Y() > m_aOutputSize.Height() - 5 )
1054 : {
1055 0 : bScrolling = ScrollPane( LINE_SIZE, false, true );
1056 0 : if( !bScrolling && ( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) )
1057 0 : aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height();
1058 :
1059 0 : bNeedScrollTimer = bScrolling && (aLowerRight.Y() > m_aOutputSize.Height() - 5);
1060 : }
1061 :
1062 : // resetting timer, if still necessary
1063 0 : if (bNeedScrollTimer)
1064 : {
1065 0 : m_aDragScrollIdle.SetPriority(SchedulerPriority::LOW);
1066 0 : m_aDragScrollIdle.Start();
1067 : }
1068 :
1069 : // redraw DraggingRect
1070 0 : m_aDragRect = Rectangle(m_ptPrevDraggingPos - m_aDragOffset, m_pDragWin->GetSizePixel());
1071 0 : Update();
1072 0 : ShowTracking( m_aDragRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
1073 :
1074 0 : return bScrolling;
1075 : }
1076 :
1077 0 : IMPL_LINK_NOARG_TYPED(OJoinTableView, OnDragScrollTimer, Idle *, void)
1078 : {
1079 0 : ScrollWhileDragging();
1080 0 : }
1081 :
1082 0 : void OJoinTableView::invalidateAndModify(SfxUndoAction *_pAction)
1083 : {
1084 0 : Invalidate(InvalidateFlags::NoChildren);
1085 0 : m_pView->getController().addUndoActionAndInvalidate(_pAction);
1086 0 : }
1087 :
1088 0 : void OJoinTableView::TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition)
1089 : {
1090 0 : Point ptThumbPos(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
1091 0 : ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel() + ptThumbPos);
1092 :
1093 0 : invalidateAndModify(new OJoinMoveTabWinUndoAct(this, ptOldPosition, ptWhich));
1094 0 : }
1095 :
1096 0 : void OJoinTableView::TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize)
1097 : {
1098 0 : ptWhich->GetData()->SetSize(ptWhich->GetSizePixel());
1099 0 : ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel());
1100 :
1101 0 : invalidateAndModify(new OJoinSizeTabWinUndoAct(this, ptOldPosition, szOldSize, ptWhich));
1102 0 : }
1103 :
1104 0 : bool OJoinTableView::IsAddAllowed()
1105 : {
1106 :
1107 : // not, if Db readonly
1108 0 : if (m_pView->getController().isReadOnly())
1109 0 : return false;
1110 :
1111 : try
1112 : {
1113 0 : Reference< XConnection> xConnection = m_pView->getController().getConnection();
1114 0 : if(!xConnection.is())
1115 0 : return false;
1116 : // not, if too many tables already
1117 0 : Reference < XDatabaseMetaData > xMetaData( xConnection->getMetaData() );
1118 :
1119 0 : sal_Int32 nMax = xMetaData.is() ? xMetaData->getMaxTablesInSelect() : 0;
1120 0 : if (nMax && nMax <= (sal_Int32)m_aTableMap.size())
1121 0 : return false;
1122 : }
1123 0 : catch(SQLException&)
1124 : {
1125 0 : return false;
1126 : }
1127 :
1128 0 : return true;
1129 : }
1130 :
1131 0 : void OJoinTableView::executePopup(const Point& _aPos,OTableConnection* _pSelConnection)
1132 : {
1133 0 : PopupMenu aContextMenu( ModuleRes( RID_MENU_JOINVIEW_CONNECTION ) );
1134 0 : switch (aContextMenu.Execute(this, _aPos))
1135 : {
1136 : case SID_DELETE:
1137 0 : RemoveConnection( _pSelConnection ,true);
1138 0 : break;
1139 : case ID_QUERY_EDIT_JOINCONNECTION:
1140 0 : ConnDoubleClicked( _pSelConnection ); // is the same as double clicked
1141 0 : break;
1142 0 : }
1143 0 : }
1144 :
1145 0 : void OJoinTableView::Command(const CommandEvent& rEvt)
1146 : {
1147 :
1148 0 : bool bHandled = false;
1149 :
1150 0 : switch (rEvt.GetCommand())
1151 : {
1152 : case CommandEventId::ContextMenu:
1153 : {
1154 0 : if( m_vTableConnection.empty() )
1155 0 : return;
1156 :
1157 0 : OTableConnection* pSelConnection = GetSelectedConn();
1158 : // when it wasn't a mouse event use the selected connection
1159 0 : if (!rEvt.IsMouseEvent())
1160 : {
1161 0 : if( pSelConnection )
1162 : {
1163 0 : const ::std::vector<OConnectionLine*>& rLines = pSelConnection->GetConnLineList();
1164 0 : ::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(rLines.begin(), rLines.end(),::std::mem_fun(&OConnectionLine::IsValid));
1165 0 : if( aIter != rLines.end() )
1166 0 : executePopup((*aIter)->getMidPoint(),pSelConnection);
1167 : }
1168 : }
1169 : else
1170 : {
1171 0 : DeselectConn(pSelConnection);
1172 :
1173 0 : const Point& aMousePos = rEvt.GetMousePosPixel();
1174 0 : auto aIter = m_vTableConnection.begin();
1175 0 : auto aEnd = m_vTableConnection.end();
1176 0 : for(;aIter != aEnd;++aIter)
1177 : {
1178 0 : if( (*aIter)->CheckHit(aMousePos) )
1179 : {
1180 0 : SelectConn(*aIter);
1181 0 : if(!getDesignView()->getController().isReadOnly() && getDesignView()->getController().isConnected())
1182 0 : executePopup(rEvt.GetMousePosPixel(),*aIter);
1183 0 : break;
1184 : }
1185 : }
1186 : }
1187 0 : bHandled = true;
1188 : }
1189 0 : break;
1190 0 : default: break;
1191 : }
1192 0 : if (!bHandled)
1193 0 : Window::Command(rEvt);
1194 : }
1195 :
1196 0 : OTableConnection* OJoinTableView::GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSupressCrossOrNaturalJoin,const OTableConnection* _rpFirstAfter) const
1197 : {
1198 0 : OTableConnection* pConn = NULL;
1199 : OSL_ENSURE(pRhs || pLhs, "OJoinTableView::GetTabConn : invalid args !");
1200 : // only one NULL-arg allowed
1201 :
1202 0 : if ((!pLhs || pLhs->ExistsAConn()) && (!pRhs || pRhs->ExistsAConn()))
1203 : {
1204 0 : bool bFoundStart = _rpFirstAfter == nullptr;
1205 :
1206 0 : auto aIter = m_vTableConnection.begin();
1207 0 : auto aEnd = m_vTableConnection.end();
1208 0 : for(;aIter != aEnd;++aIter)
1209 : {
1210 0 : OTableConnection* pData = *aIter;
1211 :
1212 0 : if ( ( (pData->GetSourceWin() == pLhs)
1213 0 : && ( (pData->GetDestWin() == pRhs)
1214 0 : || (NULL == pRhs)
1215 : )
1216 : )
1217 0 : || ( (pData->GetSourceWin() == pRhs)
1218 0 : && ( (pData->GetDestWin() == pLhs)
1219 0 : || (NULL == pLhs)
1220 : )
1221 : )
1222 : )
1223 : {
1224 0 : if ( _bSupressCrossOrNaturalJoin )
1225 : {
1226 0 : if ( supressCrossNaturalJoin(pData->GetData()) )
1227 0 : continue;
1228 : }
1229 0 : if (bFoundStart)
1230 : {
1231 0 : pConn = pData;
1232 0 : break;
1233 : }
1234 :
1235 0 : if (!pConn)
1236 : // used as fallback : if there is no conn after _rpFirstAfter the first conn between the two tables
1237 : // will be used
1238 0 : pConn = pData;
1239 :
1240 0 : if (pData == _rpFirstAfter)
1241 0 : bFoundStart = true;
1242 : }
1243 : }
1244 : }
1245 0 : return pConn;
1246 : }
1247 :
1248 0 : bool OJoinTableView::PreNotify(NotifyEvent& rNEvt)
1249 : {
1250 0 : bool bHandled = false;
1251 0 : switch (rNEvt.GetType())
1252 : {
1253 : case MouseNotifyEvent::COMMAND:
1254 : {
1255 0 : const CommandEvent* pCommand = rNEvt.GetCommandEvent();
1256 0 : if (pCommand->GetCommand() == CommandEventId::Wheel)
1257 : {
1258 0 : const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
1259 0 : if (pData->GetMode() == CommandWheelMode::SCROLL)
1260 : {
1261 0 : if (pData->GetDelta() > 0)
1262 0 : ScrollPane(-10 * pData->GetScrollLines(), pData->IsHorz(), true);
1263 : else
1264 0 : ScrollPane(10 * pData->GetScrollLines(), pData->IsHorz(), true);
1265 0 : bHandled = true;
1266 : }
1267 : }
1268 : }
1269 0 : break;
1270 : case MouseNotifyEvent::KEYINPUT:
1271 : {
1272 0 : if (m_aTableMap.empty())
1273 : // no tab wins -> no conns -> no traveling
1274 0 : break;
1275 :
1276 0 : const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
1277 0 : if (!pKeyEvent->GetKeyCode().IsMod1())
1278 : {
1279 0 : switch (pKeyEvent->GetKeyCode().GetCode())
1280 : {
1281 : case KEY_TAB:
1282 : {
1283 0 : if (!HasChildPathFocus())
1284 0 : break;
1285 :
1286 0 : bool bForward = !pKeyEvent->GetKeyCode().IsShift();
1287 : // is there an active tab win ?
1288 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
1289 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
1290 0 : for(;aIter != aEnd;++aIter)
1291 0 : if (aIter->second && aIter->second->HasChildPathFocus())
1292 0 : break;
1293 :
1294 0 : OTableWindow* pNextWin = NULL;
1295 0 : OTableConnection* pNextConn = NULL;
1296 :
1297 0 : if (aIter != m_aTableMap.end())
1298 : { // there is a currently active tab win
1299 : // check if there is an "overflow" and we should select a conn instead of a win
1300 0 : if (!m_vTableConnection.empty())
1301 : {
1302 0 : if ((aIter->second == m_aTableMap.rbegin()->second) && bForward)
1303 : // the last win is active and we're travelling forward -> select the first conn
1304 0 : pNextConn = *m_vTableConnection.begin();
1305 0 : if ((aIter == m_aTableMap.begin()) && !bForward)
1306 : // the first win is active an we're traveling backward -> select the last conn
1307 0 : pNextConn = *m_vTableConnection.rbegin();
1308 : }
1309 :
1310 0 : if (!pNextConn)
1311 : {
1312 : // no conn for any reason -> select the next or previous tab win
1313 0 : if(bForward)
1314 : {
1315 0 : if ( aIter->second == m_aTableMap.rbegin()->second )
1316 0 : pNextWin = m_aTableMap.begin()->second;
1317 : else
1318 : {
1319 0 : ++aIter;
1320 0 : pNextWin = aIter->second;
1321 : }
1322 : }
1323 : else
1324 : {
1325 0 : if (aIter == m_aTableMap.begin())
1326 0 : pNextWin = m_aTableMap.rbegin()->second;
1327 : else
1328 : {
1329 0 : --aIter;
1330 0 : pNextWin = aIter->second;
1331 : }
1332 : }
1333 : }
1334 : }
1335 : else
1336 : { // no active tab win -> travel the connections
1337 : // find the currently selected conn within the conn list
1338 0 : sal_Int32 i(0);
1339 0 : for ( auto connectionIter = m_vTableConnection.begin();
1340 0 : connectionIter != m_vTableConnection.end();
1341 : ++connectionIter, ++i
1342 : )
1343 : {
1344 0 : if ( (*connectionIter).get() == GetSelectedConn() )
1345 0 : break;
1346 : }
1347 0 : if (i == sal_Int32(m_vTableConnection.size() - 1) && bForward)
1348 : // the last conn is active and we're travelling forward -> select the first win
1349 0 : pNextWin = m_aTableMap.begin()->second;
1350 0 : if ((i == 0) && !bForward && !m_aTableMap.empty())
1351 : // the first conn is active and we're travelling backward -> select the last win
1352 0 : pNextWin = m_aTableMap.rbegin()->second;
1353 :
1354 0 : if (pNextWin)
1355 0 : DeselectConn(GetSelectedConn());
1356 : else
1357 : // no win for any reason -> select the next or previous conn
1358 0 : if (i < (sal_Int32)m_vTableConnection.size())
1359 : // there is a currently active conn
1360 0 : pNextConn = m_vTableConnection[(i + (bForward ? 1 : m_vTableConnection.size() - 1)) % m_vTableConnection.size()];
1361 : else
1362 : { // no tab win selected, no conn selected
1363 0 : if (!m_vTableConnection.empty())
1364 0 : pNextConn = m_vTableConnection[bForward ? 0 : m_vTableConnection.size() - 1];
1365 0 : else if (!m_aTableMap.empty())
1366 : {
1367 0 : if(bForward)
1368 0 : pNextWin = m_aTableMap.begin()->second;
1369 : else
1370 0 : pNextWin = m_aTableMap.rbegin()->second;
1371 : }
1372 : }
1373 : }
1374 :
1375 : // now select the object
1376 0 : if (pNextWin)
1377 : {
1378 0 : if (pNextWin->GetListBox())
1379 0 : pNextWin->GetListBox()->GrabFocus();
1380 : else
1381 0 : pNextWin->GrabFocus();
1382 0 : EnsureVisible(pNextWin);
1383 : }
1384 0 : else if (pNextConn)
1385 : {
1386 0 : GrabFocus();
1387 : // necessary : a conn may be selected even if a tab win has the focus, in this case
1388 : // the next travel would select the same conn again if we would not reset the focus ...
1389 0 : SelectConn(pNextConn);
1390 : }
1391 : }
1392 0 : break;
1393 : case KEY_RETURN:
1394 : {
1395 0 : if (!pKeyEvent->GetKeyCode().IsShift() && GetSelectedConn() && HasFocus())
1396 0 : ConnDoubleClicked(GetSelectedConn());
1397 0 : break;
1398 : }
1399 : }
1400 : }
1401 : }
1402 0 : break;
1403 : case MouseNotifyEvent::GETFOCUS:
1404 : {
1405 0 : if (m_aTableMap.empty())
1406 : // no tab wins -> no conns -> no focus change
1407 0 : break;
1408 0 : vcl::Window* pSource = rNEvt.GetWindow();
1409 0 : if (pSource)
1410 : {
1411 0 : vcl::Window* pSearchFor = NULL;
1412 0 : if (pSource->GetParent() == this)
1413 : // it may be one of the tab wins
1414 0 : pSearchFor = pSource;
1415 0 : else if (pSource->GetParent() && (pSource->GetParent()->GetParent() == this))
1416 : // it may be one of th list boxes of one of the tab wins
1417 0 : pSearchFor = pSource->GetParent();
1418 :
1419 0 : if (pSearchFor)
1420 : {
1421 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
1422 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
1423 0 : for(;aIter != aEnd;++aIter)
1424 : {
1425 0 : if (aIter->second == pSearchFor)
1426 : {
1427 0 : m_pLastFocusTabWin = aIter->second;
1428 0 : break;
1429 : }
1430 : }
1431 : }
1432 : }
1433 : }
1434 0 : break;
1435 : default:
1436 0 : break;
1437 : }
1438 :
1439 0 : if (!bHandled)
1440 0 : return Window::PreNotify(rNEvt);
1441 0 : return true;
1442 : }
1443 :
1444 0 : void OJoinTableView::GrabTabWinFocus()
1445 : {
1446 0 : if (m_pLastFocusTabWin && m_pLastFocusTabWin->IsVisible())
1447 : {
1448 0 : if (m_pLastFocusTabWin->GetListBox())
1449 0 : m_pLastFocusTabWin->GetListBox()->GrabFocus();
1450 : else
1451 0 : m_pLastFocusTabWin->GrabFocus();
1452 : }
1453 0 : else if (!m_aTableMap.empty() && m_aTableMap.begin()->second && m_aTableMap.begin()->second->IsVisible())
1454 : {
1455 0 : OTableWindow* pFirstWin = m_aTableMap.begin()->second;
1456 0 : if (pFirstWin->GetListBox())
1457 0 : pFirstWin->GetListBox()->GrabFocus();
1458 : else
1459 0 : pFirstWin->GrabFocus();
1460 : }
1461 0 : }
1462 :
1463 0 : void OJoinTableView::StateChanged( StateChangedType nType )
1464 : {
1465 0 : Window::StateChanged( nType );
1466 :
1467 : // FIXME RenderContext
1468 0 : if ( nType == StateChangedType::Zoom )
1469 : {
1470 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1471 :
1472 0 : vcl::Font aFont = rStyleSettings.GetGroupFont();
1473 0 : if ( IsControlFont() )
1474 0 : aFont.Merge( GetControlFont() );
1475 0 : SetZoomedPointFont(*this, aFont);
1476 :
1477 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
1478 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
1479 0 : for(;aIter != aEnd;++aIter)
1480 : {
1481 0 : aIter->second->SetZoom(GetZoom());
1482 0 : Size aSize(CalcZoom(aIter->second->GetSizePixel().Width()),CalcZoom(aIter->second->GetSizePixel().Height()));
1483 0 : aIter->second->SetSizePixel(aSize);
1484 : }
1485 0 : Resize();
1486 : }
1487 0 : }
1488 :
1489 0 : void OJoinTableView::HideTabWins()
1490 : {
1491 0 : SetUpdateMode(false);
1492 :
1493 0 : OTableWindowMap& rTabWins = GetTabWinMap();
1494 :
1495 : // working on a copy because the real list will be cleared in inner calls
1496 0 : OTableWindowMap aCopy(rTabWins);
1497 0 : OTableWindowMap::iterator aIter = aCopy.begin();
1498 0 : OTableWindowMap::iterator aEnd = aCopy.end();
1499 0 : for(;aIter != aEnd;++aIter)
1500 0 : RemoveTabWin(aIter->second);
1501 :
1502 0 : m_pView->getController().setModified(sal_True);
1503 :
1504 0 : SetUpdateMode(true);
1505 :
1506 0 : }
1507 :
1508 0 : sal_Int8 OJoinTableView::AcceptDrop( const AcceptDropEvent& /*_rEvt*/ )
1509 : {
1510 0 : return DND_ACTION_NONE;
1511 : }
1512 :
1513 0 : sal_Int8 OJoinTableView::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
1514 : {
1515 0 : return DND_ACTION_NONE;
1516 : }
1517 :
1518 0 : void OJoinTableView::dragFinished( )
1519 : {
1520 0 : }
1521 :
1522 0 : void OJoinTableView::clearLayoutInformation()
1523 : {
1524 0 : m_pLastFocusTabWin = NULL;
1525 0 : m_pSelectedConn = NULL;
1526 : // delete lists
1527 0 : OTableWindowMap::iterator aIter = m_aTableMap.begin();
1528 0 : OTableWindowMap::iterator aEnd = m_aTableMap.end();
1529 0 : for(;aIter != aEnd;++aIter)
1530 : {
1531 0 : if ( aIter->second )
1532 0 : aIter->second->clearListBox();
1533 0 : aIter->second = NULL;
1534 : }
1535 :
1536 0 : m_aTableMap.clear();
1537 :
1538 0 : for(auto i = m_vTableConnection.begin();
1539 0 : i != m_vTableConnection.end(); ++i)
1540 0 : i->disposeAndClear();
1541 :
1542 0 : m_vTableConnection.clear();
1543 0 : }
1544 :
1545 0 : void OJoinTableView::lookForUiActivities()
1546 : {
1547 0 : }
1548 :
1549 0 : void OJoinTableView::LoseFocus()
1550 : {
1551 0 : DeselectConn(GetSelectedConn());
1552 0 : Window::LoseFocus();
1553 0 : }
1554 :
1555 0 : void OJoinTableView::GetFocus()
1556 : {
1557 0 : Window::GetFocus();
1558 0 : if ( !m_aTableMap.empty() && !GetSelectedConn() )
1559 0 : GrabTabWinFocus();
1560 0 : }
1561 :
1562 0 : Reference< XAccessible > OJoinTableView::CreateAccessible()
1563 : {
1564 0 : m_pAccessible = new OJoinDesignViewAccess(this);
1565 0 : return m_pAccessible;
1566 : }
1567 :
1568 0 : void OJoinTableView::modified()
1569 : {
1570 0 : OJoinController& rController = m_pView->getController();
1571 0 : rController.setModified( sal_True );
1572 0 : rController.InvalidateFeature(ID_BROWSER_ADDTABLE);
1573 0 : rController.InvalidateFeature(SID_RELATION_ADD_RELATION);
1574 0 : }
1575 :
1576 0 : void OJoinTableView::addConnection(OTableConnection* _pConnection,bool _bAddData)
1577 : {
1578 0 : if ( _bAddData )
1579 : {
1580 : #if OSL_DEBUG_LEVEL > 0
1581 : TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
1582 : OSL_ENSURE( ::std::find(rTabConnDataList.begin(), rTabConnDataList.end(),_pConnection->GetData()) == rTabConnDataList.end(),"Data already in vector!");
1583 : #endif
1584 0 : m_pView->getController().getTableConnectionData().push_back(_pConnection->GetData());
1585 : }
1586 0 : m_vTableConnection.push_back(_pConnection);
1587 0 : _pConnection->RecalcLines();
1588 0 : _pConnection->InvalidateConnection();
1589 :
1590 0 : modified();
1591 0 : if ( m_pAccessible )
1592 : m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
1593 : Any(),
1594 0 : makeAny(_pConnection->GetAccessible()));
1595 0 : }
1596 :
1597 0 : bool OJoinTableView::allowQueries() const
1598 : {
1599 0 : return true;
1600 : }
1601 :
1602 0 : void OJoinTableView::onNoColumns_throw()
1603 : {
1604 : OSL_FAIL( "OTableWindow::onNoColumns_throw: cannot really handle this!" );
1605 0 : throw SQLException();
1606 : }
1607 :
1608 0 : bool OJoinTableView::supressCrossNaturalJoin(const TTableConnectionData::value_type& ) const
1609 : {
1610 0 : return false;
1611 36 : }
1612 :
1613 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|