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_TABLEWINDOW_HXX
27 #include "TableWindow.hxx"
28 #endif
29 #ifndef DBAUI_TABLEWINDOWLISTBOX_HXX
30 #include "TableWindowListBox.hxx"
31 #endif
32 #ifndef DBAUI_QUERYTABLEVIEW_HXX
33 #include "QueryTableView.hxx"
34 #endif
35 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
36 #include "QueryDesignView.hxx"
37 #endif
38 #ifndef DBAUI_TABLEWINDOWDATA_HXX
39 #include "TableWindowData.hxx"
40 #endif
41 #ifndef DBACCESS_IMAGEPROVIDER_HXX
42 #include "imageprovider.hxx"
43 #endif
44 #ifndef _TOOLS_DEBUG_HXX
45 #include <tools/debug.hxx>
46 #endif
47 #ifndef TOOLS_DIAGNOSE_EX_H
48 #include <tools/diagnose_ex.h>
49 #endif
50 #ifndef _SV_SVAPP_HXX
51 #include <vcl/svapp.hxx>
52 #endif
53 #ifndef _SV_WALL_HXX
54 #include <vcl/wall.hxx>
55 #endif
56 
57 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
58 #include <com/sun/star/container/XNameAccess.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
61 #include <com/sun/star/accessibility/AccessibleRole.hpp>
62 #include "querycontroller.hxx"
63 #include "dbu_qry.hrc"
64 #include "dbustrings.hrc"
65 #include "Query.hrc"
66 #include <comphelper/extract.hxx>
67 #include "UITools.hxx"
68 #include "TableWindowAccess.hxx"
69 #include "browserids.hxx"
70 #include <connectivity/dbtools.hxx>
71 
72 
73 using namespace dbaui;
74 using namespace ::utl;
75 using namespace ::com::sun::star;
76 using namespace ::com::sun::star::sdb;
77 using namespace ::com::sun::star::sdbc;
78 using namespace ::com::sun::star::sdbcx;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::container;
82 using namespace ::com::sun::star::lang;
83 using namespace ::com::sun::star::accessibility;
84 
85 #define TABWIN_SIZING_AREA		4
86 #define LISTBOX_SCROLLING_AREA	6
87 #define SCROLLING_TIMESPAN		500
88 
89 #define TABWIN_WIDTH_MIN	90
90 #define TABWIN_HEIGHT_MIN	80
91 
92 //========================================================================
93 // class OTableWindow
94 //========================================================================
95 DBG_NAME(OTableWindow)
96 //------------------------------------------------------------------------------
97 OTableWindow::OTableWindow( Window* pParent, const TTableWindowData::value_type& pTabWinData )
98 		  : ::comphelper::OContainerListener(m_aMutex)
99           ,Window( pParent, WB_3DLOOK|WB_MOVEABLE )
100           ,m_aTypeImage( this )
101 		  ,m_aTitle( this )
102 		  ,m_pListBox(NULL)
103 		  ,m_pAccessible(NULL)
104           ,m_pData( pTabWinData )
105 		  ,m_nMoveCount(0)
106 		  ,m_nMoveIncrement(1)
107           ,m_nSizingFlags( SIZING_NONE )
108 		  ,m_bActive( sal_False )
109 {
110 	DBG_CTOR(OTableWindow,NULL);
111 
112     // Position und Groesse bestimmen
113 	if( GetData()->HasPosition() )
114 		SetPosPixel( GetData()->GetPosition() );
115 
116 	if( GetData()->HasSize() )
117 		SetSizePixel( GetData()->GetSize() );
118 
119 	// Hintergrund setzen
120 	const StyleSettings&  aSystemStyle = Application::GetSettings().GetStyleSettings();
121 	SetBackground(Wallpaper(aSystemStyle.GetFaceColor()));
122 	// und Textfarbe (obwohl ich eigentlich keinen Text habe, aber wer weiss, was
123 	// abgeleitete Klassen machen)
124 	SetTextColor(aSystemStyle.GetButtonTextColor());
125 
126 	EnableClipSiblings();
127 }
128 
129 //------------------------------------------------------------------------------
130 OTableWindow::~OTableWindow()
131 {
132 	DBG_DTOR(OTableWindow,NULL);
133 
134 	if (m_pListBox)
135 	{
136 		OSL_ENSURE(m_pListBox->GetEntryCount()==0,"Forgot to call EmptyListbox()!");
137 		::std::auto_ptr<Window> aTemp(m_pListBox);
138 		m_pListBox = NULL;
139 	} // if (m_pListBox)
140     if ( m_pContainerListener.is() )
141         m_pContainerListener->dispose();
142 
143 	m_pAccessible = NULL;
144 }
145 // -----------------------------------------------------------------------------
146 const OJoinTableView* OTableWindow::getTableView() const
147 {
148 	OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!");
149 	return static_cast<OJoinTableView*>(GetParent());
150 }
151 // -----------------------------------------------------------------------------
152 OJoinTableView* OTableWindow::getTableView()
153 {
154 	OSL_ENSURE(static_cast<OJoinTableView*>(GetParent()),"No OJoinTableView!");
155 	return static_cast<OJoinTableView*>(GetParent());
156 }
157 // -----------------------------------------------------------------------------
158 OJoinDesignView* OTableWindow::getDesignView()
159 {
160 	OSL_ENSURE(static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent()),"No OJoinDesignView!");
161 	return static_cast<OJoinDesignView*>(GetParent()->GetParent()->GetParent());
162 }
163 //------------------------------------------------------------------------------
164 void OTableWindow::SetPosPixel( const Point& rNewPos )
165 {
166 	Point aNewPosData = rNewPos + getTableView()->GetScrollOffset();
167 	GetData()->SetPosition( aNewPosData );
168 	Window::SetPosPixel( rNewPos );
169 }
170 
171 //------------------------------------------------------------------------------
172 void OTableWindow::SetSizePixel( const Size& rNewSize )
173 {
174 	Size aOutSize(rNewSize);
175 	if( aOutSize.Width() < TABWIN_WIDTH_MIN )
176 		aOutSize.Width() = TABWIN_WIDTH_MIN;
177 	if( aOutSize.Height() < TABWIN_HEIGHT_MIN )
178 		aOutSize.Height() = TABWIN_HEIGHT_MIN;
179 
180 	GetData()->SetSize( aOutSize );
181 	Window::SetSizePixel( aOutSize );
182 }
183 //------------------------------------------------------------------------------
184 void OTableWindow::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
185 {
186 	SetPosPixel( rNewPos );
187 	SetSizePixel( rNewSize );
188 }
189 //------------------------------------------------------------------------------
190 OTableWindowListBox* OTableWindow::CreateListBox()
191 {
192 	return new OTableWindowListBox(this);
193 }
194 
195 //------------------------------------------------------------------------------
196 sal_Bool OTableWindow::FillListBox()
197 {
198     m_pListBox->Clear();
199     if ( !m_pContainerListener.is() )
200     {
201         Reference< XContainer> xContainer(m_pData->getColumns(),UNO_QUERY);
202         if ( xContainer.is() )
203             m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer);
204     }
205 	// mark all primary keys with special image
206     ModuleRes TmpRes(isHiContrast(m_pListBox) ? IMG_JOINS_H : IMG_JOINS);
207 	ImageList aImageList(TmpRes);
208 	Image aPrimKeyImage = aImageList.GetImage(IMG_PRIMARY_KEY);
209 
210 	if (GetData()->IsShowAll())
211 	{
212 		SvLBoxEntry* pEntry = m_pListBox->InsertEntry( ::rtl::OUString::createFromAscii("*") );
213 		pEntry->SetUserData( createUserData(NULL,false) );
214 	}
215 
216 	Reference<XNameAccess> xPKeyColumns;
217 	try
218 	{
219         xPKeyColumns = dbtools::getPrimaryKeyColumns_throw(m_pData->getTable());
220 	}
221 	catch(Exception&)
222 	{
223 		OSL_ENSURE(0,"Exception occured!");
224 	}
225 	try
226 	{
227         Reference< XNameAccess > xColumns = m_pData->getColumns();
228 		if( xColumns.is() )
229 		{
230 			Sequence< ::rtl::OUString> aColumns = xColumns->getElementNames();
231 			const ::rtl::OUString* pIter = aColumns.getConstArray();
232 			const ::rtl::OUString* pEnd = pIter + aColumns.getLength();
233 
234 			SvLBoxEntry* pEntry = NULL;
235 			for (; pIter != pEnd; ++pIter)
236 			{
237 				bool bPrimaryKeyColumn = xPKeyColumns.is() && xPKeyColumns->hasByName( *pIter );
238 				// is this column in the primary key
239 				if ( bPrimaryKeyColumn )
240 					pEntry = m_pListBox->InsertEntry(*pIter, aPrimKeyImage, aPrimKeyImage);
241 				else
242 					pEntry = m_pListBox->InsertEntry(*pIter);
243 
244                 Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY);
245 				if ( xColumn.is() )
246 					pEntry->SetUserData( createUserData(xColumn,bPrimaryKeyColumn) );
247 			}
248 		}
249 	}
250 	catch(Exception&)
251 	{
252 		OSL_ENSURE(0,"Exception occured!");
253 	}
254 
255 	return sal_True;
256 }
257 // -----------------------------------------------------------------------------
258 void* OTableWindow::createUserData(const Reference< XPropertySet>& /*_xColumn*/,bool /*_bPrimaryKey*/)
259 {
260 	return NULL;
261 }
262 // -----------------------------------------------------------------------------
263 void OTableWindow::deleteUserData(void*& _pUserData)
264 {
265 	OSL_ENSURE(!_pUserData,"INVALID call. Need to delete the userclass!");
266 	_pUserData = NULL;
267 }
268 //------------------------------------------------------------------------------
269 void OTableWindow::clearListBox()
270 {
271 	if ( m_pListBox )
272 	{
273 		SvLBoxEntry* pEntry = m_pListBox->First();
274 
275 		while(pEntry)
276 		{
277 			void* pUserData = pEntry->GetUserData();
278 			deleteUserData(pUserData);
279 			SvLBoxEntry* pNextEntry = m_pListBox->Next(pEntry);
280 			m_pListBox->GetModel()->Remove(pEntry);
281 			pEntry = pNextEntry;
282 		}
283 	}
284 }
285 
286 //------------------------------------------------------------------------------
287 void OTableWindow::impl_updateImage()
288 {
289     ImageProvider aImageProvider( getDesignView()->getController().getConnection() );
290 
291     Image aImage, aImageHC;
292     aImageProvider.getImages( GetComposedName(), m_pData->isQuery() ? DatabaseObject::QUERY : DatabaseObject::TABLE, aImage, aImageHC );
293 
294     if ( !aImage || !aImageHC )
295     {
296         OSL_ENSURE( false, "OTableWindow::impl_updateImage: no images!" );
297         return;
298     }
299 
300     m_aTypeImage.SetModeImage( aImage, BMP_COLOR_NORMAL );
301     m_aTypeImage.SetModeImage( aImageHC, BMP_COLOR_HIGHCONTRAST );
302     m_aTypeImage.Show();
303 }
304 
305 //------------------------------------------------------------------------------
306 sal_Bool OTableWindow::Init()
307 {
308 	// create list box if necessary
309 	if ( !m_pListBox )
310 	{
311 		m_pListBox = CreateListBox();
312 		DBG_ASSERT( m_pListBox != NULL, "OTableWindow::Init() : CreateListBox hat NULL geliefert !" );
313 		m_pListBox->SetSelectionMode( MULTIPLE_SELECTION );
314 	}
315 
316 	// Titel setzen
317 	m_aTitle.SetText( m_pData->GetWinName() );
318 	m_aTitle.Show();
319 
320 	m_pListBox->Show();
321 
322 	// die Felder in die ListBox eintragen
323 	clearListBox();
324     sal_Bool bSuccess = FillListBox();
325 	if ( bSuccess )
326 		m_pListBox->SelectAll( sal_False );
327 
328     impl_updateImage();
329 
330 	return bSuccess;
331 }
332 //------------------------------------------------------------------------------
333 void OTableWindow::DataChanged(const DataChangedEvent& rDCEvt)
334 {
335 	if (rDCEvt.GetType() == DATACHANGED_SETTINGS)
336 	{
337 		// nehmen wir den worst-case an : die Farben haben sich geaendert, also
338 		// mich anpassen
339 		const StyleSettings&  aSystemStyle = Application::GetSettings().GetStyleSettings();
340 		SetBackground(Wallpaper(Color(aSystemStyle.GetFaceColor())));
341 		SetTextColor(aSystemStyle.GetButtonTextColor());
342 	}
343 }
344 //------------------------------------------------------------------------------
345 void OTableWindow::Paint( const Rectangle& rRect )
346 {
347 	Rectangle aRect( Point(0,0), GetOutputSizePixel() );
348 	Window::Paint( rRect );
349 	Draw3DBorder( aRect );
350 }
351 
352 //------------------------------------------------------------------------------
353 void OTableWindow::Draw3DBorder(const Rectangle& rRect)
354 {
355 	// die Style-Settings des Systems fuer meine Farben
356 	const StyleSettings& aSystemStyle = Application::GetSettings().GetStyleSettings();
357 
358 	// Schwarze Linie unten und rechts
359 	SetLineColor(aSystemStyle.GetDarkShadowColor());
360 	DrawLine( rRect.BottomLeft(), rRect.BottomRight() );
361 	DrawLine( rRect.BottomRight(), rRect.TopRight() );
362 
363 	// Dunkelgraue Linie ueber der schwarzen
364 	SetLineColor(aSystemStyle.GetShadowColor());
365 	Point aEHvector(1,1);
366 	DrawLine( rRect.BottomLeft()+Point(1,-1), rRect.BottomRight() - aEHvector );
367 	DrawLine( rRect.BottomRight() - aEHvector, rRect.TopRight()+Point(-1,1) );
368 
369 	// Hellgraue Linie links und oben
370 	SetLineColor(aSystemStyle.GetLightColor());
371 	DrawLine( rRect.BottomLeft()+Point(1,-2), rRect.TopLeft() + aEHvector );
372 	DrawLine( rRect.TopLeft() + aEHvector, rRect.TopRight()+Point(-2,1) );
373 }
374 // -----------------------------------------------------------------------------
375 Rectangle OTableWindow::getSizingRect(const Point& _rPos,const Size& _rOutputSize) const
376 {
377 	Rectangle aSizingRect = Rectangle( GetPosPixel(), GetSizePixel() );
378 	sal_uInt16 nSizingFlags = GetSizingFlags();
379 
380 	if( nSizingFlags & SIZING_TOP )
381 	{
382 		if( _rPos.Y() < 0 )
383 			aSizingRect.Top() = 0;
384 		else
385 			aSizingRect.Top() = _rPos.Y();
386 	}
387 
388 	if( nSizingFlags & SIZING_BOTTOM )
389 	{
390 		if( _rPos.Y() > _rOutputSize.Height() )
391 			aSizingRect.Bottom() = _rOutputSize.Height();
392 		else
393 			aSizingRect.Bottom() = _rPos.Y();
394 	}
395 
396 
397 	if( nSizingFlags & SIZING_RIGHT )
398 	{
399 		if( _rPos.X() > _rOutputSize.Width() )
400 			aSizingRect.Right() = _rOutputSize.Width();
401 		else
402 			aSizingRect.Right() = _rPos.X();
403 	}
404 
405 	if( nSizingFlags & SIZING_LEFT )
406 	{
407 		if( _rPos.X() < 0 )
408 			aSizingRect.Left() = 0;
409 		else
410 			aSizingRect.Left() = _rPos.X();
411 	}
412 	return aSizingRect;
413 }
414 // -----------------------------------------------------------------------------
415 void OTableWindow::setSizingFlag(const Point& _rPos)
416 {
417 	Size	aOutSize = GetOutputSizePixel();
418 	//////////////////////////////////////////////////////////////////////
419 	// Flags anpassen, wenn Mauszeiger in sizingArea
420 	m_nSizingFlags = SIZING_NONE;
421 
422 	if( _rPos.X() < TABWIN_SIZING_AREA )
423 		m_nSizingFlags |= SIZING_LEFT;
424 
425 	if( _rPos.Y() < TABWIN_SIZING_AREA )
426 		m_nSizingFlags |= SIZING_TOP;
427 
428 	if( _rPos.X() > aOutSize.Width()-TABWIN_SIZING_AREA )
429 		m_nSizingFlags |= SIZING_RIGHT;
430 
431 	if( _rPos.Y() > aOutSize.Height()-TABWIN_SIZING_AREA )
432 		m_nSizingFlags |= SIZING_BOTTOM;
433 }
434 //------------------------------------------------------------------------------
435 void OTableWindow::MouseMove( const MouseEvent& rEvt )
436 {
437 	Window::MouseMove(rEvt);
438 
439 	OJoinTableView* pCont = getTableView();
440 	if (pCont->getDesignView()->getController().isReadOnly())
441 		return;
442 
443 	Point	aPos = rEvt.GetPosPixel();
444 	setSizingFlag(aPos);
445 	Pointer	aPointer;
446 
447 
448 	//////////////////////////////////////////////////////////////////////
449 	// Mauszeiger anpassen, wenn Mauszeiger in sizingArea
450 	switch( m_nSizingFlags )
451 	{
452 	case SIZING_TOP:
453 	case SIZING_BOTTOM:
454 		aPointer = Pointer( POINTER_SSIZE );
455 		break;
456 
457 	case SIZING_LEFT:
458 	case SIZING_RIGHT:
459 		aPointer = Pointer( POINTER_ESIZE );
460 		break;
461 
462 	case SIZING_LEFT+SIZING_TOP:
463 	case SIZING_RIGHT+SIZING_BOTTOM:
464 		aPointer = Pointer( POINTER_SESIZE );
465 		break;
466 
467 	case SIZING_RIGHT+SIZING_TOP:
468 	case SIZING_LEFT+SIZING_BOTTOM:
469 		aPointer = Pointer( POINTER_NESIZE );
470 		break;
471 	}
472 
473 	SetPointer( aPointer );
474 }
475 
476 //------------------------------------------------------------------------------
477 void OTableWindow::MouseButtonDown( const MouseEvent& rEvt )
478 {
479 	//////////////////////////////////////////////////////////////////////
480 	// Wenn sizing, dann bekommt Parent die Nachricht,
481 	// dass jetzt die Fenstergroesse seines Childs veraendert wird
482 	if( m_nSizingFlags )
483 		getTableView()->BeginChildSizing( this, GetPointer() );
484 
485 	Window::MouseButtonDown( rEvt );
486 }
487 
488 
489 
490 //------------------------------------------------------------------------------
491 void OTableWindow::Resize()
492 {
493 	//////////////////////////////////////////////////////////////////////
494 	// Das Fenster darf nicht verschwinden, deshalb min. Groesse setzen
495 	Size	aOutSize = GetOutputSizePixel();
496 	aOutSize = Size(CalcZoom(aOutSize.Width()),CalcZoom(aOutSize.Height()));
497 
498 	long nTitleHeight = CalcZoom( GetTextHeight() )+ CalcZoom( 4 );
499 
500 	//////////////////////////////////////////////////////////////////////
501 	// Titel und ListBox anpassen
502 	long n5Pos = CalcZoom(5);
503     long nPositionX = n5Pos;
504     long nPositionY = n5Pos;
505 
506     // position the image which indicates the type
507     m_aTypeImage.SetPosPixel( Point( nPositionX, nPositionY ) );
508     Size aImageSize( m_aTypeImage.GetImage().GetSizePixel() );
509     m_aTypeImage.SetSizePixel( aImageSize );
510 
511     if ( nTitleHeight < aImageSize.Height() )
512         nTitleHeight = aImageSize.Height();
513 
514     nPositionX += aImageSize.Width() + CalcZoom( 2 );
515 	m_aTitle.SetPosSizePixel( Point( nPositionX, nPositionY ), Size( aOutSize.Width() - nPositionX - n5Pos, nTitleHeight ) );
516 
517     long nTitleToList = CalcZoom( 3 );
518 
519 	m_pListBox->SetPosSizePixel(
520         Point( n5Pos, nPositionY + nTitleHeight + nTitleToList ),
521         Size( aOutSize.Width() - 2 * n5Pos, aOutSize.Height() - ( nPositionY + nTitleHeight + nTitleToList ) - n5Pos )
522     );
523 
524     Window::Invalidate();
525 }
526 
527 //------------------------------------------------------------------------------
528 void OTableWindow::SetBoldTitle( sal_Bool bBold )
529 {
530 	Font aFont = m_aTitle.GetFont();
531 	aFont.SetWeight( bBold?WEIGHT_BOLD:WEIGHT_NORMAL );
532 	m_aTitle.SetFont( aFont );
533 	m_aTitle.Invalidate();
534 }
535 
536 //------------------------------------------------------------------------------
537 void OTableWindow::GetFocus()
538 {
539 	Window::GetFocus();
540 	// we have to forward the focus to our listbox to enable keystokes
541 	if(m_pListBox)
542 		m_pListBox->GrabFocus();
543 }
544 // -----------------------------------------------------------------------------
545 void OTableWindow::setActive(sal_Bool _bActive)
546 {
547 	SetBoldTitle( _bActive );
548 	m_bActive = _bActive;
549 	if (!_bActive && m_pListBox && m_pListBox->GetSelectionCount() != 0)
550 		m_pListBox->SelectAll(sal_False);
551 }
552 
553 //------------------------------------------------------------------------------
554 void OTableWindow::Remove()
555 {
556 	//////////////////////////////////////////////////////////////////
557 	// Fenster loeschen
558 	OJoinTableView* pTabWinCont = getTableView();
559 	pTabWinCont->RemoveTabWin( this );
560 	pTabWinCont->Invalidate();
561 }
562 //------------------------------------------------------------------------------
563 sal_Bool OTableWindow::HandleKeyInput( const KeyEvent& rEvt )
564 {
565 	const KeyCode& rCode = rEvt.GetKeyCode();
566 	sal_uInt16 nCode = rCode.GetCode();
567 	sal_Bool   bShift = rCode.IsShift();
568 	sal_Bool   bCtrl = rCode.IsMod1();
569 
570 	sal_Bool bHandle = sal_False;
571 
572 	if( !bCtrl && !bShift && (nCode==KEY_DELETE) )
573 	{
574 		Remove();
575 		bHandle = sal_True;
576 	}
577 	return bHandle;
578 }
579 
580 //------------------------------------------------------------------------------
581 sal_Bool OTableWindow::ExistsAConn() const
582 {
583 	return getTableView()->ExistsAConn(this);
584 }
585 //------------------------------------------------------------------------------
586 void OTableWindow::EnumValidFields(::std::vector< ::rtl::OUString>& arrstrFields)
587 {
588 	arrstrFields.clear();
589 	// diese Default-Implementierung zaehlt einfach alles auf, was es in der ListBox gibt ... fuer anderes Verhalten ueberschreiben
590 	if ( m_pListBox )
591 	{
592 		arrstrFields.reserve(m_pListBox->GetEntryCount());
593 		SvLBoxEntry* pEntryLoop = m_pListBox->First();
594 		while (pEntryLoop)
595 		{
596 			arrstrFields.push_back(m_pListBox->GetEntryText(pEntryLoop));
597 			pEntryLoop = m_pListBox->Next(pEntryLoop);
598 		}
599 	}
600 }
601 // -----------------------------------------------------------------------------
602 void OTableWindow::StateChanged( StateChangedType nType )
603 {
604 	Window::StateChanged( nType );
605 
606 	if ( nType == STATE_CHANGE_ZOOM )
607 	{
608 		const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
609 
610 		Font aFont = rStyleSettings.GetGroupFont();
611 		if ( IsControlFont() )
612 			aFont.Merge( GetControlFont() );
613 		SetZoomedPointFont( aFont );
614 
615 		m_aTitle.SetZoom(GetZoom());
616 		m_pListBox->SetZoom(GetZoom());
617 		Resize();
618 		Invalidate();
619 	}
620 }
621 // -----------------------------------------------------------------------------
622 Reference< XAccessible > OTableWindow::CreateAccessible()
623 {
624 	OTableWindowAccess* pAccessible = new OTableWindowAccess(this);
625 	m_pAccessible = pAccessible;
626 	return pAccessible;
627 }
628 // -----------------------------------------------------------------------------
629 void OTableWindow::Command(const CommandEvent& rEvt)
630 {
631 	switch (rEvt.GetCommand())
632 	{
633 		case COMMAND_CONTEXTMENU:
634 		{
635 			OJoinController& rController = getDesignView()->getController();
636 			if(!rController.isReadOnly() && rController.isConnected())
637 			{
638 				Point ptWhere;
639 				if ( rEvt.IsMouseEvent() )
640 					ptWhere = rEvt.GetMousePosPixel();
641 				else
642 				{
643 					SvLBoxEntry* pCurrent = m_pListBox->GetCurEntry();
644 					if ( pCurrent )
645 						ptWhere = m_pListBox->GetEntryPosition(pCurrent);
646 					else
647 						ptWhere = m_aTitle.GetPosPixel();
648 				}
649 
650 				PopupMenu aContextMenu(ModuleRes(RID_MENU_JOINVIEW_TABLE));
651 				switch (aContextMenu.Execute(this, ptWhere))
652 				{
653 					case SID_DELETE:
654 						Remove();
655 						break;
656 				}
657 			}
658 			break;
659 		}
660 		default:
661 			Window::Command(rEvt);
662 	}
663 }
664 // -----------------------------------------------------------------------------
665 long OTableWindow::PreNotify(NotifyEvent& rNEvt)
666 {
667 	sal_Bool bHandled = sal_False;
668 	switch (rNEvt.GetType())
669 	{
670 		case EVENT_KEYINPUT:
671 		{
672 			if ( getDesignView()->getController().isReadOnly() )
673 				break;
674 
675 			const KeyEvent* pKeyEvent =	rNEvt.GetKeyEvent();
676 			const KeyCode& rCode = pKeyEvent->GetKeyCode();
677 			if ( rCode.IsMod1() )
678 			{
679 				Point aStartPoint = GetPosPixel();
680 				if ( rCode.IsShift() )
681 				{
682 					aStartPoint.X() = GetSizePixel().Width();
683 					aStartPoint.Y() = GetSizePixel().Height();
684 				}
685 
686 				switch( rCode.GetCode() )
687 				{
688 					case KEY_DOWN:
689 						bHandled = sal_True;
690 						aStartPoint.Y() += m_nMoveIncrement;
691 						break;
692 					case KEY_UP:
693 						bHandled = sal_True;
694 						aStartPoint.Y() += -m_nMoveIncrement;
695 						break;
696 					case KEY_LEFT:
697 						bHandled = sal_True;
698 						aStartPoint.X() += -m_nMoveIncrement;
699 						break;
700 					case KEY_RIGHT:
701 						bHandled = sal_True;
702 						aStartPoint.X()  += m_nMoveIncrement;
703 						break;
704 				}
705 				if ( bHandled )
706 				{
707 					if ( rCode.IsShift() )
708 					{
709 						OJoinTableView* pView = getTableView();
710 						Point ptOld = GetPosPixel();
711 						Size aSize = pView->getRealOutputSize();
712 						Size aNewSize(aStartPoint.X(),aStartPoint.Y());
713 						if (   ((ptOld.X() + aNewSize.Width())  <= aSize.Width())
714 							&& ((ptOld.Y() + aNewSize.Height()) <= aSize.Height()) )
715 						{
716 							if ( aNewSize.Width() < TABWIN_WIDTH_MIN )
717 								aNewSize.Width() = TABWIN_WIDTH_MIN;
718 							if ( aNewSize.Height() < TABWIN_HEIGHT_MIN )
719 								aNewSize.Height() = TABWIN_HEIGHT_MIN;
720 
721 							Size szOld = GetSizePixel();
722 
723 							aNewSize = Size(pView->CalcZoom(aNewSize.Width()),pView->CalcZoom(aNewSize.Height()));
724 							SetPosSizePixel( ptOld, aNewSize );
725 							pView->TabWinSized(this, ptOld, szOld);
726 							Invalidate( INVALIDATE_NOCHILDREN );
727 						}
728 					}
729 					else
730 					{
731 						// remember how often the user moved our window
732 						++m_nMoveCount;
733 						if( m_nMoveCount == 5 )
734 							m_nMoveIncrement = 10;
735 						else if( m_nMoveCount > 15 )
736 							m_nMoveCount = m_nMoveIncrement = 20;
737 
738 						Point aOldDataPoint = GetData()->GetPosition();
739 						Point aNewDataPoint = aStartPoint + getTableView()->GetScrollOffset();
740 						if ( aNewDataPoint.X() > -1 && aNewDataPoint.Y() > -1 )
741 						{
742 							OJoinTableView* pView = getTableView();
743 							if ( pView->isMovementAllowed(aNewDataPoint, GetData()->GetSize()) )
744 							{
745 								SetPosPixel(aStartPoint);
746 
747 								// aNewDataPoint can not be used here because SetPosPixel reset it
748 								pView->EnsureVisible(GetData()->GetPosition(), GetData()->GetSize());
749 								pView->TabWinMoved(this,aOldDataPoint);
750 								Invalidate(INVALIDATE_NOCHILDREN);
751 								getDesignView()->getController().setModified( sal_True );
752 							}
753 							else
754 							{
755 								m_nMoveCount		= 0; // reset our movement count
756 								m_nMoveIncrement	= 1;
757 							}
758 						}
759 						else
760 						{
761 							m_nMoveCount		= 0; // reset our movement count
762 							m_nMoveIncrement	= 1;
763 						}
764 					}
765 					resetSizingFlag();
766 				}
767 				else
768 				{
769 					m_nMoveCount		= 0; // reset our movement count
770 					m_nMoveIncrement	= 1;
771 				}
772 			}
773 			else
774 			{
775 				m_nMoveCount		= 0; // reset our movement count
776 				m_nMoveIncrement	= 1;
777 			}
778 		}
779 			break;
780 		case EVENT_KEYUP:
781 		{
782 			const KeyEvent* pKeyEvent =	rNEvt.GetKeyEvent();
783 			const KeyCode& rCode = pKeyEvent->GetKeyCode();
784 			sal_uInt16 nKeyCode = rCode.GetCode();
785 			if ( rCode.IsMod2() && nKeyCode != KEY_UP && nKeyCode != KEY_DOWN && nKeyCode != KEY_LEFT && nKeyCode != KEY_RIGHT )
786 			{
787 				m_nMoveCount		= 0; // reset our movement count
788 				m_nMoveIncrement	= 1;
789 			}
790 		}
791 			break;
792 	}
793 	if (!bHandled)
794 		return Window::PreNotify(rNEvt);
795 	return 1L;
796 }
797 // -----------------------------------------------------------------------------
798 String OTableWindow::getTitle() const
799 {
800 	return m_aTitle.GetText();
801 }
802 // -----------------------------------------------------------------------------
803 void OTableWindow::_elementInserted( const container::ContainerEvent& /*_rEvent*/ )  throw(::com::sun::star::uno::RuntimeException)
804 {
805     FillListBox();
806 }
807 // -----------------------------------------------------------------------------
808 void OTableWindow::_elementRemoved( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
809 {
810     FillListBox();
811 }
812 // -----------------------------------------------------------------------------
813 void OTableWindow::_elementReplaced( const container::ContainerEvent& /*_rEvent*/ ) throw(::com::sun::star::uno::RuntimeException)
814 {
815     FillListBox();
816 }
817 // -----------------------------------------------------------------------------
818 
819