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