Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / dbaccess / source / ui / querydesign / JoinTableView.cxx
blob001a76a76d86cf87970914291e64ce7f0e862d62
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 <JoinController.hxx>
23 #include <JoinDesignView.hxx>
24 #include <TableWindow.hxx>
25 #include <TableWindowListBox.hxx>
26 #include <TableConnection.hxx>
27 #include <TableConnectionData.hxx>
28 #include <ConnectionLine.hxx>
29 #include <ConnectionLineData.hxx>
30 #include <browserids.hxx>
31 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
32 #include <com/sun/star/sdbc/SQLException.hpp>
33 #include "QueryMoveTabWinUndoAct.hxx"
34 #include "QuerySizeTabWinUndoAct.hxx"
35 #include <toolkit/helper/vclunohelper.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/settings.hxx>
38 #include <vcl/commandevent.hxx>
39 #include <vcl/event.hxx>
40 #include <vcl/ptrstyle.hxx>
41 #include <vcl/weldutils.hxx>
42 #include <TableWindowData.hxx>
43 #include <JAccess.hxx>
44 #include <com/sun/star/accessibility/XAccessible.hpp>
45 #include <com/sun/star/accessibility/AccessibleRole.hpp>
46 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
47 #include <cppuhelper/exc_hlp.hxx>
48 #include <connectivity/dbtools.hxx>
49 #include <comphelper/diagnose_ex.hxx>
50 #include <algorithm>
51 #include <functional>
53 using namespace dbaui;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::sdbc;
56 using namespace ::com::sun::star::accessibility;
57 using namespace ::com::sun::star::lang;
59 #define LINE_SIZE 50
60 // Constants for the window layout
61 #define TABWIN_SPACING_X 17
62 #define TABWIN_SPACING_Y 17
64 #define TABWIN_WIDTH_STD 120
65 #define TABWIN_HEIGHT_STD 120
67 OScrollWindowHelper::OScrollWindowHelper( vcl::Window* pParent) : Window( pParent)
68 ,m_aHScrollBar( VclPtr<ScrollAdaptor>::Create(this, true) )
69 ,m_aVScrollBar( VclPtr<ScrollAdaptor>::Create(this, false) )
70 ,m_pTableView(nullptr)
72 StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
73 SetBackground(aSystemStyle.GetFaceColor());
75 // ScrollBars
76 GetHScrollBar().SetRange( Range(0, 1000) );
77 GetVScrollBar().SetRange( Range(0, 1000) );
79 GetHScrollBar().SetLineSize( LINE_SIZE );
80 GetVScrollBar().SetLineSize( LINE_SIZE );
82 GetHScrollBar().Show();
83 GetVScrollBar().Show();
85 // normally we should be SCROLL_PANE
86 SetAccessibleRole(AccessibleRole::SCROLL_PANE);
89 OScrollWindowHelper::~OScrollWindowHelper()
91 disposeOnce();
94 void OScrollWindowHelper::dispose()
96 m_aHScrollBar.disposeAndClear();
97 m_aVScrollBar.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, HorzScrollHdl) );
107 GetVScrollBar().SetScrollHdl( LINK(m_pTableView, OJoinTableView, VertScrollHdl) );
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 tools::Long nHScrollHeight = GetHScrollBar().GetSizePixel().Height();
123 tools::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 GetHScrollBar().SetPageSize( aTotalOutputSize.Width() );
136 GetHScrollBar().SetVisibleSize( aTotalOutputSize.Width() );
138 GetVScrollBar().SetPageSize( aTotalOutputSize.Height() );
139 GetVScrollBar().SetVisibleSize( aTotalOutputSize.Height() );
141 // adjust the ranges of the scrollbars if necessary
142 tools::Long lRange = GetHScrollBar().GetRange().Max() - GetHScrollBar().GetRange().Min();
143 if (m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() > lRange)
144 GetHScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().X() + aTotalOutputSize.Width() + GetHScrollBar().GetRange().Min());
146 lRange = GetVScrollBar().GetRange().Max() - GetVScrollBar().GetRange().Min();
147 if (m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() > lRange)
148 GetVScrollBar().SetRangeMax(m_pTableView->GetScrollOffset().Y() + aTotalOutputSize.Height() + GetVScrollBar().GetRange().Min());
150 m_pTableView->SetPosSizePixel(Point( 0, 0 ),Size( aTotalOutputSize.Width()-nVScrollWidth, aTotalOutputSize.Height()-nHScrollHeight ));
154 OJoinTableView::OJoinTableView( vcl::Window* pParent, OJoinDesignView* pView )
155 :Window( pParent,WB_BORDER )
156 ,DropTargetHelper(this)
157 ,m_aDragScrollIdle("dbaccess OJoinTableView m_aDragScrollIdle")
158 ,m_aDragOffset( Point(0,0) )
159 ,m_aScrollOffset( Point(0,0) )
160 ,m_pDragWin( nullptr )
161 ,m_pSizingWin( nullptr )
162 ,m_pSelectedConn( nullptr )
163 ,m_pLastFocusTabWin(nullptr)
164 ,m_pView( pView )
166 SetSizePixel( Size(1000, 1000) );
168 InitColors();
170 m_aDragScrollIdle.SetInvokeHandler(LINK(this, OJoinTableView, OnDragScrollTimer));
173 OJoinTableView::~OJoinTableView()
175 disposeOnce();
178 void OJoinTableView::dispose()
180 if( m_pAccessible )
182 m_pAccessible->clearTableView();
183 m_pAccessible = nullptr;
185 // delete lists
186 clearLayoutInformation();
187 m_pDragWin.clear();
188 m_pSizingWin.clear();
189 m_pSelectedConn.clear();
190 m_pLastFocusTabWin.clear();
191 m_pView.clear();
192 m_vTableConnection.clear();
193 vcl::Window::dispose();
196 IMPL_LINK(OJoinTableView, HorzScrollHdl, weld::Scrollbar&, rScrollbar, void)
198 // move all windows
199 ScrollPane(rScrollbar.adjustment_get_value() - m_aScrollOffset.X(), true, false);
202 IMPL_LINK(OJoinTableView, VertScrollHdl, weld::Scrollbar&, rScrollbar, void)
204 // move all windows
205 ScrollPane(rScrollbar.adjustment_get_value() - m_aScrollOffset.Y(), false, 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.setX( GetHScrollBar().GetThumbPos() );
220 m_aScrollOffset.setY( GetVScrollBar().GetThumbPos() );
222 VclPtr<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 for (auto const& elem : m_aTableMap)
232 OTableWindow* pCurrent = elem.second;
233 Point aPos(pCurrent->GetData()->GetPosition() - GetScrollOffset());
234 pCurrent->SetPosPixel(aPos);
238 sal_Int64 OJoinTableView::GetTabWinCount() const
240 return m_aTableMap.size();
243 bool OJoinTableView::RemoveConnection(VclPtr<OTableConnection>& rConn, bool _bDelete)
245 VclPtr<OTableConnection> xConn(rConn);
247 DeselectConn(xConn);
249 // to force a redraw
250 xConn->InvalidateConnection();
252 m_pView->getController().removeConnectionData(xConn->GetData());
254 m_vTableConnection.erase(std::find(m_vTableConnection.begin(), m_vTableConnection.end(), xConn));
256 modified();
257 if ( m_pAccessible )
258 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
259 Any(xConn->GetAccessible()),
260 Any());
261 if (_bDelete)
262 xConn->disposeOnce();
264 return true;
267 OTableWindow* OJoinTableView::GetTabWindow( const OUString& rName )
269 OTableWindowMap::const_iterator aIter = m_aTableMap.find(rName);
271 return aIter == m_aTableMap.end() ? nullptr : aIter->second;
274 TTableWindowData::value_type OJoinTableView::createTableWindowData(const OUString& _rComposedName
275 ,const OUString& _sTableName
276 ,const OUString& _rWinName)
278 TTableWindowData::value_type pData( CreateImpl(_rComposedName, _sTableName,_rWinName) );
279 OJoinDesignView* pParent = getDesignView();
282 if ( !pData->init(pParent->getController().getConnection(),allowQueries()) )
284 if ( pData->isValid() )
285 onNoColumns_throw();
286 else
287 pData.reset();
290 catch ( const SQLException& )
292 ::dbtools::showError( ::dbtools::SQLExceptionInfo( ::cppu::getCaughtException() ),
293 VCLUnoHelper::GetInterface(pParent), pParent->getController().getORB() );
295 catch( const WrappedTargetException& e )
297 SQLException aSql;
298 if ( e.TargetException >>= aSql )
299 ::dbtools::showError( ::dbtools::SQLExceptionInfo( aSql ), VCLUnoHelper::GetInterface(pParent), pParent->getController().getORB() );
301 catch( const Exception& )
303 DBG_UNHANDLED_EXCEPTION("dbaccess");
305 return pData;
308 std::shared_ptr<OTableWindowData> OJoinTableView::CreateImpl(const OUString& _rComposedName
309 ,const OUString& _sTableName
310 ,const OUString& _rWinName)
312 return std::make_shared<OTableWindowData>( nullptr,_rComposedName,_sTableName, _rWinName );
315 void OJoinTableView::AddTabWin(const OUString& _rComposedName, const OUString& rWinName, bool /*bNewTable*/)
317 OSL_ENSURE(!_rComposedName.isEmpty(),"There must be a table name supplied!");
319 TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName ));
321 // insert new window in window list
322 VclPtr<OTableWindow> pNewTabWin = createWindow( pNewTabWinData );
323 if ( pNewTabWin->Init() )
325 m_pView->getController().getTableWindowData().push_back( pNewTabWinData);
326 // when we already have a table with this name insert the full qualified one instead
327 if(m_aTableMap.contains(rWinName))
328 m_aTableMap[_rComposedName] = pNewTabWin;
329 else
330 m_aTableMap[rWinName] = pNewTabWin;
332 SetDefaultTabWinPosSize( pNewTabWin );
333 pNewTabWin->Show();
335 modified();
336 if ( m_pAccessible )
337 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
338 Any(),
339 Any(pNewTabWin->GetAccessible()));
341 else
343 pNewTabWin->clearListBox();
344 pNewTabWin.disposeAndClear();
348 void OJoinTableView::RemoveTabWin( OTableWindow* pTabWin )
350 // first delete all connections of this window to others
351 bool bRemove = true;
352 TTableWindowData::value_type pData = pTabWin->GetData();
353 sal_Int32 nCount = m_vTableConnection.size();
354 auto aIter = m_vTableConnection.rbegin();
355 while(aIter != m_vTableConnection.rend() && bRemove)
357 VclPtr<OTableConnection>& rTabConn = *aIter;
358 if (
359 (pData == rTabConn->GetData()->getReferencingTable()) ||
360 (pData == rTabConn->GetData()->getReferencedTable())
363 bRemove = RemoveConnection(rTabConn, true);
364 aIter = m_vTableConnection.rbegin();
366 else
367 ++aIter;
370 // then delete the window itself
371 if ( bRemove )
373 if ( m_pAccessible )
374 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
375 Any(pTabWin->GetAccessible()),Any()
378 pTabWin->Hide();
379 OJoinController& rController = m_pView->getController();
380 TTableWindowData::iterator aFind = std::find(rController.getTableWindowData().begin(), rController.getTableWindowData().end(), pData);
381 if(aFind != rController.getTableWindowData().end())
383 rController.getTableWindowData().erase(aFind);
384 rController.setModified(true);
387 if ( !m_aTableMap.erase( pTabWin->GetWinName() ) )
388 m_aTableMap.erase( pTabWin->GetComposedName() );
390 if (pTabWin == m_pLastFocusTabWin)
391 m_pLastFocusTabWin = nullptr;
393 pTabWin->clearListBox();
394 pTabWin->disposeOnce();
397 if ( static_cast<sal_Int32>(m_vTableConnection.size()) < (nCount-1) ) // if some connections could be removed
398 modified();
401 namespace
403 bool isScrollAllowed( OJoinTableView* _pView,tools::Long nDelta, bool bHoriz)
405 // adjust ScrollBar-Positions
406 ScrollAdaptor& rBar = bHoriz ? _pView->GetHScrollBar() : _pView->GetVScrollBar();
408 tools::Long nOldThumbPos = rBar.GetThumbPos();
409 tools::Long nNewThumbPos = nOldThumbPos + nDelta;
410 if( nNewThumbPos < 0 )
411 nNewThumbPos = 0;
412 else if( nNewThumbPos > rBar.GetRangeMax() )
413 nNewThumbPos = rBar.GetRangeMax();
415 if ( bHoriz )
417 if( nNewThumbPos == _pView->GetScrollOffset().X() )
418 return false;
420 else if ( nNewThumbPos == _pView->GetScrollOffset().Y() )
421 return false;
423 return true;
425 bool getMovementImpl(OJoinTableView* _pView,const Point& _rPoint,const Size& _rSize,tools::Long& _nScrollX,tools::Long& _nScrollY)
427 _nScrollY = _nScrollX = 0;
428 // data about the tab win
429 Point aUpperLeft = _rPoint;
430 // normalize with respect to visibility
431 aUpperLeft -= _pView->GetScrollOffset();
432 Point aLowerRight(aUpperLeft.X() + _rSize.Width(), aUpperLeft.Y() + _rSize.Height());
434 // data about ourself
435 Size aSize = _pView->getRealOutputSize(); //GetOutputSizePixel();
437 bool bVisible = true;
438 bool bFitsHor = (aUpperLeft.X() >= 0) && (aLowerRight.X() <= aSize.Width());
439 bool bFitsVert= (aUpperLeft.Y() >= 0) && (aLowerRight.Y() <= aSize.Height());
440 if (!bFitsHor || !bFitsVert)
442 if (!bFitsHor)
444 // ensure the visibility of the right border
445 if ( aLowerRight.X() > aSize.Width() )
446 _nScrollX = aLowerRight.X() - aSize.Width() + TABWIN_SPACING_X;
448 // ensure the visibility of the left border (higher priority)
449 if ( aUpperLeft.X() < 0 )
450 _nScrollX = aUpperLeft.X() - TABWIN_SPACING_X;
453 if (!bFitsVert)
455 // lower border
456 if ( aLowerRight.Y() > aSize.Height() )
457 _nScrollY = aLowerRight.Y() - aSize.Height() + TABWIN_SPACING_Y;
458 // upper border
459 if ( aUpperLeft.Y() < 0 )
460 _nScrollY = aUpperLeft.Y() - TABWIN_SPACING_Y;
463 if ( _nScrollX ) // aSize.Width() > _rSize.Width() &&
464 bVisible = isScrollAllowed(_pView,_nScrollX, true);
466 if ( _nScrollY ) // aSize.Height() > _rSize.Height() &&
467 bVisible = bVisible && isScrollAllowed(_pView,_nScrollY, false);
469 if ( bVisible )
471 sal_Int32 nHRangeMax = _pView->GetHScrollBar().GetRangeMax();
472 sal_Int32 nVRangeMax = _pView->GetVScrollBar().GetRangeMax();
474 if ( aSize.Width() + _pView->GetHScrollBar().GetThumbPos() + _nScrollX > nHRangeMax )
475 bVisible = false;
476 if ( bVisible && aSize.Height() + _pView->GetVScrollBar().GetThumbPos() + _nScrollY > nVRangeMax )
477 bVisible = false;
481 return bVisible;
483 } // end of ano namespace
485 bool OJoinTableView::isMovementAllowed(const Point& _rPoint,const Size& _rSize)
487 tools::Long nX,nY;
488 return getMovementImpl(this,_rPoint,_rSize,nX,nY);
491 void OJoinTableView::EnsureVisible(const OTableWindow* _pWin)
493 // data about the tab win
494 const TTableWindowData::value_type& pData = _pWin->GetData();
495 EnsureVisible( pData->GetPosition() , pData->GetSize());
496 Invalidate(InvalidateFlags::NoChildren);
499 void OJoinTableView::EnsureVisible(const Point& _rPoint,const Size& _rSize)
501 tools::Long nScrollX,nScrollY;
503 if ( getMovementImpl(this,_rPoint,_rSize,nScrollX,nScrollY) )
505 bool bVisible = true;
506 if (nScrollX)
507 bVisible = ScrollPane(nScrollX, true, true);
509 if (nScrollY && bVisible)
510 ScrollPane(nScrollY, false, true);
514 void OJoinTableView::SetDefaultTabWinPosSize( OTableWindow* pTabWin )
516 // determine position:
517 // the window is divided into lines with height TABWIN_SPACING_Y+TABWIN_HEIGHT_STD.
518 // Then for each line is checked, if there is space for another window.
519 // If there is no space, the next line is checked.
520 Size aOutSize = GetSizePixel();
521 Point aNewPos( 0,0 );
522 sal_uInt16 nRow = 0;
523 bool bEnd = false;
524 while( !bEnd )
526 // Set new position to start of line
527 aNewPos.setX( TABWIN_SPACING_X );
528 aNewPos.setY( (nRow+1) * TABWIN_SPACING_Y );
530 // determine rectangle for the corresponding line
531 tools::Rectangle aRowRect( Point(0,0), aOutSize );
532 aRowRect.SetTop( nRow * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ) );
533 aRowRect.SetBottom( (nRow+1) * ( TABWIN_SPACING_Y + TABWIN_HEIGHT_STD ) );
535 // check occupied areas of this line
536 for (auto const& elem : m_aTableMap)
538 OTableWindow* pOtherTabWin = elem.second;
539 tools::Rectangle aOtherTabWinRect( pOtherTabWin->GetPosPixel(), pOtherTabWin->GetSizePixel() );
542 ( (aOtherTabWinRect.Top()>aRowRect.Top()) && (aOtherTabWinRect.Top()<aRowRect.Bottom()) ) ||
543 ( (aOtherTabWinRect.Bottom()>aRowRect.Top()) && (aOtherTabWinRect.Bottom()<aRowRect.Bottom()) )
546 // TabWin is in the line
547 if( aOtherTabWinRect.Right()>aNewPos.X() )
548 aNewPos.setX( aOtherTabWinRect.Right() + TABWIN_SPACING_X );
552 // Is there space left in this line?
553 if( (aNewPos.X()+TABWIN_WIDTH_STD)<aRowRect.Right() )
555 aNewPos.setY( aRowRect.Top() + TABWIN_SPACING_Y );
556 bEnd = true;
558 else
560 if( (aRowRect.Bottom()+aRowRect.GetHeight()) > aOutSize.Height() )
562 // insert it in the first row
563 sal_Int32 nCount = m_aTableMap.size() % (nRow+1);
564 ++nCount;
565 aNewPos.setY( nCount * TABWIN_SPACING_Y + (nCount-1)*CalcZoom(TABWIN_HEIGHT_STD) );
566 bEnd = true;
568 else
569 nRow++;
574 // determine size
575 Size aNewSize( CalcZoom(TABWIN_WIDTH_STD), CalcZoom(TABWIN_HEIGHT_STD) );
577 // check if the new position in inside the scrollbars ranges
578 Point aBottom(aNewPos);
579 aBottom.AdjustX(aNewSize.Width() );
580 aBottom.AdjustY(aNewSize.Height() );
582 if(!GetHScrollBar().GetRange().Contains(aBottom.X()))
583 GetHScrollBar().SetRange( Range(0, aBottom.X()) );
584 if(!GetVScrollBar().GetRange().Contains(aBottom.Y()))
585 GetVScrollBar().SetRange( Range(0, aBottom.Y()) );
587 pTabWin->SetPosSizePixel( aNewPos, aNewSize );
590 void OJoinTableView::DataChanged(const DataChangedEvent& rDCEvt)
592 if (rDCEvt.GetType() == DataChangedEventType::SETTINGS)
594 // consider the worst case: the colors changed, so adjust me
595 InitColors();
596 Invalidate(InvalidateFlags::NoChildren);
597 // due to the Invalidate, the connections are redrawn, so that they are also pictured in the new colors
601 void OJoinTableView::InitColors()
603 // the colors for the illustration should be the system colors
604 StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
605 SetBackground(Wallpaper(aSystemStyle.GetDialogColor()));
608 void OJoinTableView::BeginChildMove( OTableWindow* pTabWin, const Point& rMousePos )
611 if (m_pView->getController().isReadOnly())
612 return;
614 m_pDragWin = pTabWin;
615 SetPointer(PointerStyle::Move);
616 Point aMousePos = ScreenToOutputPixel( rMousePos );
617 m_aDragOffset = aMousePos - pTabWin->GetPosPixel();
618 m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
619 StartTracking();
622 void OJoinTableView::NotifyTitleClicked( OTableWindow* pTabWin, const Point& rMousePos )
624 DeselectConn(GetSelectedConn());
625 BeginChildMove(pTabWin, rMousePos);
628 void OJoinTableView::BeginChildSizing( OTableWindow* pTabWin, PointerStyle nPointer )
631 if (m_pView->getController().isReadOnly())
632 return;
634 SetPointer( nPointer );
635 m_pSizingWin = pTabWin;
636 StartTracking();
639 bool OJoinTableView::ScrollPane( tools::Long nDelta, bool bHoriz, bool bPaintScrollBars )
641 bool bRet = true;
643 // adjust ScrollBar-Positions
644 if( bPaintScrollBars )
646 if( bHoriz )
648 tools::Long nOldThumbPos = GetHScrollBar().GetThumbPos();
649 tools::Long nNewThumbPos = nOldThumbPos + nDelta;
650 if( nNewThumbPos < 0 )
652 nNewThumbPos = 0;
653 bRet = false;
655 if( nNewThumbPos > GetHScrollBar().GetRange().Max() )
657 nNewThumbPos = GetHScrollBar().GetRange().Max();
658 bRet = false;
660 GetHScrollBar().SetThumbPos( nNewThumbPos );
661 nDelta = GetHScrollBar().GetThumbPos() - nOldThumbPos;
663 else
665 tools::Long nOldThumbPos = GetVScrollBar().GetThumbPos();
666 tools::Long nNewThumbPos = nOldThumbPos+nDelta;
667 if( nNewThumbPos < 0 )
669 nNewThumbPos = 0;
670 bRet = false;
672 if( nNewThumbPos > GetVScrollBar().GetRange().Max() )
674 nNewThumbPos = GetVScrollBar().GetRange().Max();
675 bRet = false;
677 GetVScrollBar().SetThumbPos( nNewThumbPos );
678 nDelta = GetVScrollBar().GetThumbPos() - nOldThumbPos;
682 // If ScrollOffset hitting borders, no redrawing.
683 if( (GetHScrollBar().GetThumbPos()==m_aScrollOffset.X()) &&
684 (GetVScrollBar().GetThumbPos()==m_aScrollOffset.Y()) )
685 return false;
687 // set ScrollOffset anew
688 if (bHoriz)
689 m_aScrollOffset.setX( GetHScrollBar().GetThumbPos() );
690 else
691 m_aScrollOffset.setY( GetVScrollBar().GetThumbPos() );
693 // move all windows
694 OTableWindow* pTabWin;
695 Point aPos;
697 for (auto const& elem : m_aTableMap)
699 pTabWin = elem.second;
700 aPos = pTabWin->GetPosPixel();
702 if( bHoriz )
703 aPos.AdjustX( -nDelta );
704 else aPos.AdjustY( -nDelta );
706 pTabWin->SetPosPixel( aPos );
709 Invalidate(); // InvalidateFlags::NoChildren
711 return bRet;
714 void OJoinTableView::Tracking( const TrackingEvent& rTEvt )
716 HideTracking();
718 if (rTEvt.IsTrackingEnded())
720 if( m_pDragWin )
722 if (m_aDragScrollIdle.IsActive())
723 m_aDragScrollIdle.Stop();
725 // adjust position of child after moving
726 // windows are not allowed to leave display range
727 Point aDragWinPos = rTEvt.GetMouseEvent().GetPosPixel() - m_aDragOffset;
728 Size aDragWinSize = m_pDragWin->GetSizePixel();
729 if( aDragWinPos.X() < 0 )
730 aDragWinPos.setX( 0 );
731 if( aDragWinPos.Y() < 0 )
732 aDragWinPos.setY( 0 );
733 if( (aDragWinPos.X() + aDragWinSize.Width()) > m_aOutputSize.Width() )
734 aDragWinPos.setX( m_aOutputSize.Width() - aDragWinSize.Width() - 1 );
735 if( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() )
736 aDragWinPos.setY( m_aOutputSize.Height() - aDragWinSize.Height() - 1 );
737 if( aDragWinPos.X() < 0 )
738 aDragWinPos.setX( 0 );
739 if( aDragWinPos.Y() < 0 )
740 aDragWinPos.setY( 0 );
741 // TODO : don't position window anew, if it is leaving range, but just expand the range
743 // position window
744 EndTracking();
745 m_pDragWin->SetZOrder(nullptr, ZOrderFlags::First);
746 // check, if I really moved
747 // (this prevents setting the modified-Flag, when there actually was no change0
748 TTableWindowData::value_type pData = m_pDragWin->GetData();
749 if ( ! (pData && pData->HasPosition() && (pData->GetPosition() == aDragWinPos)))
751 // old logic coordinates
752 Point ptOldPos = m_pDragWin->GetPosPixel() + Point(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
753 // new positioning
754 m_pDragWin->SetPosPixel(aDragWinPos);
755 TabWinMoved(m_pDragWin, ptOldPos);
757 m_pDragWin->GrabFocus();
759 m_pDragWin = nullptr;
760 SetPointer(PointerStyle::Arrow);
762 // else we handle the resizing
763 else if( m_pSizingWin )
765 SetPointer( PointerStyle::Arrow );
766 EndTracking();
768 // old physical coordinates
770 Size szOld = m_pSizingWin->GetSizePixel();
771 Point ptOld = m_pSizingWin->GetPosPixel();
772 Size aNewSize(CalcZoom(m_aSizingRect.GetSize().Width()),CalcZoom(m_aSizingRect.GetSize().Height()));
773 m_pSizingWin->SetPosSizePixel( m_aSizingRect.TopLeft(), aNewSize );
774 TabWinSized(m_pSizingWin, ptOld, szOld);
776 m_pSizingWin->Invalidate( m_aSizingRect );
777 m_pSizingWin = nullptr;
780 else if (rTEvt.IsTrackingCanceled())
782 if (m_aDragScrollIdle.IsActive())
783 m_aDragScrollIdle.Stop();
784 EndTracking();
786 else
788 if( m_pDragWin )
790 m_ptPrevDraggingPos = rTEvt.GetMouseEvent().GetPosPixel();
791 // scroll at window borders
792 ScrollWhileDragging();
795 if( m_pSizingWin )
797 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
798 m_aSizingRect = m_pSizingWin->getSizingRect(aMousePos,m_aOutputSize);
799 PaintImmediately();
800 ShowTracking( m_aSizingRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
805 void OJoinTableView::ConnDoubleClicked(VclPtr<OTableConnection>& /*rConnection*/)
809 void OJoinTableView::MouseButtonDown( const MouseEvent& rEvt )
811 GrabFocus();
812 Window::MouseButtonDown(rEvt);
815 void OJoinTableView::MouseButtonUp( const MouseEvent& rEvt )
817 Window::MouseButtonUp(rEvt);
818 // Has a connection been selected?
819 if( m_vTableConnection.empty() )
820 return;
822 DeselectConn(GetSelectedConn());
824 for (auto & elem : m_vTableConnection)
826 if( elem->CheckHit(rEvt.GetPosPixel()) )
828 SelectConn(elem);
830 // Double-click
831 if( rEvt.GetClicks() == 2 )
832 ConnDoubleClicked(elem);
834 break;
839 void OJoinTableView::KeyInput( const KeyEvent& rEvt )
841 sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
842 bool bShift = rEvt.GetKeyCode().IsShift();
843 bool bCtrl = rEvt.GetKeyCode().IsMod1();
845 if( !bCtrl && !bShift && (nCode==KEY_DELETE) )
847 if (GetSelectedConn())
848 RemoveConnection(GetSelectedConn(), true);
850 else
851 Window::KeyInput( rEvt );
854 void OJoinTableView::DeselectConn(OTableConnection* pConn)
856 if (!pConn || !pConn->IsSelected())
857 return;
859 // deselect the corresponding entries in the ListBox of the table window
860 OTableWindow* pWin = pConn->GetSourceWin();
861 if (pWin && pWin->GetListBox())
862 pWin->GetListBox()->get_widget().unselect_all();
864 pWin = pConn->GetDestWin();
865 if (pWin && pWin->GetListBox())
866 pWin->GetListBox()->get_widget().unselect_all();
868 pConn->Deselect();
869 m_pSelectedConn = nullptr;
872 void OJoinTableView::SelectConn(OTableConnection* pConn)
874 DeselectConn(GetSelectedConn());
876 pConn->Select();
877 m_pSelectedConn = pConn;
878 GrabFocus(); // has to be called here because a table window may still be focused
880 // select the concerned entries in the windows
881 OTableWindow* pConnSource = pConn->GetSourceWin();
882 OTableWindow* pConnDest = pConn->GetDestWin();
883 if (!(pConnSource && pConnDest))
884 return;
886 OTableWindowListBox* pSourceBox = pConnSource->GetListBox().get();
887 OTableWindowListBox* pDestBox = pConnDest->GetListBox().get();
888 if (!(pSourceBox && pDestBox))
889 return;
891 pSourceBox->get_widget().unselect_all();
892 pDestBox->get_widget().unselect_all();
894 bool bScrolled = false;
896 const std::vector<std::unique_ptr<OConnectionLine>>& rLines = pConn->GetConnLineList();
897 auto aIter = rLines.rbegin();
898 for(;aIter != rLines.rend();++aIter)
900 if ((*aIter)->IsValid())
902 int nSourceEntry = pSourceBox->GetEntryFromText((*aIter)->GetData()->GetSourceFieldName());
903 if (nSourceEntry != -1)
905 pSourceBox->get_widget().select(nSourceEntry);
906 pSourceBox->get_widget().scroll_to_row(nSourceEntry);
907 bScrolled = true;
910 int nDestEntry = pDestBox->GetEntryFromText((*aIter)->GetData()->GetDestFieldName());
911 if (nDestEntry != -1)
913 pDestBox->get_widget().select(nDestEntry);
914 pDestBox->get_widget().scroll_to_row(nDestEntry);
915 bScrolled = true;
920 if (bScrolled)
922 // scrolling was done -> redraw
923 Invalidate(InvalidateFlags::NoChildren);
927 void OJoinTableView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
929 DrawConnections(rRenderContext, rRect);
932 void OJoinTableView::InvalidateConnections()
934 // draw Joins
935 for (auto & conn : m_vTableConnection)
936 conn->InvalidateConnection();
939 void OJoinTableView::DrawConnections(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
941 // draw Joins
942 for(const auto& connection : m_vTableConnection)
943 connection->Draw(rRenderContext, rRect);
944 // finally redraw the selected one above all others
945 if (GetSelectedConn())
946 GetSelectedConn()->Draw(rRenderContext, rRect);
949 std::vector<VclPtr<OTableConnection> >::const_iterator OJoinTableView::getTableConnections(const OTableWindow* _pFromWin) const
951 return std::find_if( m_vTableConnection.begin(),
952 m_vTableConnection.end(),
953 [_pFromWin](OTableConnection * p) { return p->isTableConnection(_pFromWin); });
956 sal_Int32 OJoinTableView::getConnectionCount(const OTableWindow* _pFromWin) const
958 return std::count_if( m_vTableConnection.begin(),
959 m_vTableConnection.end(),
960 [_pFromWin](OTableConnection * p) { return p->isTableConnection(_pFromWin); });
963 bool OJoinTableView::ExistsAConn(const OTableWindow* pFrom) const
965 return getTableConnections(pFrom) != m_vTableConnection.end();
968 void OJoinTableView::ClearAll()
970 SetUpdateMode(false);
972 HideTabWins();
974 // and the same with the Connections
975 for (auto & elem : m_vTableConnection)
977 RemoveConnection(elem, true);
979 m_vTableConnection.clear();
981 m_pLastFocusTabWin = nullptr;
982 m_pSelectedConn = nullptr;
984 // scroll to the upper left
985 ScrollPane(-GetScrollOffset().X(), true, true);
986 ScrollPane(-GetScrollOffset().Y(), false, true);
987 Invalidate();
990 void OJoinTableView::ScrollWhileDragging()
992 OSL_ENSURE(m_pDragWin != nullptr, "OJoinTableView::ScrollWhileDragging must not be called when a window is being dragged !");
994 // kill the timer
995 if (m_aDragScrollIdle.IsActive())
996 m_aDragScrollIdle.Stop();
998 Point aDragWinPos = m_ptPrevDraggingPos - m_aDragOffset;
999 Size aDragWinSize = m_pDragWin->GetSizePixel();
1000 Point aLowerRight(aDragWinPos.X() + aDragWinSize.Width(), aDragWinPos.Y() + aDragWinSize.Height());
1002 if (aDragWinPos == m_pDragWin->GetPosPixel())
1003 return;
1005 // avoid illustration errors (when scrolling with active TrackingRect)
1006 HideTracking();
1008 bool bScrolling = false;
1009 bool bNeedScrollTimer = false;
1011 // scroll at window borders
1012 // TODO : only catch, if window would disappear completely (don't, if there is still a pixel visible)
1013 if( aDragWinPos.X() < 5 )
1015 bScrolling = ScrollPane( -LINE_SIZE, true, true );
1016 if( !bScrolling && (aDragWinPos.X()<0) )
1017 aDragWinPos.setX( 0 );
1019 // do I need further (timer controlled) scrolling ?
1020 bNeedScrollTimer = bScrolling && (aDragWinPos.X() < 5);
1023 if( aLowerRight.X() > m_aOutputSize.Width() - 5 )
1025 bScrolling = ScrollPane( LINE_SIZE, true, true ) ;
1026 if( !bScrolling && ( aLowerRight.X() > m_aOutputSize.Width() ) )
1027 aDragWinPos.setX( m_aOutputSize.Width() - aDragWinSize.Width() );
1029 // do I need further (timer controlled) scrolling ?
1030 bNeedScrollTimer = bScrolling && (aLowerRight.X() > m_aOutputSize.Width() - 5);
1033 if( aDragWinPos.Y() < 5 )
1035 bScrolling = ScrollPane( -LINE_SIZE, false, true );
1036 if( !bScrolling && (aDragWinPos.Y()<0) )
1037 aDragWinPos.setY( 0 );
1039 bNeedScrollTimer = bScrolling && (aDragWinPos.Y() < 5);
1042 if( aLowerRight.Y() > m_aOutputSize.Height() - 5 )
1044 bScrolling = ScrollPane( LINE_SIZE, false, true );
1045 if( !bScrolling && ( (aDragWinPos.Y() + aDragWinSize.Height()) > m_aOutputSize.Height() ) )
1046 aDragWinPos.setY( m_aOutputSize.Height() - aDragWinSize.Height() );
1048 bNeedScrollTimer = bScrolling && (aLowerRight.Y() > m_aOutputSize.Height() - 5);
1051 // resetting timer, if still necessary
1052 if (bNeedScrollTimer)
1054 m_aDragScrollIdle.SetPriority( TaskPriority::HIGH_IDLE );
1055 m_aDragScrollIdle.Start();
1058 // redraw DraggingRect
1059 m_aDragRect = tools::Rectangle(m_ptPrevDraggingPos - m_aDragOffset, m_pDragWin->GetSizePixel());
1060 PaintImmediately();
1061 ShowTracking( m_aDragRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
1064 IMPL_LINK_NOARG(OJoinTableView, OnDragScrollTimer, Timer *, void)
1066 ScrollWhileDragging();
1069 void OJoinTableView::invalidateAndModify(std::unique_ptr<SfxUndoAction> _pAction)
1071 Invalidate(InvalidateFlags::NoChildren);
1072 m_pView->getController().addUndoActionAndInvalidate(std::move(_pAction));
1075 void OJoinTableView::TabWinMoved(OTableWindow* ptWhich, const Point& ptOldPosition)
1077 Point ptThumbPos(GetHScrollBar().GetThumbPos(), GetVScrollBar().GetThumbPos());
1078 ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel() + ptThumbPos);
1080 invalidateAndModify(std::make_unique<OJoinMoveTabWinUndoAct>(this, ptOldPosition, ptWhich));
1083 void OJoinTableView::TabWinSized(OTableWindow* ptWhich, const Point& ptOldPosition, const Size& szOldSize)
1085 ptWhich->GetData()->SetSize(ptWhich->GetSizePixel());
1086 ptWhich->GetData()->SetPosition(ptWhich->GetPosPixel());
1088 invalidateAndModify(std::make_unique<OJoinSizeTabWinUndoAct>(this, ptOldPosition, szOldSize, ptWhich));
1091 bool OJoinTableView::IsAddAllowed()
1094 // not, if Db readonly
1095 if (m_pView->getController().isReadOnly())
1096 return false;
1100 Reference< XConnection> xConnection = m_pView->getController().getConnection();
1101 if(!xConnection.is())
1102 return false;
1103 // not, if too many tables already
1104 Reference < XDatabaseMetaData > xMetaData( xConnection->getMetaData() );
1106 sal_Int32 nMax = xMetaData.is() ? xMetaData->getMaxTablesInSelect() : 0;
1107 if (nMax && nMax <= static_cast<sal_Int32>(m_aTableMap.size()))
1108 return false;
1110 catch(SQLException&)
1112 return false;
1115 return true;
1118 void OJoinTableView::executePopup(const Point& rPos, VclPtr<OTableConnection>& rSelConnection)
1120 ::tools::Rectangle aRect(rPos, Size(1, 1));
1121 weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
1122 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, u"dbaccess/ui/joinviewmenu.ui"_ustr));
1123 std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu(u"menu"_ustr));
1124 OUString sIdent = xContextMenu->popup_at_rect(pPopupParent, aRect);
1125 if (sIdent == "delete")
1126 RemoveConnection(rSelConnection, true);
1127 else if (sIdent == "edit")
1128 ConnDoubleClicked(rSelConnection); // is the same as double clicked
1131 void OJoinTableView::Command(const CommandEvent& rEvt)
1134 bool bHandled = false;
1136 switch (rEvt.GetCommand())
1138 case CommandEventId::ContextMenu:
1140 if( m_vTableConnection.empty() )
1141 return;
1143 VclPtr<OTableConnection>& rSelConnection = GetSelectedConn();
1144 // when it wasn't a mouse event use the selected connection
1145 if (!rEvt.IsMouseEvent())
1147 if (rSelConnection)
1149 const std::vector<std::unique_ptr<OConnectionLine>>& rLines = rSelConnection->GetConnLineList();
1150 auto aIter = std::find_if(rLines.begin(), rLines.end(),std::mem_fn(&OConnectionLine::IsValid));
1151 if( aIter != rLines.end() )
1152 executePopup((*aIter)->getMidPoint(), rSelConnection);
1155 else
1157 DeselectConn(rSelConnection);
1159 const Point& aMousePos = rEvt.GetMousePosPixel();
1160 for (auto & elem : m_vTableConnection)
1162 if( elem->CheckHit(aMousePos) )
1164 SelectConn(elem);
1165 if(!getDesignView()->getController().isReadOnly() && getDesignView()->getController().isConnected())
1166 executePopup(rEvt.GetMousePosPixel(),elem);
1167 break;
1171 bHandled = true;
1173 break;
1174 default: break;
1176 if (!bHandled)
1177 Window::Command(rEvt);
1180 OTableConnection* OJoinTableView::GetTabConn(const OTableWindow* pLhs,const OTableWindow* pRhs,bool _bSuppressCrossOrNaturalJoin) const
1182 OTableConnection* pConn = nullptr;
1183 OSL_ENSURE(pRhs || pLhs, "OJoinTableView::GetTabConn : invalid args !");
1184 // only one NULL-arg allowed
1186 if ((!pLhs || pLhs->ExistsAConn()) && (!pRhs || pRhs->ExistsAConn()))
1188 for(VclPtr<OTableConnection> const & pData : m_vTableConnection)
1190 if ( ( (pData->GetSourceWin() == pLhs)
1191 && ( (pData->GetDestWin() == pRhs)
1192 || (nullptr == pRhs)
1195 || ( (pData->GetSourceWin() == pRhs)
1196 && ( (pData->GetDestWin() == pLhs)
1197 || (nullptr == pLhs)
1202 if ( _bSuppressCrossOrNaturalJoin )
1204 if ( suppressCrossNaturalJoin(pData->GetData()) )
1205 continue;
1207 pConn = pData;
1208 break;
1212 return pConn;
1215 bool OJoinTableView::PreNotify(NotifyEvent& rNEvt)
1217 bool bHandled = false;
1218 switch (rNEvt.GetType())
1220 case NotifyEventType::COMMAND:
1222 const CommandEvent* pCommand = rNEvt.GetCommandEvent();
1223 if (pCommand->GetCommand() == CommandEventId::Wheel)
1225 const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
1226 if (pData->GetMode() == CommandWheelMode::SCROLL)
1228 if (pData->GetDelta() > 0)
1229 ScrollPane(-10 * pData->GetScrollLines(), pData->IsHorz(), true);
1230 else
1231 ScrollPane(10 * pData->GetScrollLines(), pData->IsHorz(), true);
1232 bHandled = true;
1236 break;
1237 case NotifyEventType::KEYINPUT:
1239 if (m_aTableMap.empty())
1240 // no tab wins -> no conns -> no traveling
1241 break;
1243 const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
1244 if (!pKeyEvent->GetKeyCode().IsMod1())
1246 switch (pKeyEvent->GetKeyCode().GetCode())
1248 case KEY_TAB:
1250 if (!HasChildPathFocus())
1251 break;
1253 bool bForward = !pKeyEvent->GetKeyCode().IsShift();
1254 // is there an active tab win ?
1255 OTableWindowMap::const_iterator aIter = std::find_if(m_aTableMap.begin(), m_aTableMap.end(),
1256 [](const OTableWindowMap::value_type& rEntry) { return rEntry.second && rEntry.second->HasChildPathFocus(); });
1258 OTableWindow* pNextWin = nullptr;
1259 OTableConnection* pNextConn = nullptr;
1261 if (aIter != m_aTableMap.end())
1262 { // there is a currently active tab win
1263 // check if there is an "overflow" and we should select a conn instead of a win
1264 if (!m_vTableConnection.empty())
1266 if ((aIter->second == m_aTableMap.rbegin()->second) && bForward)
1267 // the last win is active and we're travelling forward -> select the first conn
1268 pNextConn = m_vTableConnection.begin()->get();
1269 if ((aIter == m_aTableMap.begin()) && !bForward)
1270 // the first win is active and we're traveling backward -> select the last conn
1271 pNextConn = m_vTableConnection.rbegin()->get();
1274 if (!pNextConn)
1276 // no conn for any reason -> select the next or previous tab win
1277 if(bForward)
1279 if ( aIter->second == m_aTableMap.rbegin()->second )
1280 pNextWin = m_aTableMap.begin()->second;
1281 else
1283 ++aIter;
1284 pNextWin = aIter->second;
1287 else
1289 if (aIter == m_aTableMap.begin())
1290 pNextWin = m_aTableMap.rbegin()->second;
1291 else
1293 --aIter;
1294 pNextWin = aIter->second;
1299 else
1300 { // no active tab win -> travel the connections
1301 // find the currently selected conn within the conn list
1302 sal_Int32 i(0);
1303 for (auto const& elem : m_vTableConnection)
1305 if ( elem.get() == GetSelectedConn() )
1306 break;
1307 ++i;
1309 if (i == sal_Int32(m_vTableConnection.size() - 1) && bForward)
1310 // the last conn is active and we're travelling forward -> select the first win
1311 pNextWin = m_aTableMap.begin()->second;
1312 if ((i == 0) && !bForward && !m_aTableMap.empty())
1313 // the first conn is active and we're travelling backward -> select the last win
1314 pNextWin = m_aTableMap.rbegin()->second;
1316 if (pNextWin)
1317 DeselectConn(GetSelectedConn());
1318 else
1319 // no win for any reason -> select the next or previous conn
1320 if (i < static_cast<sal_Int32>(m_vTableConnection.size()))
1321 // there is a currently active conn
1322 pNextConn = m_vTableConnection[(i + (bForward ? 1 : m_vTableConnection.size() - 1)) % m_vTableConnection.size()].get();
1323 else
1324 { // no tab win selected, no conn selected
1325 if (!m_vTableConnection.empty())
1326 pNextConn = m_vTableConnection[bForward ? 0 : m_vTableConnection.size() - 1].get();
1327 else if (!m_aTableMap.empty())
1329 if(bForward)
1330 pNextWin = m_aTableMap.begin()->second;
1331 else
1332 pNextWin = m_aTableMap.rbegin()->second;
1337 // now select the object
1338 if (pNextWin)
1340 if (pNextWin->GetListBox())
1341 pNextWin->GetListBox()->GrabFocus();
1342 else
1343 pNextWin->GrabFocus();
1344 EnsureVisible(pNextWin);
1346 else if (pNextConn)
1348 GrabFocus();
1349 // necessary : a conn may be selected even if a tab win has the focus, in this case
1350 // the next travel would select the same conn again if we would not reset the focus ...
1351 SelectConn(pNextConn);
1354 break;
1355 case KEY_RETURN:
1357 if (!pKeyEvent->GetKeyCode().IsShift() && GetSelectedConn() && HasFocus())
1358 ConnDoubleClicked(GetSelectedConn());
1359 break;
1364 break;
1365 case NotifyEventType::GETFOCUS:
1367 if (m_aTableMap.empty())
1368 // no tab wins -> no conns -> no focus change
1369 break;
1370 vcl::Window* pSource = rNEvt.GetWindow();
1371 if (pSource)
1373 vcl::Window* pSearchFor = nullptr;
1374 if (pSource->GetParent() == this)
1375 // it may be one of the tab wins
1376 pSearchFor = pSource;
1377 else if (pSource->GetParent() && (pSource->GetParent()->GetParent() == this))
1378 // it may be one of th list boxes of one of the tab wins
1379 pSearchFor = pSource->GetParent();
1381 if (pSearchFor)
1383 for (auto const& elem : m_aTableMap)
1385 if (elem.second == pSearchFor)
1387 m_pLastFocusTabWin = elem.second;
1388 break;
1394 break;
1395 default:
1396 break;
1399 if (!bHandled)
1400 return Window::PreNotify(rNEvt);
1401 return true;
1404 void OJoinTableView::GrabTabWinFocus()
1406 if (m_pLastFocusTabWin && m_pLastFocusTabWin->IsVisible())
1408 if (m_pLastFocusTabWin->GetListBox())
1409 m_pLastFocusTabWin->GetListBox()->GrabFocus();
1410 else
1411 m_pLastFocusTabWin->GrabFocus();
1413 else if (!m_aTableMap.empty() && m_aTableMap.begin()->second && m_aTableMap.begin()->second->IsVisible())
1415 VclPtr<OTableWindow> pFirstWin = m_aTableMap.begin()->second;
1416 if (pFirstWin->GetListBox())
1417 pFirstWin->GetListBox()->GrabFocus();
1418 else
1419 pFirstWin->GrabFocus();
1423 void OJoinTableView::StateChanged( StateChangedType nType )
1425 Window::StateChanged( nType );
1427 // FIXME RenderContext
1428 if ( nType != StateChangedType::Zoom )
1429 return;
1431 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1433 vcl::Font aFont = rStyleSettings.GetGroupFont();
1434 if ( IsControlFont() )
1435 aFont.Merge( GetControlFont() );
1436 SetZoomedPointFont(*GetOutDev(), aFont);
1438 for (auto const& elem : m_aTableMap)
1440 elem.second->SetZoom(GetZoom());
1441 Size aSize(CalcZoom(elem.second->GetSizePixel().Width()),CalcZoom(elem.second->GetSizePixel().Height()));
1442 elem.second->SetSizePixel(aSize);
1444 Resize();
1447 void OJoinTableView::HideTabWins()
1449 SetUpdateMode(false);
1451 OTableWindowMap& rTabWins = GetTabWinMap();
1453 // working on a copy because the real list will be cleared in inner calls
1454 OTableWindowMap aCopy(rTabWins);
1455 for (auto const& elem : aCopy)
1456 RemoveTabWin(elem.second);
1458 m_pView->getController().setModified(true);
1460 SetUpdateMode(true);
1464 sal_Int8 OJoinTableView::AcceptDrop( const AcceptDropEvent& /*_rEvt*/ )
1466 return DND_ACTION_NONE;
1469 sal_Int8 OJoinTableView::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ )
1471 return DND_ACTION_NONE;
1474 void OJoinTableView::dragFinished( )
1478 void OJoinTableView::clearLayoutInformation()
1480 m_pLastFocusTabWin = nullptr;
1481 m_pSelectedConn = nullptr;
1482 // delete lists
1483 for (auto & elem : m_aTableMap)
1485 if ( elem.second )
1486 elem.second->clearListBox();
1487 elem.second.disposeAndClear();
1490 m_aTableMap.clear();
1492 for (auto & elem : m_vTableConnection)
1493 elem.disposeAndClear();
1495 m_vTableConnection.clear();
1498 void OJoinTableView::lookForUiActivities()
1502 void OJoinTableView::LoseFocus()
1504 DeselectConn(GetSelectedConn());
1505 Window::LoseFocus();
1508 void OJoinTableView::GetFocus()
1510 Window::GetFocus();
1511 if ( !m_aTableMap.empty() && !GetSelectedConn() )
1512 GrabTabWinFocus();
1515 Reference< XAccessible > OJoinTableView::CreateAccessible()
1517 m_pAccessible = new OJoinDesignViewAccess(this);
1518 return m_pAccessible;
1521 void OJoinTableView::modified()
1523 OJoinController& rController = m_pView->getController();
1524 rController.setModified( true );
1525 rController.InvalidateFeature(ID_BROWSER_ADDTABLE);
1526 rController.InvalidateFeature(SID_RELATION_ADD_RELATION);
1529 void OJoinTableView::addConnection(OTableConnection* _pConnection,bool _bAddData)
1531 if ( _bAddData )
1533 #if OSL_DEBUG_LEVEL > 0
1534 TTableConnectionData& rTabConnDataList = m_pView->getController().getTableConnectionData();
1535 OSL_ENSURE( std::find(rTabConnDataList.begin(), rTabConnDataList.end(),_pConnection->GetData()) == rTabConnDataList.end(),"Data already in vector!");
1536 #endif
1537 m_pView->getController().getTableConnectionData().push_back(_pConnection->GetData());
1539 m_vTableConnection.emplace_back(_pConnection);
1540 _pConnection->RecalcLines();
1541 _pConnection->InvalidateConnection();
1543 modified();
1544 if ( m_pAccessible )
1545 m_pAccessible->notifyAccessibleEvent( AccessibleEventId::CHILD,
1546 Any(),
1547 Any(_pConnection->GetAccessible()));
1550 bool OJoinTableView::allowQueries() const
1552 return true;
1555 void OJoinTableView::onNoColumns_throw()
1557 OSL_FAIL( "OTableWindow::onNoColumns_throw: cannot really handle this!" );
1558 throw SQLException();
1561 bool OJoinTableView::suppressCrossNaturalJoin(const TTableConnectionData::value_type& ) const
1563 return false;
1566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */