1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "TableWindowListBox.hxx"
21 #include "TableWindow.hxx"
22 #include "QueryDesignView.hxx"
23 #include "QueryTableView.hxx"
24 #include "querycontroller.hxx"
25 #include "JoinExchange.hxx"
26 #include <osl/diagnose.h>
27 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
28 #include <vcl/svapp.hxx>
30 using namespace dbaui
;
31 using namespace ::com::sun::star::sdbc
;
32 using namespace ::com::sun::star::uno
;
33 using namespace ::com::sun::star::datatransfer
;
35 OJoinExchangeData::OJoinExchangeData(OTableWindowListBox
* pBox
)
37 , pEntry(pBox
->FirstSelected())
40 const sal_uLong SCROLLING_TIMESPAN
= 500;
41 const long LISTBOX_SCROLLING_AREA
= 6;
42 //==================================================================
43 // class OTableWindowListBox
44 //==================================================================
45 DBG_NAME(OTableWindowListBox
)
46 //------------------------------------------------------------------------------
47 OTableWindowListBox::OTableWindowListBox( OTableWindow
* pParent
)
48 :SvTreeListBox( pParent
, WB_HASBUTTONS
| WB_BORDER
)
49 ,m_aMousePos( Point(0,0) )
53 ,m_bReallyScrolled( sal_False
)
55 DBG_CTOR(OTableWindowListBox
,NULL
);
56 m_aScrollTimer
.SetTimeout( SCROLLING_TIMESPAN
);
57 SetDoubleClickHdl( LINK(this, OTableWindowListBox
, OnDoubleClick
) );
59 SetSelectionMode(SINGLE_SELECTION
);
64 //------------------------------------------------------------------------------
65 void OTableWindowListBox::dragFinished( )
67 // first show the error msg when existing
68 m_pTabWin
->getDesignView()->getController().showError(m_pTabWin
->getDesignView()->getController().clearOccurredError());
69 // second look for ui activities which should happen after d&d
71 Application::RemoveUserEvent(m_nUiEvent
);
72 m_nUiEvent
= Application::PostUserEvent(LINK(this, OTableWindowListBox
, LookForUiHdl
));
75 //------------------------------------------------------------------------------
76 OTableWindowListBox::~OTableWindowListBox()
78 DBG_DTOR(OTableWindowListBox
,NULL
);
80 Application::RemoveUserEvent(m_nDropEvent
);
82 Application::RemoveUserEvent(m_nUiEvent
);
83 if( m_aScrollTimer
.IsActive() )
84 m_aScrollTimer
.Stop();
88 //------------------------------------------------------------------------------
89 SvTreeListEntry
* OTableWindowListBox::GetEntryFromText( const String
& rEntryText
)
91 //////////////////////////////////////////////////////////////////////
92 // iterate through the list
93 SvTreeList
* pTreeList
= GetModel();
94 SvTreeListEntry
* pEntry
= pTreeList
->First();
95 OJoinDesignView
* pView
= m_pTabWin
->getDesignView();
96 OJoinController
& rController
= pView
->getController();
98 sal_Bool bCase
= sal_False
;
101 Reference
<XConnection
> xConnection
= rController
.getConnection();
104 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
106 bCase
= xMeta
->supportsMixedCaseQuotedIdentifiers();
110 if((bCase
? rEntryText
== GetEntryText(pEntry
) : rEntryText
.EqualsIgnoreCaseAscii(GetEntryText(pEntry
))))
114 pEntry
= pTreeList
->Next(pEntry
);
124 //------------------------------------------------------------------------------
125 void OTableWindowListBox::NotifyScrolled()
127 m_bReallyScrolled
= sal_True
;
130 //------------------------------------------------------------------------------
131 void OTableWindowListBox::NotifyEndScroll()
133 if (m_bReallyScrolled
)
134 // connections of this table, if any, should be redrawn
135 m_pTabWin
->getTableView()->Invalidate(INVALIDATE_NOCHILDREN
);
137 // without INVALIDATE_NOCHILDREN all tables would be redrawn,
139 m_bReallyScrolled
= sal_False
;
142 //------------------------------------------------------------------------------
143 long OTableWindowListBox::PreNotify(NotifyEvent
& rNEvt
)
145 sal_Bool bHandled
= sal_False
;
146 switch (rNEvt
.GetType())
150 const KeyEvent
* pKeyEvent
= rNEvt
.GetKeyEvent();
151 const KeyCode
& rCode
= pKeyEvent
->GetKeyCode();
153 if (rCode
.GetCode() != KEY_RETURN
)
157 bHandled
= m_pTabWin
->HandleKeyInput(*pKeyEvent
);
162 if (rCode
.IsMod1() || rCode
.IsMod2() || rCode
.IsShift())
165 static_cast<OTableWindow
*>(Window::GetParent())->OnEntryDoubleClicked(FirstSelected());
171 return SvTreeListBox::PreNotify(rNEvt
);
175 //------------------------------------------------------------------------------
176 IMPL_LINK( OTableWindowListBox
, ScrollUpHdl
, SvTreeListBox
*, /*pBox*/ )
178 SvTreeListEntry
* pEntry
= GetEntry( m_aMousePos
);
182 if( pEntry
!= Last() )
184 ScrollOutputArea( -1 );
185 pEntry
= GetEntry( m_aMousePos
);
186 Select( pEntry
, sal_True
);
192 //------------------------------------------------------------------------------
193 IMPL_LINK( OTableWindowListBox
, ScrollDownHdl
, SvTreeListBox
*, /*pBox*/ )
195 SvTreeListEntry
* pEntry
= GetEntry( m_aMousePos
);
199 if( pEntry
!= Last() )
201 ScrollOutputArea( 1 );
202 pEntry
= GetEntry( m_aMousePos
);
203 Select( pEntry
, sal_True
);
209 //------------------------------------------------------------------------------
210 void OTableWindowListBox::StartDrag( sal_Int8
/*nAction*/, const Point
& /*rPosPixel*/ )
212 OJoinTableView
* pCont
= m_pTabWin
->getTableView();
213 if (!pCont
->getDesignView()->getController().isReadOnly() && pCont
->getDesignView()->getController().isConnected())
215 // asterix was not allowed to be copied to selection browsebox
216 sal_Bool bFirstNotAllowed
= FirstSelected() == First() && m_pTabWin
->GetData()->IsShowAll();
218 // create a description of the source
219 OJoinExchangeData
jxdSource(this);
220 // put it into a exchange object
221 OJoinExchObj
* pJoin
= new OJoinExchObj(jxdSource
,bFirstNotAllowed
);
222 Reference
< XTransferable
> xEnsureDelete(pJoin
);
223 pJoin
->StartDrag(this, DND_ACTION_LINK
, this);
227 //------------------------------------------------------------------------------
228 sal_Int8
OTableWindowListBox::AcceptDrop( const AcceptDropEvent
& _rEvt
)
230 sal_Int8 nDND_Action
= DND_ACTION_NONE
;
232 if ( !OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_TABID
) // this means that the first entry is to be draged
233 && OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_JOIN
) )
234 { // don't drop into the window if it's the drag source itself
236 // remove the selection if the dragging operation is leaving the window
238 SelectAll(sal_False
);
242 m_aMousePos
= _rEvt
.maPosPixel
;
243 Size aOutputSize
= GetOutputSizePixel();
244 SvTreeListEntry
* pEntry
= GetEntry( m_aMousePos
);
246 return DND_ACTION_NONE
;
249 Rectangle
aBottomScrollArea( Point(0, aOutputSize
.Height()-LISTBOX_SCROLLING_AREA
),
250 Size(aOutputSize
.Width(), LISTBOX_SCROLLING_AREA
) );
251 Rectangle
aTopScrollArea( Point(0,0), Size(aOutputSize
.Width(), LISTBOX_SCROLLING_AREA
) );
253 // scroll up if the pointer is on the upper scroll area
254 if( aBottomScrollArea
.IsInside(m_aMousePos
) )
256 if( !m_aScrollTimer
.IsActive() )
258 m_aScrollTimer
.SetTimeoutHdl( LINK(this, OTableWindowListBox
, ScrollUpHdl
) );
263 // scroll down if the pointer is on the lower scroll area
264 else if( aTopScrollArea
.IsInside(m_aMousePos
) )
266 if( !m_aScrollTimer
.IsActive() )
268 m_aScrollTimer
.SetTimeoutHdl( LINK(this, OTableWindowListBox
, ScrollDownHdl
) );
269 ScrollDownHdl( this );
274 if( m_aScrollTimer
.IsActive() )
275 m_aScrollTimer
.Stop();
278 // automatically select right entry when dragging
279 if ((FirstSelected() != pEntry
) || (FirstSelected() && NextSelected(FirstSelected())))
280 SelectAll(sal_False
);
281 Select(pEntry
, sal_True
);
283 // one cannot drop on the first (*) entry
284 if(!( m_pTabWin
->GetData()->IsShowAll() && (pEntry
==First()) ))
285 nDND_Action
= DND_ACTION_LINK
;
290 // -----------------------------------------------------------------------------
292 //------------------------------------------------------------------------------
293 IMPL_LINK( OTableWindowListBox
, LookForUiHdl
, void *, /*EMPTY_ARG*/)
296 m_pTabWin
->getTableView()->lookForUiActivities();
299 //------------------------------------------------------------------------------
300 IMPL_LINK( OTableWindowListBox
, DropHdl
, void *, /*EMPTY_ARG*/)
302 // create the connection
304 OSL_ENSURE(m_pTabWin
,"No TableWindow!");
307 OJoinTableView
* pCont
= m_pTabWin
->getTableView();
308 OSL_ENSURE(pCont
,"No QueryTableView!");
309 pCont
->AddConnection(m_aDropInfo
.aSource
, m_aDropInfo
.aDest
);
311 catch(const SQLException
& e
)
313 // remember the exception so that we can show them later when d&d is finished
314 m_pTabWin
->getDesignView()->getController().setErrorOccurred(::dbtools::SQLExceptionInfo(e
));
318 //------------------------------------------------------------------------------
319 sal_Int8
OTableWindowListBox::ExecuteDrop( const ExecuteDropEvent
& _rEvt
)
321 TransferableDataHelper
aDropped(_rEvt
.maDropEvent
.Transferable
);
322 if ( OJoinExchObj::isFormatAvailable(aDropped
.GetDataFlavorExVector()))
323 { // don't drop into the window if it's the drag source itself
324 m_aDropInfo
.aSource
= OJoinExchangeData(this);
325 m_aDropInfo
.aDest
= OJoinExchObj::GetSourceDescription(_rEvt
.maDropEvent
.Transferable
);
328 Application::RemoveUserEvent(m_nDropEvent
);
329 m_nDropEvent
= Application::PostUserEvent(LINK(this, OTableWindowListBox
, DropHdl
));
331 return DND_ACTION_LINK
;
333 return DND_ACTION_NONE
;
336 //------------------------------------------------------------------------------
337 void OTableWindowListBox::LoseFocus()
340 m_pTabWin
->setActive(sal_False
);
341 SvTreeListBox::LoseFocus();
344 //------------------------------------------------------------------------------
345 void OTableWindowListBox::GetFocus()
348 m_pTabWin
->setActive();
350 if (GetCurEntry() != NULL
)
352 if ( GetSelectionCount() == 0 || GetCurEntry() != FirstSelected() )
354 if ( FirstSelected() )
355 Select(FirstSelected(), sal_False
);
356 Select(GetCurEntry(), sal_True
);
359 ShowFocusRect(FirstSelected());
361 SvTreeListBox::GetFocus();
364 //------------------------------------------------------------------------------
365 IMPL_LINK( OTableWindowListBox
, OnDoubleClick
, SvTreeListBox
*, /*pBox*/ )
368 Window
* pParent
= Window::GetParent();
369 OSL_ENSURE(pParent
!= NULL
, "OTableWindowListBox::OnDoubleClick : habe kein Parent !");
371 static_cast<OTableWindow
*>(pParent
)->OnEntryDoubleClicked(GetHdlEntry());
375 // -----------------------------------------------------------------------------
376 void OTableWindowListBox::Command(const CommandEvent
& rEvt
)
378 switch (rEvt
.GetCommand())
380 case COMMAND_CONTEXTMENU
:
382 static_cast<OTableWindow
*>(Window::GetParent())->Command(rEvt
);
386 SvTreeListBox::Command(rEvt
);
389 // -----------------------------------------------------------------------------
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */