Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / dbaccess / source / ui / querydesign / JoinTableView.cxx
blobd12eca785cadfeaf57302ca94374c8a756578ae3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 <algorithm>
48 #include <functional>
50 using namespace dbaui;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::sdbc;
53 using namespace ::com::sun::star::accessibility;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::lang;
57 #define LINE_SIZE 50
58 // Constants for the window layout
59 #define TABWIN_SPACING_X 17
60 #define TABWIN_SPACING_Y 17
62 #define TABWIN_WIDTH_STD 120
63 #define TABWIN_HEIGHT_STD 120
65 OScrollWindowHelper::OScrollWindowHelper( vcl::Window* pParent) : Window( pParent)
66 ,m_aHScrollBar( VclPtr<ScrollBar>::Create(this, WB_HSCROLL|WB_REPEAT|WB_DRAG) )
67 ,m_aVScrollBar( VclPtr<ScrollBar>::Create(this, WB_VSCROLL|WB_REPEAT|WB_DRAG) )
68 ,m_pCornerWindow(VclPtr<ScrollBarBox>::Create(this, WB_3DLOOK))
69 ,m_pTableView(nullptr)
72 // ScrollBars
74 GetHScrollBar().SetRange( Range(0, 1000) );
75 GetVScrollBar().SetRange( Range(0, 1000) );
77 GetHScrollBar().SetLineSize( LINE_SIZE );
78 GetVScrollBar().SetLineSize( LINE_SIZE );
80 GetHScrollBar().Show();
81 GetVScrollBar().Show();
82 m_pCornerWindow->Show();
84 // normally we should be SCROLL_PANE
85 SetAccessibleRole(AccessibleRole::SCROLL_PANE);
88 OScrollWindowHelper::~OScrollWindowHelper()
90 disposeOnce();
93 void OScrollWindowHelper::dispose()
95 m_aHScrollBar.disposeAndClear();
96 m_aVScrollBar.disposeAndClear();
97 m_pCornerWindow.disposeAndClear();
98 m_pTableView.clear();
99 vcl::Window::dispose();
102 void OScrollWindowHelper::setTableView(OJoinTableView* _pTableView)
104 m_pTableView = _pTableView;
105 // ScrollBars
106 GetHScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
107 GetVScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, ScrollHdl) );
110 void OScrollWindowHelper::resetRange(const Point& _aSize)
112 Point aPos = PixelToLogic(_aSize);
113 GetHScrollBar().SetRange( Range(0, aPos.X() + TABWIN_SPACING_X) );
114 GetVScrollBar().SetRange( Range(0, aPos.Y() + TABWIN_SPACING_Y) );
117 void OScrollWindowHelper::Resize()
119 Window::Resize();
121 Size aTotalOutputSize = GetOutputSizePixel();
122 long nHScrollHeight = GetHScrollBar().GetSizePixel().Height();
123 long nVScrollWidth = GetVScrollBar().GetSizePixel().Width();
125 GetHScrollBar().SetPosSizePixel(
126 Point( 0, aTotalOutputSize.Height()-nHScrollHeight ),
127 Size( aTotalOutputSize.Width()-nVScrollWidth, nHScrollHeight )
130 GetVScrollBar().SetPosSizePixel(
131 Point( aTotalOutputSize.Width()-nVScrollWidth, 0 ),
132 Size( nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight )
135 m_pCornerWindow->SetPosSizePixel(
136 Point( aTotalOutputSize.Width() - nVScrollWidth, aTotalOutputSize.Height() - nHScrollHeight),
137 Size( nVScrollWidth, nHScrollHeight )
140 GetHScrollBar().SetPageSize( aTotalOutputSize.Width() );
141 GetHScrollBar().SetVisibleSize( aTotalOutputSize.Width() );
143 GetVScrollBar().SetPageSize( aTotalOutputSize.Height() );
144 GetVScrollBar().SetVisibleSize( aTotalOutputSize.Height() );
146 // adjust the ranges of the scrollbars if necessary
147 long lRange = GetHScrollBar().GetRange().Max() - GetHScrollBar().GetRange().Min();
148 if (m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() > lRange)
149 GetHScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() + GetHScrollBar().GetRange().Min());
151 lRange = GetVScrollBar().GetRange().Max() - GetVScrollBar().GetRange().Min();
152 if (m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() > lRange)
153 GetVScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() + GetVScrollBar().GetRange().Min());
155 m_pTableView->SetPosSizePixel(Point( 0, 0 ),Size( aTotalOutputSize.Width()-nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight ));
158 // class OJoinTableView
160 OJoinTableView::OJoinTableView( vcl::Window* pParent, OJoinDesignView* pView )
161 :Window( pParent,WB_BORDER )
162 ,DropTargetHelper(this)
163 ,m_aDragOffset( Point(0,0) )
164 ,m_aScrollOffset( Point(0,0) )
165 ,m_pDragWin( nullptr )
166 ,m_pSizingWin( nullptr )
167 ,m_pSelectedConn( nullptr )
168 ,m_bTrackingInitiallyMoved(false)
169 ,m_pLastFocusTabWin(nullptr)
170 ,m_pView( pView )
171 ,m_pAccessible(nullptr)
173 SetSizePixel( Size(1000, 1000) );
175 InitColors();
177 m_aDragScrollIdle.SetIdleHdl(LINK(this, OJoinTableView, OnDragScrollTimer));
180 OJoinTableView::~OJoinTableView()
182 disposeOnce();
185 void OJoinTableView::dispose()
187 if( m_pAccessible )
189 m_pAccessible->clearTableView();
190 m_pAccessible = nullptr;
192 // delete lists
193 clearLayoutInformation();
194 m_pDragWin.clear();
195 m_pSizingWin.clear();
196 m_pSelectedConn.clear();
197 m_pLastFocusTabWin.clear();
198 m_pView.clear();
199 vcl::Window::dispose();
202 IMPL_LINK_TYPED( OJoinTableView, ScrollHdl, ScrollBar*, pScrollBar, void )
204 // move all windows
205 ScrollPane( pScrollBar->GetDelta(), (pScrollBar == &GetHScrollBar()), false );
208 void OJoinTableView::Resize()
210 Window::Resize();
211 m_aOutputSize = GetSizePixel();
213 // tab win positions may not be up-to-date
214 if (m_aTableMap.empty())
215 // no tab wins ...
216 return;
218 // we have at least one table so resize it
219 m_aScrollOffset.X() = GetHScrollBar().GetThumbPos();
220 m_aScrollOffset.Y() = GetVScrollBar().GetThumbPos();
222 OTableWindow* pCheck = m_aTableMap.begin()->second;
223 Point aRealPos = pCheck->GetPosPixel();
224 Point aAssumedPos = pCheck->GetData()->GetPosition() - GetScrollOffset();
226 if (aRealPos == aAssumedPos)
227 // all ok
228 return;
230 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
231 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
232 for(;aIter != aEnd;++aIter)
234 OTableWindow* pCurrent = aIter->second;
235 Point aPos(pCurrent->GetData()->GetPosition() - GetScrollOffset());
236 pCurrent->SetPosPixel(aPos);
240 sal_uLong OJoinTableView::GetTabWinCount()
242 return m_aTableMap.size();
245 bool OJoinTableView::RemoveConnection(VclPtr<OTableConnection>& rConn, bool _bDelete)
247 VclPtr<OTableConnection> xConn(rConn);
249 DeselectConn(xConn);
251 // to force a redraw
252 xConn->InvalidateConnection();
254 m_pView->getController().removeConnectionData(xConn->GetData());
256 m_vTableConnection.erase(std::find(m_vTableConnection.begin(), m_vTableConnection.end(), xConn));
258 modified();
259 if ( m_pAccessible )
260 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
261 makeAny(xConn->GetAccessible()),
262 Any());
263 if (_bDelete)
264 xConn->disposeOnce();
266 return true;
269 OTableWindow* OJoinTableView::GetTabWindow( const OUString& rName )
271 OTableWindowMap::const_iterator aIter = m_aTableMap.find(rName);
273 return aIter == m_aTableMap.end() ? nullptr : aIter->second;
276 TTableWindowData::value_type OJoinTableView::createTableWindowData(const OUString& _rComposedName
277 ,const OUString& _sTableName
278 ,const OUString& _rWinName)
280 TTableWindowData::value_type pData( CreateImpl(_rComposedName, _sTableName,_rWinName) );
281 OJoinDesignView* pParent = getDesignView();
284 if ( !pData->init(pParent->getController().getConnection(),allowQueries()) )
286 if ( pData->isValid() )
287 onNoColumns_throw();
288 else
289 pData.reset();
292 catch ( const SQLException& )
294 ::dbaui::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ),
295 pParent, pParent->getController().getORB() );
297 catch( const WrappedTargetException& e )
299 SQLException aSql;
300 if ( e.TargetException >>= aSql )
301 ::dbaui::showError( ::dbtools::SQLExceptionInfo( aSql ), pParent, pParent->getController().getORB() );
303 catch( const Exception& )
305 DBG_UNHANDLED_EXCEPTION();
307 return pData;
310 OTableWindowData* OJoinTableView::CreateImpl(const OUString& _rComposedName
311 ,const OUString& _sTableName
312 ,const OUString& _rWinName)
314 return new OTableWindowData( nullptr,_rComposedName,_sTableName, _rWinName );
317 void OJoinTableView::AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool /*bNewTable*/)
319 OSL_ENSURE(!_rComposedName.isEmpty(),"There must be a table name supplied!");
321 TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName ));
323 // insert new window in window list
324 VclPtr<OTableWindow> pNewTabWin = createWindow( pNewTabWinData );
325 if ( pNewTabWin->Init() )
327 m_pView->getController().getTableWindowData().push_back( pNewTabWinData);
328 // when we already have a table with this name insert the full qualified one instead
329 if(m_aTableMap.find(rWinName) != m_aTableMap.end())
330 m_aTableMap[_rComposedName] = pNewTabWin;
331 else
332 m_aTableMap[rWinName] = pNewTabWin;
334 SetDefaultTabWinPosSize( pNewTabWin );
335 pNewTabWin->Show();
337 modified();
338 if ( m_pAccessible )
339 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
340 Any(),
341 makeAny(pNewTabWin->GetAccessible()));
343 else
345 pNewTabWin->clearListBox();
346 pNewTabWin.disposeAndClear();
350 void OJoinTableView::RemoveTabWin( OTableWindow* pTabWin )
352 // first delete all connections of this window to others
353 bool bRemove = true;
354 TTableWindowData::value_type pData = pTabWin->GetData();
355 sal_Int32 nCount = m_vTableConnection.size();
356 auto aIter = m_vTableConnection.rbegin();
357 while(aIter != m_vTableConnection.rend() && bRemove)
359 VclPtr<OTableConnection>& rTabConn = (*aIter);
360 if (
361 (pData == rTabConn->GetData()->getReferencingTable()) ||
362 (pData == rTabConn->GetData()->getReferencedTable())
365 bRemove = RemoveConnection(rTabConn, true);
366 aIter = m_vTableConnection.rbegin();
368 else
369 ++aIter;
372 // then delete the window itself
373 if ( bRemove )
375 if ( m_pAccessible )
376 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
377 makeAny(pTabWin->GetAccessible()),Any()
380 pTabWin->Hide();
381 OJoinController& rController = m_pView->getController();
382 TTableWindowData::iterator aFind = ::std::find(rController.getTableWindowData().begin(), rController.getTableWindowData().end(), pData);
383 if(aFind != rController.getTableWindowData().end())
385 rController.getTableWindowData().erase(aFind);
386 rController.setModified(true);
389 if ( !m_aTableMap.erase( pTabWin->GetWinName() ) )
390 m_aTableMap.erase( pTabWin->GetComposedName() );
392 if (pTabWin == m_pLastFocusTabWin)
393 m_pLastFocusTabWin = nullptr;
395 pTabWin->clearListBox();
396 pTabWin->disposeOnce();
399 if ( (sal_Int32)m_vTableConnection.size() < (nCount-1) ) // if some connections could be removed
400 modified();
403 namespace
405 bool isScrollAllowed( OJoinTableView* _pView,long nDelta, bool bHoriz)
407 // adjust ScrollBar-Positions
408 ScrollBar& rBar = bHoriz ? _pView->GetHScrollBar() : _pView->GetVScrollBar() ;
410 long nOldThumbPos = rBar.GetThumbPos();
411 long nNewThumbPos = nOldThumbPos + nDelta;
412 if( nNewThumbPos < 0 )
413 nNewThumbPos = 0;
414 else if( nNewThumbPos > rBar.GetRangeMax() )
415 nNewThumbPos = rBar.GetRangeMax();
417 if ( bHoriz )
419 if( nNewThumbPos == _pView->GetScrollOffset().X() )
420 return false;
422 else if ( nNewThumbPos == _pView->GetScrollOffset().Y() )
423 return false;
425 return true;
427 bool getMovementImpl(OJoinTableView* _pView,const Point& _rPoint,const Size& _rSize,long& _nScrollX,long& _nScrollY)
429 _nScrollY = _nScrollX = 0;
430 // data about the tab win
431 Point aUpperLeft = _rPoint;
432 // normalize with respect to visibility
433 aUpperLeft -= _pView->GetScrollOffset();
434 Point aLowerRight(aUpperLeft.X() + _rSize.Width(), aUpperLeft.Y() + _rSize.Height());
436 // data about ourself
437 Size aSize = _pView->getRealOutputSize(); //GetOutputSizePixel();
439 bool bVisible = true;
440 bool bFitsHor = (aUpperLeft.X() >= 0) && (aLowerRight.X() <= aSize.Width());
441 bool bFitsVert= (aUpperLeft.Y() >= 0) && (aLowerRight.Y() <= aSize.Height());
442 if (!bFitsHor || !bFitsVert)
444 if (!bFitsHor)
446 // ensure the visibility of the right border
447 if ( aLowerRight.X() > aSize.Width() )
448 _nScrollX = aLowerRight.X() - aSize.Width() + TABWIN_SPACING_X;
450 // ensure the visibility of the left border (higher priority)
451 if ( aUpperLeft.X() < 0 )
452 _nScrollX = aUpperLeft.X() - TABWIN_SPACING_X;
455 if (!bFitsVert)
457 // lower border
458 if ( aLowerRight.Y() > aSize.Height() )
459 _nScrollY = aLowerRight.Y() - aSize.Height() + TABWIN_SPACING_Y;
460 // upper border
461 if ( aUpperLeft.Y() < 0 )
462 _nScrollY = aUpperLeft.Y() - TABWIN_SPACING_Y;
465 if ( _nScrollX ) // aSize.Width() > _rSize.Width() &&
466 bVisible = isScrollAllowed(_pView,_nScrollX, true);
468 if ( _nScrollY ) // aSize.Height() > _rSize.Height() &&
469 bVisible = bVisible && isScrollAllowed(_pView,_nScrollY, false);
471 if ( bVisible )
473 sal_Int32 nHRangeMax = _pView->GetHScrollBar().GetRangeMax();
474 sal_Int32 nVRangeMax = _pView->GetVScrollBar().GetRangeMax();
476 if ( aSize.Width() + _pView->GetHScrollBar().GetThumbPos() + _nScrollX > nHRangeMax )
477 bVisible = false;
478 if ( bVisible && aSize.Height() + _pView->GetVScrollBar().GetThumbPos() + _nScrollY > nVRangeMax )
479 bVisible = false;
483 return bVisible;
485 } // end of ano namespace
487 bool OJoinTableView::isMovementAllowed(const Point& _rPoint,const Size& _rSize)
489 long nX,nY;
490 return getMovementImpl(this,_rPoint,_rSize,nX,nY);
493 void OJoinTableView::EnsureVisible(const OTableWindow* _pWin)
495 // data about the tab win
496 TTableWindowData::value_type pData = _pWin->GetData();
497 EnsureVisible( pData->GetPosition() , pData->GetSize());
498 Invalidate(InvalidateFlags::NoChildren);
501 void OJoinTableView::EnsureVisible(const Point& _rPoint,const Size& _rSize)
503 long nScrollX,nScrollY;
505 if ( getMovementImpl(this,_rPoint,_rSize,nScrollX,nScrollY) )
507 bool bVisible = true;
508 if (nScrollX)
509 bVisible = ScrollPane(nScrollX, true, true);
511 if (nScrollY && bVisible)
512 ScrollPane(nScrollY, false, true);
516 void OJoinTableView::SetDefaultTabWinPosSize( OTableWindow* pTabWin )
518 // determine position:
519 // the window is divided into lines with height TABWIN_SPACING_Y+TABWIN_HEIGHT_STD.
520 // Then for each line is checked, if there is space for another window.
521 // If there is no space, the next line is checked.
522 Size aOutSize = GetSizePixel();
523 Point aNewPos( 0,0 );
524 sal_uInt16 nRow = 0;
525 bool bEnd = false;
526 while( !bEnd )
528 // Set new position to start of line
529 aNewPos.X() = TABWIN_SPACING_X;
530 aNewPos.Y() = (nRow+1) * TABWIN_SPACING_Y;
532 // determine rectangle for the corresponding line
533 Rectangle aRowRect( Point(0,0), aOutSize );
534 aRowRect.Top() = nRow * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD );
535 aRowRect.Bottom() = (nRow+1) * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD );
537 // check occupied areas of this line
538 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
539 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
540 for(;aIter != aEnd;++aIter)
542 OTableWindow* pOtherTabWin = aIter->second;
543 Rectangle aOtherTabWinRect( pOtherTabWin->GetPosPixel(), pOtherTabWin->GetSizePixel() );
546 ( (aOtherTabWinRect.Top()>aRowRect.Top()) && (aOtherTabWinRect.Top()<aRowRect.Bottom()) ) ||
547 ( (aOtherTabWinRect.Bottom()>aRowRect.Top()) && (aOtherTabWinRect.Bottom()<aRowRect.Bottom()) )
550 // TabWin is in the line
551 if( aOtherTabWinRect.Right()>aNewPos.X() )
552 aNewPos.X() = aOtherTabWinRect.Right() + TABWIN_SPACING_X;
556 // Is there space left in this line?
557 if( (aNewPos.X()+TABWIN_WIDTH_STD)<aRowRect.Right() )
559 aNewPos.Y() = aRowRect.Top() + TABWIN_SPACING_Y;
560 bEnd = true;
562 else
564 if( (aRowRect.Bottom()+aRowRect.GetHeight()) > aOutSize.Height() )
566 // insert it in the first row
567 sal_Int32 nCount = m_aTableMap.size() % (nRow+1);
568 ++nCount;
569 aNewPos.Y() = nCount * TABWIN_SPACING_Y + (nCount-1)*CalcZoom(TABWIN_HEIGHT_STD);
570 bEnd = true;
572 else
573 nRow++;
578 // determine size
579 Size aNewSize( CalcZoom(TABWIN_WIDTH_STD), CalcZoom(TABWIN_HEIGHT_STD) );
581 // check if the new position in inside the scrollbars ranges
582 Point aBottom(aNewPos);
583 aBottom.X() += aNewSize.Width();
584 aBottom.Y() += aNewSize.Height();
586 if(!GetHScrollBar().GetRange().IsInside(aBottom.X()))
587 GetHScrollBar().SetRange( Range(0, aBottom.X()) );
588 if(!GetVScrollBar().GetRange().IsInside(aBottom.Y()))
589 GetVScrollBar().SetRange( Range(0, aBottom.Y()) );
591 pTabWin->SetPosSizePixel( aNewPos, aNewSize );
594 void OJoinTableView::DataChanged(const DataChangedEvent& rDCEvt)
596 if (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
598 // consider the worst case: the colors changed, so adjust me
599 InitColors();
600 Invalidate(InvalidateFlags::NoChildren);
601 // due to the Invalidate, the connections are redrawn, so that they are also pictured in the new colors
605 void OJoinTableView::InitColors()
607 // the colors for the illustration should be the system colors
608 StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
609 SetBackground(Wallpaper(Color(aSystemStyle.GetDialogColor())));
612 void OJoinTableView::BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos )
615 if (m_pView->getController().isReadOnly())
616 return;
618 m_pDragWin = pTabWin;
619 SetPointer(Pointer(PointerStyle::Move));
620 Point aMousePos = ScreenToOutputPixel( rMousePos );
621 m_aDragOffset = aMousePos - pTabWin->GetPosPixel();
622 m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
623 m_bTrackingInitiallyMoved = false;
624 StartTracking();
627 void OJoinTableView::NotifyTitleClicked( OTableWindow* pTabWin, const Point& rMousePos )
629 DeselectConn(GetSelectedConn());
630 BeginChildMove(pTabWin, rMousePos);
633 void OJoinTableView::BeginChildSizing( OTableWindow* pTabWin, const Pointer& rPointer )
636 if (m_pView->getController().isReadOnly())
637 return;
639 SetPointer( rPointer );
640 m_pSizingWin = pTabWin;
641 StartTracking();
644 bool OJoinTableView::ScrollPane( long nDelta, bool bHoriz, bool bPaintScrollBars )
646 bool bRet = true;
648 // adjust ScrollBar-Positions
649 if( bPaintScrollBars )
651 if( bHoriz )
653 long nOldThumbPos = GetHScrollBar().GetThumbPos();
654 long nNewThumbPos = nOldThumbPos + nDelta;
655 if( nNewThumbPos < 0 )
657 nNewThumbPos = 0;
658 bRet = false;
660 if( nNewThumbPos > GetHScrollBar().GetRange().Max() )
662 nNewThumbPos = GetHScrollBar().GetRange().Max();
663 bRet = false;
665 GetHScrollBar().SetThumbPos( nNewThumbPos );
666 nDelta = GetHScrollBar().GetThumbPos() - nOldThumbPos;
668 else
670 long nOldThumbPos = GetVScrollBar().GetThumbPos();
671 long nNewThumbPos = nOldThumbPos+nDelta;
672 if( nNewThumbPos < 0 )
674 nNewThumbPos = 0;
675 bRet = false;
677 if( nNewThumbPos > GetVScrollBar().GetRange().Max() )
679 nNewThumbPos = GetVScrollBar().GetRange().Max();
680 bRet = false;
682 GetVScrollBar().SetThumbPos( nNewThumbPos );
683 nDelta = GetVScrollBar().GetThumbPos() - nOldThumbPos;
687 // If ScrollOffset hitting borders, no redrawing.
688 if( (GetHScrollBar().GetThumbPos()==m_aScrollOffset.X()) &&
689 (GetVScrollBar().GetThumbPos()==m_aScrollOffset.Y()) )
690 return false;
692 // set ScrollOffset anew
693 if (bHoriz)
694 m_aScrollOffset.X() = GetHScrollBar().GetThumbPos();
695 else
696 m_aScrollOffset.Y() = GetVScrollBar().GetThumbPos();
698 // move all windows
699 OTableWindow* pTabWin;
700 Point aPos;
702 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
703 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
704 for(;aIter != aEnd;++aIter)
706 pTabWin = aIter->second;
707 aPos = pTabWin->GetPosPixel();
709 if( bHoriz )
710 aPos.X() -= nDelta;
711 else aPos.Y() -= nDelta;
713 pTabWin->SetPosPixel( aPos );
716 Invalidate(); // InvalidateFlags::NoChildren
718 return bRet;
721 void OJoinTableView::Tracking( const TrackingEvent& rTEvt )
723 HideTracking();
725 if (rTEvt.IsTrackingEnded())
727 if( m_pDragWin )
729 if (m_aDragScrollIdle.IsActive())
730 m_aDragScrollIdle.Stop();
732 // adjust position of child after moving
733 // windows are not allowed to leave display range
734 Point aDragWinPos = rTEvt.GetMouseEvent().GetPosPixel() - m_aDragOffset;
735 Size aDragWinSize = m_pDragWin->GetSizePixel();
736 if( aDragWinPos.X() < 0 )
737 aDragWinPos.X() = 0;
738 if( aDragWinPos.Y() < 0 )
739 aDragWinPos.Y() = 0;
740 if( (aDragWinPos.X() + aDragWinSize.Width()) > m_aOutputSize.Width() )
741 aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width() - 1;
742 if( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() )
743 aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height() - 1;
744 if( aDragWinPos.X() < 0 )
745 aDragWinPos.X() = 0;
746 if( aDragWinPos.Y() < 0 )
747 aDragWinPos.Y() = 0;
748 // TODO : don't position window anew, if it is leaving range, but just expand the range
750 // position window
751 EndTracking();
752 m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
753 // check, if I really moved
754 // (this prevents setting the modified-Flag, when there actually was no change0
755 TTableWindowData::value_type pData = m_pDragWin->GetData();
756 if ( ! (pData && pData->HasPosition() && (pData->GetPosition() == aDragWinPos)))
758 // old logic coordinates
759 Point ptOldPos = m_pDragWin->GetPosPixel() + Point(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
760 // new positioning
761 m_pDragWin->SetPosPixel(aDragWinPos);
762 TabWinMoved(m_pDragWin, ptOldPos);
764 m_pDragWin->GrabFocus();
766 m_pDragWin = nullptr;
767 SetPointer(Pointer(PointerStyle::Arrow));
769 // else we handle the resizing
770 else if( m_pSizingWin )
772 SetPointer( Pointer() );
773 EndTracking();
775 // old physical coordinates
777 Size szOld = m_pSizingWin->GetSizePixel();
778 Point ptOld = m_pSizingWin->GetPosPixel();
779 Size aNewSize(CalcZoom(m_aSizingRect.GetSize().Width()),CalcZoom(m_aSizingRect.GetSize().Height()));
780 m_pSizingWin->SetPosSizePixel( m_aSizingRect.TopLeft(), aNewSize );
781 TabWinSized(m_pSizingWin, ptOld, szOld);
783 m_pSizingWin->Invalidate( m_aSizingRect );
784 m_pSizingWin = nullptr;
787 else if (rTEvt.IsTrackingCanceled())
789 if (m_aDragScrollIdle.IsActive())
790 m_aDragScrollIdle.Stop();
791 EndTracking();
793 else
795 if( m_pDragWin )
797 m_ptPrevDraggingPos = rTEvt.GetMouseEvent().GetPosPixel();
798 // scroll at window borders
799 ScrollWhileDragging();
802 if( m_pSizingWin )
804 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
805 m_aSizingRect = m_pSizingWin->getSizingRect(aMousePos,m_aOutputSize);
806 Update();
807 ShowTracking( m_aSizingRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
812 void OJoinTableView::ConnDoubleClicked(VclPtr<OTableConnection>& /*rConnection*/)
816 void OJoinTableView::MouseButtonDown( const MouseEvent& rEvt )
818 GrabFocus();
819 Window::MouseButtonDown(rEvt);
822 void OJoinTableView::MouseButtonUp( const MouseEvent& rEvt )
824 Window::MouseButtonUp(rEvt);
825 // Has a connection been selected?
826 if( !m_vTableConnection.empty() )
828 DeselectConn(GetSelectedConn());
830 auto aIter = m_vTableConnection.begin();
831 auto aEnd = m_vTableConnection.end();
832 for(;aIter != aEnd;++aIter)
834 if( (*aIter)->CheckHit(rEvt.GetPosPixel()) )
836 SelectConn((*aIter));
838 // Double-click
839 if( rEvt.GetClicks() == 2 )
840 ConnDoubleClicked( (*aIter) );
842 break;
848 void OJoinTableView::KeyInput( const KeyEvent& rEvt )
850 sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
851 bool bShift = rEvt.GetKeyCode().IsShift();
852 bool bCtrl = rEvt.GetKeyCode().IsMod1();
854 if( !bCtrl && !bShift && (nCode==KEY_DELETE) )
856 if (GetSelectedConn())
857 RemoveConnection(GetSelectedConn(), true);
859 else
860 Window::KeyInput( rEvt );
863 void OJoinTableView::DeselectConn(OTableConnection* pConn)
865 if (!pConn || !pConn->IsSelected())
866 return;
868 // deselect the corresponding entries in the ListBox of the table window
869 OTableWindow* pWin = pConn->GetSourceWin();
870 if (pWin && pWin->GetListBox())
871 pWin->GetListBox()->SelectAll(false);
873 pWin = pConn->GetDestWin();
874 if (pWin && pWin->GetListBox())
875 pWin->GetListBox()->SelectAll(false);
877 pConn->Deselect();
878 m_pSelectedConn = nullptr;
881 void OJoinTableView::SelectConn(OTableConnection* pConn)
883 DeselectConn(GetSelectedConn());
885 pConn->Select();
886 m_pSelectedConn = pConn;
887 GrabFocus(); // has to be called here because a table window may still be focused
889 // select the concerned entries in the windows
890 OTableWindow* pConnSource = pConn->GetSourceWin();
891 OTableWindow* pConnDest = pConn->GetDestWin();
892 if (pConnSource && pConnDest)
894 OTableWindowListBox* pSourceBox = pConnSource->GetListBox();
895 OTableWindowListBox* pDestBox = pConnDest->GetListBox();
896 if (pSourceBox && pDestBox)
898 pSourceBox->SelectAll(false);
899 pDestBox->SelectAll(false);
901 SvTreeListEntry* pFirstSourceVisible = pSourceBox->GetFirstEntryInView();
902 SvTreeListEntry* pFirstDestVisible = pDestBox->GetFirstEntryInView();
904 const ::std::vector<OConnectionLine*>& rLines = pConn->GetConnLineList();
905 ::std::vector<OConnectionLine*>::const_reverse_iterator aIter = rLines.rbegin();
906 for(;aIter != rLines.rend();++aIter)
908 if ((*aIter)->IsValid())
910 SvTreeListEntry* pSourceEntry = pSourceBox->GetEntryFromText((*aIter)->GetData()->GetSourceFieldName());
911 if (pSourceEntry)
913 pSourceBox->Select(pSourceEntry);
914 pSourceBox->MakeVisible(pSourceEntry);
917 SvTreeListEntry* pDestEntry = pDestBox->GetEntryFromText((*aIter)->GetData()->GetDestFieldName());
918 if (pDestEntry)
920 pDestBox->Select(pDestEntry);
921 pDestBox->MakeVisible(pDestEntry);
927 if ((pFirstSourceVisible != pSourceBox->GetFirstEntryInView())
928 || (pFirstDestVisible != pDestBox->GetFirstEntryInView()))
929 // scrolling was done -> redraw
930 Invalidate(InvalidateFlags::NoChildren);
935 void OJoinTableView::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
937 DrawConnections(rRenderContext, rRect);
940 void OJoinTableView::InvalidateConnections()
942 // draw Joins
943 for (auto & conn : m_vTableConnection)
944 conn->InvalidateConnection();
947 void OJoinTableView::DrawConnections(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
949 // draw Joins
950 for(const auto& connection : m_vTableConnection)
951 connection->Draw(rRenderContext, rRect);
952 // finally redraw the selected one above all others
953 if (GetSelectedConn())
954 GetSelectedConn()->Draw(rRenderContext, rRect);
957 ::std::vector<VclPtr<OTableConnection> >::const_iterator OJoinTableView::getTableConnections(const OTableWindow* _pFromWin) const
959 return ::std::find_if( m_vTableConnection.begin(),
960 m_vTableConnection.end(),
961 ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin));
964 sal_Int32 OJoinTableView::getConnectionCount(const OTableWindow* _pFromWin) const
966 return ::std::count_if( m_vTableConnection.begin(),
967 m_vTableConnection.end(),
968 ::std::bind2nd(::std::mem_fun(&OTableConnection::isTableConnection),_pFromWin));
971 bool OJoinTableView::ExistsAConn(const OTableWindow* pFrom) const
973 return getTableConnections(pFrom) != m_vTableConnection.end();
976 void OJoinTableView::ClearAll()
978 SetUpdateMode(false);
980 HideTabWins();
982 // and the same with the Connections
983 while(true)
985 auto aIter = m_vTableConnection.begin();
986 if (aIter == m_vTableConnection.end())
987 break;
988 RemoveConnection(*aIter, true);
990 m_vTableConnection.clear();
992 m_pLastFocusTabWin = nullptr;
993 m_pSelectedConn = nullptr;
995 // scroll to the upper left
996 ScrollPane(-GetScrollOffset().X(), true, true);
997 ScrollPane(-GetScrollOffset().Y(), false, true);
998 Invalidate();
1001 void OJoinTableView::ScrollWhileDragging()
1003 OSL_ENSURE(m_pDragWin != nullptr, "OJoinTableView::ScrollWhileDragging must not be called when a window is being dragged !");
1005 // kill the timer
1006 if (m_aDragScrollIdle.IsActive())
1007 m_aDragScrollIdle.Stop();
1009 Point aDragWinPos = m_ptPrevDraggingPos - m_aDragOffset;
1010 Size aDragWinSize = m_pDragWin->GetSizePixel();
1011 Point aLowerRight(aDragWinPos.X() + aDragWinSize.Width(), aDragWinPos.Y() + aDragWinSize.Height());
1013 if (!m_bTrackingInitiallyMoved && (aDragWinPos == m_pDragWin->GetPosPixel()))
1014 return;
1016 // avoid illustration errors (when scrolling with active TrackingRect)
1017 HideTracking();
1019 bool bScrolling = false;
1020 bool bNeedScrollTimer = false;
1022 // scroll at window borders
1023 // TODO : only catch, if window would disappear completely (don't, if there is still a pixel visible)
1024 if( aDragWinPos.X() < 5 )
1026 bScrolling = ScrollPane( -LINE_SIZE, true, true );
1027 if( !bScrolling && (aDragWinPos.X()<0) )
1028 aDragWinPos.X() = 0;
1030 // do I need further (timer controlled) scrolling ?
1031 bNeedScrollTimer = bScrolling && (aDragWinPos.X() < 5);
1034 if( aLowerRight.X() > m_aOutputSize.Width() - 5 )
1036 bScrolling = ScrollPane( LINE_SIZE, true, true ) ;
1037 if( !bScrolling && ( aLowerRight.X() > m_aOutputSize.Width() ) )
1038 aDragWinPos.X() = m_aOutputSize.Width() - aDragWinSize.Width();
1040 // do I need further (timer controlled) scrolling ?
1041 bNeedScrollTimer = bScrolling && (aLowerRight.X() > m_aOutputSize.Width() - 5);
1044 if( aDragWinPos.Y() < 5 )
1046 bScrolling = ScrollPane( -LINE_SIZE, false, true );
1047 if( !bScrolling && (aDragWinPos.Y()<0) )
1048 aDragWinPos.Y() = 0;
1050 bNeedScrollTimer = bScrolling && (aDragWinPos.Y() < 5);
1053 if( aLowerRight.Y() > m_aOutputSize.Height() - 5 )
1055 bScrolling = ScrollPane( LINE_SIZE, false, true );
1056 if( !bScrolling && ( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) )
1057 aDragWinPos.Y() = m_aOutputSize.Height() - aDragWinSize.Height();
1059 bNeedScrollTimer = bScrolling && (aLowerRight.Y() > m_aOutputSize.Height() - 5);
1062 // resetting timer, if still necessary
1063 if (bNeedScrollTimer)
1065 m_aDragScrollIdle.SetPriority(SchedulerPriority::LOW);
1066 m_aDragScrollIdle.Start();
1069 // redraw DraggingRect
1070 m_aDragRect = Rectangle(m_ptPrevDraggingPos - m_aDragOffset, m_pDragWin->GetSizePixel());
1071 Update();
1072 ShowTracking( m_aDragRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
1075 IMPL_LINK_NOARG_TYPED(OJoinTableView, OnDragScrollTimer, Idle *, void)
1077 ScrollWhileDragging();
1080 void OJoinTableView::invalidateAndModify(SfxUndoAction *_pAction)
1082 Invalidate(InvalidateFlags::NoChildren);
1083 m_pView->getController().addUndoActionAndInvalidate(_pAction);
1086 void OJoinTableView::TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition)
1088 Point ptThumbPos(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
1089 ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel() + ptThumbPos);
1091 invalidateAndModify(new OJoinMoveTabWinUndoAct(this, ptOldPosition, ptWhich));
1094 void OJoinTableView::TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize)
1096 ptWhich->GetData()->SetSize(ptWhich->GetSizePixel());
1097 ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel());
1099 invalidateAndModify(new OJoinSizeTabWinUndoAct(this, ptOldPosition, szOldSize, ptWhich));
1102 bool OJoinTableView::IsAddAllowed()
1105 // not, if Db readonly
1106 if (m_pView->getController().isReadOnly())
1107 return false;
1111 Reference< XConnection> xConnection = m_pView->getController().getConnection();
1112 if(!xConnection.is())
1113 return false;
1114 // not, if too many tables already
1115 Reference < XDatabaseMetaData > xMetaData( xConnection->getMetaData() );
1117 sal_Int32 nMax = xMetaData.is() ? xMetaData->getMaxTablesInSelect() : 0;
1118 if (nMax && nMax <= (sal_Int32)m_aTableMap.size())
1119 return false;
1121 catch(SQLException&)
1123 return false;
1126 return true;
1129 void OJoinTableView::executePopup(const Point& _aPos, VclPtr<OTableConnection>& rSelConnection)
1131 PopupMenu aContextMenu( ModuleRes( RID_MENU_JOINVIEW_CONNECTION ) );
1132 switch (aContextMenu.Execute(this, _aPos))
1134 case SID_DELETE:
1135 RemoveConnection(rSelConnection, true);
1136 break;
1137 case ID_QUERY_EDIT_JOINCONNECTION:
1138 ConnDoubleClicked(rSelConnection); // is the same as double clicked
1139 break;
1143 void OJoinTableView::Command(const CommandEvent& rEvt)
1146 bool bHandled = false;
1148 switch (rEvt.GetCommand())
1150 case CommandEventId::ContextMenu:
1152 if( m_vTableConnection.empty() )
1153 return;
1155 VclPtr<OTableConnection>& rSelConnection = GetSelectedConn();
1156 // when it wasn't a mouse event use the selected connection
1157 if (!rEvt.IsMouseEvent())
1159 if (rSelConnection)
1161 const ::std::vector<OConnectionLine*>& rLines = rSelConnection->GetConnLineList();
1162 ::std::vector<OConnectionLine*>::const_iterator aIter = ::std::find_if(rLines.begin(), rLines.end(),::std::mem_fun(&OConnectionLine::IsValid));
1163 if( aIter != rLines.end() )
1164 executePopup((*aIter)->getMidPoint(), rSelConnection);
1167 else
1169 DeselectConn(rSelConnection);
1171 const Point& aMousePos = rEvt.GetMousePosPixel();
1172 auto aIter = m_vTableConnection.begin();
1173 auto aEnd = m_vTableConnection.end();
1174 for(;aIter != aEnd;++aIter)
1176 if( (*aIter)->CheckHit(aMousePos) )
1178 SelectConn(*aIter);
1179 if(!getDesignView()->getController().isReadOnly() && getDesignView()->getController().isConnected())
1180 executePopup(rEvt.GetMousePosPixel(),*aIter);
1181 break;
1185 bHandled = true;
1187 break;
1188 default: break;
1190 if (!bHandled)
1191 Window::Command(rEvt);
1194 OTableConnection* OJoinTableView::GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSupressCrossOrNaturalJoin,const OTableConnection* _rpFirstAfter) const
1196 OTableConnection* pConn = nullptr;
1197 OSL_ENSURE(pRhs || pLhs, "OJoinTableView::GetTabConn : invalid args !");
1198 // only one NULL-arg allowed
1200 if ((!pLhs || pLhs->ExistsAConn()) && (!pRhs || pRhs->ExistsAConn()))
1202 bool bFoundStart = _rpFirstAfter == nullptr;
1204 auto aIter = m_vTableConnection.begin();
1205 auto aEnd = m_vTableConnection.end();
1206 for(;aIter != aEnd;++aIter)
1208 OTableConnection* pData = *aIter;
1210 if ( ( (pData->GetSourceWin() == pLhs)
1211 && ( (pData->GetDestWin() == pRhs)
1212 || (nullptr == pRhs)
1215 || ( (pData->GetSourceWin() == pRhs)
1216 && ( (pData->GetDestWin() == pLhs)
1217 || (nullptr == pLhs)
1222 if ( _bSupressCrossOrNaturalJoin )
1224 if ( supressCrossNaturalJoin(pData->GetData()) )
1225 continue;
1227 if (bFoundStart)
1229 pConn = pData;
1230 break;
1233 if (!pConn)
1234 // used as fallback : if there is no conn after _rpFirstAfter the first conn between the two tables
1235 // will be used
1236 pConn = pData;
1238 if (pData == _rpFirstAfter)
1239 bFoundStart = true;
1243 return pConn;
1246 bool OJoinTableView::PreNotify(NotifyEvent& rNEvt)
1248 bool bHandled = false;
1249 switch (rNEvt.GetType())
1251 case MouseNotifyEvent::COMMAND:
1253 const CommandEvent* pCommand = rNEvt.GetCommandEvent();
1254 if (pCommand->GetCommand() == CommandEventId::Wheel)
1256 const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
1257 if (pData->GetMode() == CommandWheelMode::SCROLL)
1259 if (pData->GetDelta() > 0)
1260 ScrollPane(-10 * pData->GetScrollLines(), pData->IsHorz(), true);
1261 else
1262 ScrollPane(10 * pData->GetScrollLines(), pData->IsHorz(), true);
1263 bHandled = true;
1267 break;
1268 case MouseNotifyEvent::KEYINPUT:
1270 if (m_aTableMap.empty())
1271 // no tab wins -> no conns -> no traveling
1272 break;
1274 const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
1275 if (!pKeyEvent->GetKeyCode().IsMod1())
1277 switch (pKeyEvent->GetKeyCode().GetCode())
1279 case KEY_TAB:
1281 if (!HasChildPathFocus())
1282 break;
1284 bool bForward = !pKeyEvent->GetKeyCode().IsShift();
1285 // is there an active tab win ?
1286 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
1287 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
1288 for(;aIter != aEnd;++aIter)
1289 if (aIter->second && aIter->second->HasChildPathFocus())
1290 break;
1292 OTableWindow* pNextWin = nullptr;
1293 OTableConnection* pNextConn = nullptr;
1295 if (aIter != m_aTableMap.end())
1296 { // there is a currently active tab win
1297 // check if there is an "overflow" and we should select a conn instead of a win
1298 if (!m_vTableConnection.empty())
1300 if ((aIter->second == m_aTableMap.rbegin()->second) && bForward)
1301 // the last win is active and we're travelling forward -> select the first conn
1302 pNextConn = *m_vTableConnection.begin();
1303 if ((aIter == m_aTableMap.begin()) && !bForward)
1304 // the first win is active an we're traveling backward -> select the last conn
1305 pNextConn = *m_vTableConnection.rbegin();
1308 if (!pNextConn)
1310 // no conn for any reason -> select the next or previous tab win
1311 if(bForward)
1313 if ( aIter->second == m_aTableMap.rbegin()->second )
1314 pNextWin = m_aTableMap.begin()->second;
1315 else
1317 ++aIter;
1318 pNextWin = aIter->second;
1321 else
1323 if (aIter == m_aTableMap.begin())
1324 pNextWin = m_aTableMap.rbegin()->second;
1325 else
1327 --aIter;
1328 pNextWin = aIter->second;
1333 else
1334 { // no active tab win -> travel the connections
1335 // find the currently selected conn within the conn list
1336 sal_Int32 i(0);
1337 for ( auto connectionIter = m_vTableConnection.begin();
1338 connectionIter != m_vTableConnection.end();
1339 ++connectionIter, ++i
1342 if ( (*connectionIter).get() == GetSelectedConn() )
1343 break;
1345 if (i == sal_Int32(m_vTableConnection.size() - 1) && bForward)
1346 // the last conn is active and we're travelling forward -> select the first win
1347 pNextWin = m_aTableMap.begin()->second;
1348 if ((i == 0) && !bForward && !m_aTableMap.empty())
1349 // the first conn is active and we're travelling backward -> select the last win
1350 pNextWin = m_aTableMap.rbegin()->second;
1352 if (pNextWin)
1353 DeselectConn(GetSelectedConn());
1354 else
1355 // no win for any reason -> select the next or previous conn
1356 if (i < (sal_Int32)m_vTableConnection.size())
1357 // there is a currently active conn
1358 pNextConn = m_vTableConnection[(i + (bForward ? 1 : m_vTableConnection.size() - 1)) % m_vTableConnection.size()];
1359 else
1360 { // no tab win selected, no conn selected
1361 if (!m_vTableConnection.empty())
1362 pNextConn = m_vTableConnection[bForward ? 0 : m_vTableConnection.size() - 1];
1363 else if (!m_aTableMap.empty())
1365 if(bForward)
1366 pNextWin = m_aTableMap.begin()->second;
1367 else
1368 pNextWin = m_aTableMap.rbegin()->second;
1373 // now select the object
1374 if (pNextWin)
1376 if (pNextWin->GetListBox())
1377 pNextWin->GetListBox()->GrabFocus();
1378 else
1379 pNextWin->GrabFocus();
1380 EnsureVisible(pNextWin);
1382 else if (pNextConn)
1384 GrabFocus();
1385 // necessary : a conn may be selected even if a tab win has the focus, in this case
1386 // the next travel would select the same conn again if we would not reset the focus ...
1387 SelectConn(pNextConn);
1390 break;
1391 case KEY_RETURN:
1393 if (!pKeyEvent->GetKeyCode().IsShift() && GetSelectedConn() && HasFocus())
1394 ConnDoubleClicked(GetSelectedConn());
1395 break;
1400 break;
1401 case MouseNotifyEvent::GETFOCUS:
1403 if (m_aTableMap.empty())
1404 // no tab wins -> no conns -> no focus change
1405 break;
1406 vcl::Window* pSource = rNEvt.GetWindow();
1407 if (pSource)
1409 vcl::Window* pSearchFor = nullptr;
1410 if (pSource->GetParent() == this)
1411 // it may be one of the tab wins
1412 pSearchFor = pSource;
1413 else if (pSource->GetParent() && (pSource->GetParent()->GetParent() == this))
1414 // it may be one of th list boxes of one of the tab wins
1415 pSearchFor = pSource->GetParent();
1417 if (pSearchFor)
1419 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
1420 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
1421 for(;aIter != aEnd;++aIter)
1423 if (aIter->second == pSearchFor)
1425 m_pLastFocusTabWin = aIter->second;
1426 break;
1432 break;
1433 default:
1434 break;
1437 if (!bHandled)
1438 return Window::PreNotify(rNEvt);
1439 return true;
1442 void OJoinTableView::GrabTabWinFocus()
1444 if (m_pLastFocusTabWin && m_pLastFocusTabWin->IsVisible())
1446 if (m_pLastFocusTabWin->GetListBox())
1447 m_pLastFocusTabWin->GetListBox()->GrabFocus();
1448 else
1449 m_pLastFocusTabWin->GrabFocus();
1451 else if (!m_aTableMap.empty() && m_aTableMap.begin()->second && m_aTableMap.begin()->second->IsVisible())
1453 OTableWindow* pFirstWin = m_aTableMap.begin()->second;
1454 if (pFirstWin->GetListBox())
1455 pFirstWin->GetListBox()->GrabFocus();
1456 else
1457 pFirstWin->GrabFocus();
1461 void OJoinTableView::StateChanged( StateChangedType nType )
1463 Window::StateChanged( nType );
1465 // FIXME RenderContext
1466 if ( nType == StateChangedType::Zoom )
1468 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1470 vcl::Font aFont = rStyleSettings.GetGroupFont();
1471 if ( IsControlFont() )
1472 aFont.Merge( GetControlFont() );
1473 SetZoomedPointFont(*this, aFont);
1475 OTableWindowMap::const_iterator aIter = m_aTableMap.begin();
1476 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
1477 for(;aIter != aEnd;++aIter)
1479 aIter->second->SetZoom(GetZoom());
1480 Size aSize(CalcZoom(aIter->second->GetSizePixel().Width()),CalcZoom(aIter->second->GetSizePixel().Height()));
1481 aIter->second->SetSizePixel(aSize);
1483 Resize();
1487 void OJoinTableView::HideTabWins()
1489 SetUpdateMode(false);
1491 OTableWindowMap& rTabWins = GetTabWinMap();
1493 // working on a copy because the real list will be cleared in inner calls
1494 OTableWindowMap aCopy(rTabWins);
1495 OTableWindowMap::const_iterator aIter = aCopy.begin();
1496 OTableWindowMap::const_iterator aEnd = aCopy.end();
1497 for(;aIter != aEnd;++aIter)
1498 RemoveTabWin(aIter->second);
1500 m_pView->getController().setModified(true);
1502 SetUpdateMode(true);
1506 sal_Int8 OJoinTableView::AcceptDrop( const AcceptDropEvent& /*_rEvt*/ )
1508 return DND_ACTION_NONE;
1511 sal_Int8 OJoinTableView::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
1513 return DND_ACTION_NONE;
1516 void OJoinTableView::dragFinished( )
1520 void OJoinTableView::clearLayoutInformation()
1522 m_pLastFocusTabWin = nullptr;
1523 m_pSelectedConn = nullptr;
1524 // delete lists
1525 OTableWindowMap::iterator aIter = m_aTableMap.begin();
1526 OTableWindowMap::const_iterator aEnd = m_aTableMap.end();
1527 for(;aIter != aEnd;++aIter)
1529 if ( aIter->second )
1530 aIter->second->clearListBox();
1531 aIter->second.disposeAndClear();
1534 m_aTableMap.clear();
1536 for(auto i = m_vTableConnection.begin();
1537 i != m_vTableConnection.end(); ++i)
1538 i->disposeAndClear();
1540 m_vTableConnection.clear();
1543 void OJoinTableView::lookForUiActivities()
1547 void OJoinTableView::LoseFocus()
1549 DeselectConn(GetSelectedConn());
1550 Window::LoseFocus();
1553 void OJoinTableView::GetFocus()
1555 Window::GetFocus();
1556 if ( !m_aTableMap.empty() && !GetSelectedConn() )
1557 GrabTabWinFocus();
1560 Reference< XAccessible > OJoinTableView::CreateAccessible()
1562 m_pAccessible = new OJoinDesignViewAccess(this);
1563 return m_pAccessible;
1566 void OJoinTableView::modified()
1568 OJoinController& rController = m_pView->getController();
1569 rController.setModified( true );
1570 rController.InvalidateFeature(ID_BROWSER_ADDTABLE);
1571 rController.InvalidateFeature(SID_RELATION_ADD_RELATION);
1574 void OJoinTableView::addConnection(OTableConnection* _pConnection,bool _bAddData)
1576 if ( _bAddData )
1578 #if OSL_DEBUG_LEVEL > 0
1579 TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
1580 OSL_ENSURE( ::std::find(rTabConnDataList.begin(), rTabConnDataList.end(),_pConnection->GetData()) == rTabConnDataList.end(),"Data already in vector!");
1581 #endif
1582 m_pView->getController().getTableConnectionData().push_back(_pConnection->GetData());
1584 m_vTableConnection.push_back(_pConnection);
1585 _pConnection->RecalcLines();
1586 _pConnection->InvalidateConnection();
1588 modified();
1589 if ( m_pAccessible )
1590 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
1591 Any(),
1592 makeAny(_pConnection->GetAccessible()));
1595 bool OJoinTableView::allowQueries() const
1597 return true;
1600 void OJoinTableView::onNoColumns_throw()
1602 OSL_FAIL( "OTableWindow::onNoColumns_throw: cannot really handle this!" );
1603 throw SQLException();
1606 bool OJoinTableView::supressCrossNaturalJoin(const TTableConnectionData::value_type& ) const
1608 return false;
1611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */