xref: /AOO41X/main/dbaccess/source/ui/querydesign/TableWindowListBox.cxx (revision 96de54900b79e13b861fbc62cbf36018b54e21b7)
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_dbaccess.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