1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbui.hxx"
26 #ifndef DBAUI_TABLEWINDOWLISTBOX_HXX
27 #include "TableWindowListBox.hxx"
28 #endif
29 #ifndef DBAUI_TABLEWINDOW_HXX
30 #include "TableWindow.hxx"
31 #endif
32 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
33 #include "QueryDesignView.hxx"
34 #endif
35 #ifndef DBAUI_QUERYTABLEVIEW_HXX
36 #include "QueryTableView.hxx"
37 #endif
38 #ifndef DBAUI_QUERYCONTROLLER_HXX
39 #include "querycontroller.hxx"
40 #endif
41 #ifndef DBAUI_JOINEXCHANGE_HXX
42 #include "JoinExchange.hxx"
43 #endif
44 #ifndef _TOOLS_DEBUG_HXX
45 #include <tools/debug.hxx>
46 #endif
47 #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
48 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
49 #endif
50 #ifndef _SVX_DBEXCH_HRC
51 #include <svx/dbexch.hrc>
52 #endif
53 #ifndef _SV_SVAPP_HXX
54 #include <vcl/svapp.hxx>
55 #endif
56
57 using namespace dbaui;
58 using namespace ::com::sun::star::sdbc;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::datatransfer;
61
OJoinExchangeData(OTableWindowListBox * pBox)62 OJoinExchangeData::OJoinExchangeData(OTableWindowListBox* pBox)
63 : pListBox(pBox)
64 , pEntry(pBox->FirstSelected())
65 { }
66
67 const sal_uLong SCROLLING_TIMESPAN = 500;
68 const long LISTBOX_SCROLLING_AREA = 6;
69 //==================================================================
70 // class OTableWindowListBox
71 //==================================================================
DBG_NAME(OTableWindowListBox)72 DBG_NAME(OTableWindowListBox)
73 //------------------------------------------------------------------------------
74 OTableWindowListBox::OTableWindowListBox( OTableWindow* pParent )
75 :SvTreeListBox( pParent, WB_HASBUTTONS | WB_BORDER)
76 ,m_aMousePos( Point(0,0) )
77 ,m_pTabWin( pParent )
78 ,m_nDropEvent(0)
79 ,m_nUiEvent(0)
80 ,m_bReallyScrolled( sal_False )
81 {
82 DBG_CTOR(OTableWindowListBox,NULL);
83 m_aScrollTimer.SetTimeout( SCROLLING_TIMESPAN );
84 SetDoubleClickHdl( LINK(this, OTableWindowListBox, OnDoubleClick) );
85
86 SetSelectionMode(SINGLE_SELECTION);
87
88 SetHighlightRange( );
89 }
90
91 //------------------------------------------------------------------------------
dragFinished()92 void OTableWindowListBox::dragFinished( )
93 {
94 // first show the error msg when existing
95 m_pTabWin->getDesignView()->getController().showError(m_pTabWin->getDesignView()->getController().clearOccuredError());
96 // second look for ui activities which should happen after d&d
97 if (m_nUiEvent)
98 Application::RemoveUserEvent(m_nUiEvent);
99 m_nUiEvent = Application::PostUserEvent(LINK(this, OTableWindowListBox, LookForUiHdl));
100 }
101
102 //------------------------------------------------------------------------------
~OTableWindowListBox()103 OTableWindowListBox::~OTableWindowListBox()
104 {
105 DBG_DTOR(OTableWindowListBox,NULL);
106 if (m_nDropEvent)
107 Application::RemoveUserEvent(m_nDropEvent);
108 if (m_nUiEvent)
109 Application::RemoveUserEvent(m_nUiEvent);
110 if( m_aScrollTimer.IsActive() )
111 m_aScrollTimer.Stop();
112 m_pTabWin = NULL;
113 }
114
115 //------------------------------------------------------------------------------
GetEntryFromText(const String & rEntryText)116 SvLBoxEntry* OTableWindowListBox::GetEntryFromText( const String& rEntryText )
117 {
118 //////////////////////////////////////////////////////////////////////
119 // Liste durchiterieren
120 SvTreeList* pTreeList = GetModel();
121 SvLBoxEntry* pEntry = (SvLBoxEntry*)pTreeList->First();
122 OJoinDesignView* pView = m_pTabWin->getDesignView();
123 OJoinController& rController = pView->getController();
124
125 sal_Bool bCase = sal_False;
126 try
127 {
128 Reference<XConnection> xConnection = rController.getConnection();
129 if(xConnection.is())
130 {
131 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
132 if(xMeta.is())
133 bCase = xMeta->supportsMixedCaseQuotedIdentifiers();
134 }
135 while( pEntry )
136 {
137 if((bCase ? rEntryText == GetEntryText(pEntry) : rEntryText.EqualsIgnoreCaseAscii(GetEntryText(pEntry))))
138 {
139 return pEntry;
140 }
141 pEntry = (SvLBoxEntry*)pTreeList->Next( pEntry );
142 }
143 }
144 catch(SQLException&)
145 {
146 }
147
148 return NULL;
149 }
150
151 //------------------------------------------------------------------------------
NotifyScrolled()152 void OTableWindowListBox::NotifyScrolled()
153 {
154 m_bReallyScrolled = sal_True;
155 }
156
157 //------------------------------------------------------------------------------
NotifyEndScroll()158 void OTableWindowListBox::NotifyEndScroll()
159 {
160 if (m_bReallyScrolled)
161 // die Verbindungen, die diese Tabelle eventuell hat, muessen neu gezeichnet werden
162 m_pTabWin->getTableView()->Invalidate(INVALIDATE_NOCHILDREN);
163 // ohne das INVALIDATE_NOCHILDREN wuerden auch alle Tabellen neu gezeichnet werden,
164 // sprich : es flackert
165 m_bReallyScrolled = sal_False;
166 }
167
168 //------------------------------------------------------------------------------
PreNotify(NotifyEvent & rNEvt)169 long OTableWindowListBox::PreNotify(NotifyEvent& rNEvt)
170 {
171 sal_Bool bHandled = sal_False;
172 switch (rNEvt.GetType())
173 {
174 case EVENT_KEYINPUT:
175 {
176 const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
177 const KeyCode& rCode = pKeyEvent->GetKeyCode();
178
179 if (rCode.GetCode() != KEY_RETURN)
180 {
181 if(m_pTabWin)
182 {
183 bHandled = m_pTabWin->HandleKeyInput(*pKeyEvent);
184 // bHandled = sal_True;
185 }
186 break;
187 }
188
189 if (rCode.IsMod1() || rCode.IsMod2() || rCode.IsShift())
190 break;
191 if (FirstSelected())
192 static_cast<OTableWindow*>(Window::GetParent())->OnEntryDoubleClicked(FirstSelected());
193 }
194 break;
195 }
196
197 if (!bHandled)
198 return SvTreeListBox::PreNotify(rNEvt);
199 return 1L;
200 }
201
202 //------------------------------------------------------------------------------
203 IMPL_LINK( OTableWindowListBox, ScrollUpHdl, SvTreeListBox*, /*pBox*/ )
204 {
205 SvLBoxEntry* pEntry = GetEntry( m_aMousePos );
206 if( !pEntry )
207 return 0;
208
209 if( pEntry != Last() )
210 {
211 ScrollOutputArea( -1 );
212 pEntry = GetEntry( m_aMousePos );
213 Select( pEntry, sal_True );
214 // m_aScrollTimer.Start();
215 }
216
217 return 0;
218 }
219
220 //------------------------------------------------------------------------------
221 IMPL_LINK( OTableWindowListBox, ScrollDownHdl, SvTreeListBox*, /*pBox*/ )
222 {
223 SvLBoxEntry* pEntry = GetEntry( m_aMousePos );
224 if( !pEntry )
225 return 0;
226
227 if( pEntry != Last() )
228 {
229 ScrollOutputArea( 1 );
230 pEntry = GetEntry( m_aMousePos );
231 Select( pEntry, sal_True );
232 // m_aScrollTimer.Start();
233 }
234
235 return 0;
236 }
237
238 //------------------------------------------------------------------------------
StartDrag(sal_Int8,const Point &)239 void OTableWindowListBox::StartDrag( sal_Int8 /*nAction*/, const Point& /*rPosPixel*/ )
240 {
241 OJoinTableView* pCont = m_pTabWin->getTableView();
242 if (!pCont->getDesignView()->getController().isReadOnly() && pCont->getDesignView()->getController().isConnected())
243 {
244 // #100271# OJ asterix was not allowed to be copied to selection browsebox
245 sal_Bool bFirstNotAllowed = FirstSelected() == First() && m_pTabWin->GetData()->IsShowAll();
246 EndSelection();
247 // create a description of the source
248 OJoinExchangeData jxdSource(this);
249 // put it into a exchange object
250 OJoinExchObj* pJoin = new OJoinExchObj(jxdSource,bFirstNotAllowed);
251 Reference< XTransferable > xEnsureDelete(pJoin);
252 pJoin->StartDrag(this, DND_ACTION_LINK, this);
253 }
254 }
255
256 //------------------------------------------------------------------------------
AcceptDrop(const AcceptDropEvent & _rEvt)257 sal_Int8 OTableWindowListBox::AcceptDrop( const AcceptDropEvent& _rEvt )
258 {
259 sal_Int8 nDND_Action = DND_ACTION_NONE;
260 // check the format
261 if ( !OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_TABID) // this means that the first entry is to be draged
262 && OJoinExchObj::isFormatAvailable(GetDataFlavorExVector(),SOT_FORMATSTR_ID_SBA_JOIN) )
263 { // don't drop into the window if it's the drag source itself
264
265
266 // remove the selection if the dragging operation is leaving the window
267 if (_rEvt.mbLeaving)
268 SelectAll(sal_False);
269 else
270 {
271 // hit test
272 m_aMousePos = _rEvt.maPosPixel;
273 Size aOutputSize = GetOutputSizePixel();
274 SvLBoxEntry* pEntry = GetEntry( m_aMousePos );
275 if( !pEntry )
276 return DND_ACTION_NONE;
277
278 // Scrolling Areas
279 Rectangle aBottomScrollArea( Point(0, aOutputSize.Height()-LISTBOX_SCROLLING_AREA),
280 Size(aOutputSize.Width(), LISTBOX_SCROLLING_AREA) );
281 Rectangle aTopScrollArea( Point(0,0), Size(aOutputSize.Width(), LISTBOX_SCROLLING_AREA) );
282
283 // Wenn Zeiger auf der oberen ScrollingArea steht, nach oben scrollen
284 if( aBottomScrollArea.IsInside(m_aMousePos) )
285 {
286 if( !m_aScrollTimer.IsActive() )
287 {
288 m_aScrollTimer.SetTimeoutHdl( LINK(this, OTableWindowListBox, ScrollUpHdl) );
289 ScrollUpHdl( this );
290 }
291 }
292
293 // Wenn Zeiger auf der oberen ScrollingArea steht, nach unten scrollen
294 else if( aTopScrollArea.IsInside(m_aMousePos) )
295 {
296 if( !m_aScrollTimer.IsActive() )
297 {
298 m_aScrollTimer.SetTimeoutHdl( LINK(this, OTableWindowListBox, ScrollDownHdl) );
299 ScrollDownHdl( this );
300 }
301 }
302 else
303 {
304 if( m_aScrollTimer.IsActive() )
305 m_aScrollTimer.Stop();
306 }
307
308 // Beim Drag automatisch den richtigen Eintrag selektieren
309 if ((FirstSelected() != pEntry) || (FirstSelected() && NextSelected(FirstSelected())))
310 SelectAll(sal_False);
311 Select(pEntry, sal_True);
312
313 // Auf den ersten Eintrag (*) kann nicht gedroppt werden
314 if(!( m_pTabWin->GetData()->IsShowAll() && (pEntry==First()) ))
315 nDND_Action = DND_ACTION_LINK;
316 }
317 }
318 return nDND_Action;
319 }
320 // -----------------------------------------------------------------------------
321
322 //------------------------------------------------------------------------------
323 IMPL_LINK( OTableWindowListBox, LookForUiHdl, void *, /*EMPTY_ARG*/)
324 {
325 m_nUiEvent = 0;
326 m_pTabWin->getTableView()->lookForUiActivities();
327 return 0L;
328 }
329 //------------------------------------------------------------------------------
330 IMPL_LINK( OTableWindowListBox, DropHdl, void *, /*EMPTY_ARG*/)
331 {
332 // create the connection
333 m_nDropEvent = 0;
334 OSL_ENSURE(m_pTabWin,"No TableWindow!");
335 try
336 {
337 OJoinTableView* pCont = m_pTabWin->getTableView();
338 OSL_ENSURE(pCont,"No QueryTableView!");
339 pCont->AddConnection(m_aDropInfo.aSource, m_aDropInfo.aDest);
340 }
341 catch(const SQLException& e)
342 {
343 // remember the exception so that we can show them later when d&d is finished
344 m_pTabWin->getDesignView()->getController().setErrorOccured(::dbtools::SQLExceptionInfo(e));
345 }
346 return 0L;
347 }
348 //------------------------------------------------------------------------------
ExecuteDrop(const ExecuteDropEvent & _rEvt)349 sal_Int8 OTableWindowListBox::ExecuteDrop( const ExecuteDropEvent& _rEvt )
350 {
351 TransferableDataHelper aDropped(_rEvt.maDropEvent.Transferable);
352 if ( OJoinExchObj::isFormatAvailable(aDropped.GetDataFlavorExVector()))
353 { // don't drop into the window if it's the drag source itself
354 m_aDropInfo.aSource = OJoinExchangeData(this);
355 m_aDropInfo.aDest = OJoinExchObj::GetSourceDescription(_rEvt.maDropEvent.Transferable);
356
357 if (m_nDropEvent)
358 Application::RemoveUserEvent(m_nDropEvent);
359 m_nDropEvent = Application::PostUserEvent(LINK(this, OTableWindowListBox, DropHdl));
360
361 return DND_ACTION_LINK;
362 }
363 return DND_ACTION_NONE;
364 }
365
366 //------------------------------------------------------------------------------
LoseFocus()367 void OTableWindowListBox::LoseFocus()
368 {
369 if(m_pTabWin)
370 m_pTabWin->setActive(sal_False);
371 SvTreeListBox::LoseFocus();
372 }
373
374 //------------------------------------------------------------------------------
GetFocus()375 void OTableWindowListBox::GetFocus()
376 {
377 if(m_pTabWin)
378 m_pTabWin->setActive();
379
380 if (GetCurEntry() != NULL)
381 {
382 if ( GetSelectionCount() == 0 || GetCurEntry() != FirstSelected() )
383 {
384 if ( FirstSelected() )
385 Select(FirstSelected(), sal_False);
386 Select(GetCurEntry(), sal_True);
387 }
388 else
389 ShowFocusRect(FirstSelected());
390 }
391 SvTreeListBox::GetFocus();
392 }
393
394 //------------------------------------------------------------------------------
395 IMPL_LINK( OTableWindowListBox, OnDoubleClick, SvTreeListBox *, /*pBox*/ )
396 {
397 // meinem Elter Bescheid sagen
398 Window* pParent = Window::GetParent();
399 DBG_ASSERT(pParent != NULL, "OTableWindowListBox::OnDoubleClick : habe kein Parent !");
400
401 static_cast<OTableWindow*>(pParent)->OnEntryDoubleClicked(GetHdlEntry());
402
403 return 0;
404 }
405 // -----------------------------------------------------------------------------
Command(const CommandEvent & rEvt)406 void OTableWindowListBox::Command(const CommandEvent& rEvt)
407 {
408 switch (rEvt.GetCommand())
409 {
410 case COMMAND_CONTEXTMENU:
411 {
412 static_cast<OTableWindow*>(Window::GetParent())->Command(rEvt);
413 break;
414 }
415 default:
416 SvTreeListBox::Command(rEvt);
417 }
418 }
419 // -----------------------------------------------------------------------------
420