update credits
[LibreOffice.git] / svtools / source / brwbox / editbrowsebox.cxx
blob9e0ab710991a7b2a40e50d2e9edcfa42573ce4c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svtools/editbrowsebox.hxx>
22 #include "editbrowsebox.hrc"
24 #include <vcl/svapp.hxx>
25 #include <tools/debug.hxx>
26 #include <vcl/window.hxx>
28 #include <vcl/edit.hxx>
29 #include <tools/resid.hxx>
30 #include <vcl/spinfld.hxx>
31 #include <svtools/svtresid.hxx>
33 #include <svtools/svtools.hrc>
35 #include <algorithm>
36 #include <tools/multisel.hxx>
37 #include "editbrowseboximpl.hxx"
38 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 #include <com/sun/star/accessibility/XAccessible.hpp>
40 #include <comphelper/types.hxx>
42 // .......................................................................
43 namespace svt
45 // .......................................................................
46 namespace
48 //..............................................................
49 sal_uInt16 getRealGetFocusFlags( Window* _pWindow )
51 sal_uInt16 nFlags = 0;
52 while ( _pWindow && !nFlags )
54 nFlags = _pWindow->GetGetFocusFlags( );
55 _pWindow = _pWindow->GetParent();
57 return nFlags;
61 using namespace ::com::sun::star::uno;
62 using namespace com::sun::star::accessibility::AccessibleEventId;
63 using com::sun::star::accessibility::XAccessible;
64 //==================================================================
66 IEditImplementation::~IEditImplementation()
70 //==================================================================
71 //= EditBrowserHeader
72 //==================================================================
73 //------------------------------------------------------------------------------
74 void EditBrowserHeader::DoubleClick()
76 sal_uInt16 nColId = GetCurItemId();
77 if (nColId)
79 sal_uInt32 nAutoWidth = ((EditBrowseBox*)GetParent())->GetAutoColumnWidth(nColId);
80 if (nAutoWidth != ((EditBrowseBox*)GetParent())->GetColumnWidth(nColId))
82 ((EditBrowseBox*)GetParent())->SetColumnWidth(nColId, nAutoWidth);
83 ((EditBrowseBox*)GetParent())->ColumnResized(nColId);
89 //==================================================================
90 //= EditBrowseBox
91 //==================================================================
92 //------------------------------------------------------------------------------
93 void EditBrowseBox::BrowserMouseEventPtr::Clear()
95 DELETEZ(pEvent);
98 //------------------------------------------------------------------------------
99 void EditBrowseBox::BrowserMouseEventPtr::Set(const BrowserMouseEvent* pEvt, sal_Bool bIsDown)
101 if (pEvt == pEvent)
103 bDown = bIsDown;
104 return;
106 Clear();
107 if (pEvt)
109 pEvent = new BrowserMouseEvent(pEvt->GetWindow(),
110 *pEvt,
111 pEvt->GetRow(),
112 pEvt->GetColumn(),
113 pEvt->GetColumnId(),
114 pEvt->GetRect());
115 bDown = bIsDown;
119 //------------------------------------------------------------------------------
120 DBG_NAME(EditBrowseBox);
121 void EditBrowseBox::impl_construct()
123 m_aImpl = ::std::auto_ptr<EditBrowseBoxImpl>(new EditBrowseBoxImpl());
125 SetCompoundControl(sal_True);
126 SetGridLineColor( Color( COL_LIGHTGRAY ) );
128 ImplInitSettings(sal_True, sal_True, sal_True);
130 pCheckBoxPaint = new CheckBoxControl(&GetDataWindow());
131 pCheckBoxPaint->SetPaintTransparent( sal_True );
132 pCheckBoxPaint->SetBackground();
135 //------------------------------------------------------------------------------
136 EditBrowseBox::EditBrowseBox(Window* pParent, const ResId& rId, sal_Int32 nBrowserFlags, BrowserMode _nMode )
137 :BrowseBox( pParent, rId, _nMode )
138 ,nStartEvent(0)
139 ,nEndEvent(0)
140 ,nCellModifiedEvent(0)
141 ,nPaintRow(-1)
142 ,nEditRow(-1)
143 ,nOldEditRow(-1)
144 ,nEditCol(0)
145 ,nOldEditCol(0)
146 ,bHasFocus(sal_False)
147 ,bPaintStatus(sal_True)
148 ,bActiveBeforeTracking( sal_False )
149 ,m_nBrowserFlags(nBrowserFlags)
151 DBG_CTOR(EditBrowseBox,NULL);
153 impl_construct();
156 //==================================================================
157 EditBrowseBox::EditBrowseBox( Window* pParent, sal_Int32 nBrowserFlags, WinBits nBits, BrowserMode _nMode )
158 :BrowseBox( pParent, nBits, _nMode )
159 ,nStartEvent(0)
160 ,nEndEvent(0)
161 ,nCellModifiedEvent(0)
162 ,nPaintRow(-1)
163 ,nEditRow(-1)
164 ,nOldEditRow(-1)
165 ,nEditCol(0)
166 ,nOldEditCol(0)
167 ,bHasFocus(sal_False)
168 ,bPaintStatus(sal_True)
169 ,bActiveBeforeTracking( sal_False )
170 ,m_nBrowserFlags(nBrowserFlags)
171 ,pHeader(NULL)
173 DBG_CTOR(EditBrowseBox,NULL);
175 impl_construct();
178 //------------------------------------------------------------------------------
179 void EditBrowseBox::Init()
181 // late construction
184 //------------------------------------------------------------------------------
185 EditBrowseBox::~EditBrowseBox()
187 if (nStartEvent)
188 Application::RemoveUserEvent(nStartEvent);
189 if (nEndEvent)
190 Application::RemoveUserEvent(nEndEvent);
191 if (nCellModifiedEvent)
192 Application::RemoveUserEvent(nCellModifiedEvent);
194 delete pCheckBoxPaint;
196 DBG_DTOR(EditBrowseBox,NULL);
199 //------------------------------------------------------------------------------
200 void EditBrowseBox::RemoveRows()
202 BrowseBox::Clear();
203 nOldEditRow = nEditRow = nPaintRow = -1;
204 nEditCol = nOldEditCol = 0;
207 //------------------------------------------------------------------------------
208 BrowserHeader* EditBrowseBox::CreateHeaderBar(BrowseBox* pParent)
210 pHeader = imp_CreateHeaderBar(pParent);
211 if (!IsUpdateMode())
212 pHeader->SetUpdateMode(sal_False);
213 return pHeader;
216 //------------------------------------------------------------------------------
217 BrowserHeader* EditBrowseBox::imp_CreateHeaderBar(BrowseBox* pParent)
219 return new EditBrowserHeader(pParent);
222 //------------------------------------------------------------------------------
223 void EditBrowseBox::LoseFocus()
225 BrowseBox::LoseFocus();
226 DetermineFocus( 0 );
229 //------------------------------------------------------------------------------
230 void EditBrowseBox::GetFocus()
232 BrowseBox::GetFocus();
234 // This should handle the case that the BrowseBox (or one of it's children)
235 // gets the focus from outside by pressing Tab
236 if (IsEditing() && Controller()->GetWindow().IsVisible())
237 Controller()->GetWindow().GrabFocus();
239 DetermineFocus( getRealGetFocusFlags( this ) );
242 //------------------------------------------------------------------------------
243 sal_Bool EditBrowseBox::SeekRow(long nRow)
245 nPaintRow = nRow;
246 return sal_True;
249 //------------------------------------------------------------------------------
250 IMPL_LINK_NOARG(EditBrowseBox, StartEditHdl)
252 nStartEvent = 0;
253 if (IsEditing())
255 EnableAndShow();
256 if (!aController->GetWindow().HasFocus() && (m_pFocusWhileRequest == Application::GetFocusWindow()))
257 aController->GetWindow().GrabFocus();
259 return 0;
262 //------------------------------------------------------------------------------
263 void EditBrowseBox::PaintField( OutputDevice& rDev, const Rectangle& rRect,
264 sal_uInt16 nColumnId ) const
266 if (nColumnId == HandleColumnId)
268 if (bPaintStatus)
269 PaintStatusCell(rDev, rRect);
271 else
273 // don't paint the current cell
274 if (&rDev == &GetDataWindow())
275 // but only if we're painting onto our data win (which is the usual painting)
276 if (nPaintRow == nEditRow)
278 if (IsEditing() && nEditCol == nColumnId && aController->GetWindow().IsVisible())
279 return;
281 PaintCell(rDev, rRect, nColumnId);
285 //------------------------------------------------------------------------------
286 Image EditBrowseBox::GetImage(RowStatus eStatus) const
288 if ( !m_aStatusImages.GetImageCount() )
290 const_cast<EditBrowseBox*>(this)->m_aStatusImages = ImageList( SvtResId( RID_SVTOOLS_IMAGELIST_EDITBROWSEBOX ) );
293 Image aImage;
294 bool bNeedMirror = IsRTLEnabled();
295 switch (eStatus)
297 case CURRENT:
298 aImage = m_aStatusImages.GetImage(IMG_EBB_CURRENT);
299 break;
300 case CURRENTNEW:
301 aImage = m_aStatusImages.GetImage(IMG_EBB_CURRENTNEW);
302 break;
303 case MODIFIED:
304 aImage = m_aStatusImages.GetImage(IMG_EBB_MODIFIED);
305 bNeedMirror = false; // the pen is not mirrored
306 break;
307 case NEW:
308 aImage = m_aStatusImages.GetImage(IMG_EBB_NEW);
309 break;
310 case DELETED:
311 aImage = m_aStatusImages.GetImage(IMG_EBB_DELETED);
312 break;
313 case PRIMARYKEY:
314 aImage = m_aStatusImages.GetImage(IMG_EBB_PRIMARYKEY);
315 break;
316 case CURRENT_PRIMARYKEY:
317 aImage = m_aStatusImages.GetImage(IMG_EBB_CURRENT_PRIMARYKEY);
318 break;
319 case FILTER:
320 aImage = m_aStatusImages.GetImage(IMG_EBB_FILTER);
321 break;
322 case HEADERFOOTER:
323 aImage = m_aStatusImages.GetImage(IMG_EBB_HEADERFOOTER);
324 break;
325 case CLEAN:
326 break;
328 if ( bNeedMirror )
330 BitmapEx aBitmap( aImage.GetBitmapEx() );
331 aBitmap.Mirror( BMP_MIRROR_HORZ );
332 aImage = Image( aBitmap );
334 return aImage;
337 //------------------------------------------------------------------------------
338 void EditBrowseBox::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const
340 if (nPaintRow < 0)
341 return;
343 RowStatus eStatus = GetRowStatus( nPaintRow );
344 sal_Int32 nBrowserFlags = GetBrowserFlags();
346 if (nBrowserFlags & EBBF_NO_HANDLE_COLUMN_CONTENT)
347 return;
349 // draw the text of the header column
350 if (nBrowserFlags & EBBF_HANDLE_COLUMN_TEXT )
352 rDev.DrawText( rRect, GetCellText( nPaintRow, 0 ),
353 TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_CLIP );
355 // draw an image
356 else if (eStatus != CLEAN && rDev.GetOutDevType() == OUTDEV_WINDOW)
358 Image aImage(GetImage(eStatus));
359 // calc the image position
360 Size aImageSize(aImage.GetSizePixel());
361 aImageSize.Width() = CalcZoom(aImageSize.Width());
362 aImageSize.Height() = CalcZoom(aImageSize.Height());
363 Point aPos( rRect.TopLeft() );
365 if ( ( aImageSize.Width() > rRect.GetWidth() ) || ( aImageSize.Height() > rRect.GetHeight() ) )
366 rDev.SetClipRegion(Region(rRect));
368 if ( aImageSize.Width() < rRect.GetWidth() )
369 aPos.X() += ( rRect.GetWidth() - aImageSize.Width() ) / 2;
371 if ( aImageSize.Height() < rRect.GetHeight() )
372 aPos.Y() += ( rRect.GetHeight() - aImageSize.Height() ) / 2;
374 if ( IsZoom() )
375 rDev.DrawImage( aPos, aImageSize, aImage, 0 );
376 else
377 rDev.DrawImage( aPos, aImage, 0 );
379 if (rDev.IsClipRegion())
380 rDev.SetClipRegion();
384 //------------------------------------------------------------------------------
385 void EditBrowseBox::ImplStartTracking()
387 bActiveBeforeTracking = IsEditing();
388 if ( bActiveBeforeTracking )
390 DeactivateCell();
391 Update();
394 BrowseBox::ImplStartTracking();
397 //------------------------------------------------------------------------------
398 void EditBrowseBox::ImplTracking()
400 BrowseBox::ImplTracking();
403 //------------------------------------------------------------------------------
404 void EditBrowseBox::ImplEndTracking()
406 if ( bActiveBeforeTracking )
407 ActivateCell();
408 bActiveBeforeTracking = sal_False;
410 BrowseBox::ImplEndTracking();
413 //------------------------------------------------------------------------------
414 void EditBrowseBox::RowHeightChanged()
416 if ( IsEditing() )
418 Rectangle aRect( GetCellRect( nEditRow, nEditCol, sal_False ) );
419 CellControllerRef aCellController( Controller() );
420 ResizeController( aCellController, aRect );
421 aCellController->GetWindow().GrabFocus();
424 BrowseBox::RowHeightChanged();
427 //------------------------------------------------------------------------------
428 EditBrowseBox::RowStatus EditBrowseBox::GetRowStatus(long) const
430 return CLEAN;
433 //------------------------------------------------------------------------------
434 void EditBrowseBox::KeyInput( const KeyEvent& rEvt )
436 sal_uInt16 nCode = rEvt.GetKeyCode().GetCode();
437 sal_Bool bShift = rEvt.GetKeyCode().IsShift();
438 sal_Bool bCtrl = rEvt.GetKeyCode().IsMod1();
440 switch (nCode)
442 case KEY_RETURN:
443 if (!bCtrl && !bShift && IsTabAllowed(sal_True))
445 Dispatch(BROWSER_CURSORRIGHT);
447 else
448 BrowseBox::KeyInput(rEvt);
449 return;
450 case KEY_TAB:
451 if (!bCtrl && !bShift)
453 if (IsTabAllowed(sal_True))
454 Dispatch(BROWSER_CURSORRIGHT);
455 else
456 // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now
457 // that tab isn't allowed here. So give the Control class a chance
458 Control::KeyInput(rEvt);
459 return;
461 else if (!bCtrl && bShift)
463 if (IsTabAllowed(sal_False))
464 Dispatch(BROWSER_CURSORLEFT);
465 else
466 // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now
467 // that tab isn't allowed here. So give the Control class a chance
468 Control::KeyInput(rEvt);
469 return;
471 default:
472 BrowseBox::KeyInput(rEvt);
476 //------------------------------------------------------------------------------
477 void EditBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt)
479 sal_uInt16 nColPos = GetColumnPos( rEvt.GetColumnId() );
480 long nRow = rEvt.GetRow();
482 // absorb double clicks
483 if (rEvt.GetClicks() > 1 && rEvt.GetRow() >= 0)
484 return;
486 // change to a new position
487 if (IsEditing() && (nColPos != nEditCol || nRow != nEditRow) && (nColPos != BROWSER_INVALIDID) && (nRow < GetRowCount()))
489 CellControllerRef aCellController(Controller());
490 HideAndDisable(aCellController);
493 // we are about to leave the current cell. If there is a "this cell has been modified" notification
494 // pending (asynchronously), this may be deadly -> do it synchronously
495 if ( nCellModifiedEvent )
497 Application::RemoveUserEvent( nCellModifiedEvent );
498 nCellModifiedEvent = 0;
499 LINK( this, EditBrowseBox, CellModifiedHdl ).Call( NULL );
502 if (rEvt.GetColumnId() == HandleColumnId)
503 { // it was the handle column. save the current cell content if necessary
504 // (clicking on the handle column results in selecting the current row)
505 if (IsEditing() && aController->IsModified())
506 SaveModified();
509 aMouseEvent.Set(&rEvt,sal_True);
510 BrowseBox::MouseButtonDown(rEvt);
511 aMouseEvent.Clear();
513 if (0 != (m_nBrowserFlags & EBBF_ACTIVATE_ON_BUTTONDOWN))
515 // the base class does not travel upon MouseButtonDown, but implActivateCellOnMouseEvent assumes we traveled ...
516 GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() );
517 if (rEvt.GetRow() >= 0)
518 implActivateCellOnMouseEvent(rEvt, sal_False);
522 //------------------------------------------------------------------------------
523 void EditBrowseBox::MouseButtonUp( const BrowserMouseEvent& rEvt )
525 // absorb double clicks
526 if (rEvt.GetClicks() > 1 && rEvt.GetRow() >= 0)
527 return;
529 aMouseEvent.Set(&rEvt,sal_False);
530 BrowseBox::MouseButtonUp(rEvt);
531 aMouseEvent.Clear();
533 if (0 == (m_nBrowserFlags & EBBF_ACTIVATE_ON_BUTTONDOWN))
534 if (rEvt.GetRow() >= 0)
535 implActivateCellOnMouseEvent(rEvt, sal_True);
538 //------------------------------------------------------------------------------
539 void EditBrowseBox::implActivateCellOnMouseEvent(const BrowserMouseEvent& _rEvt, sal_Bool _bUp)
541 if (!IsEditing())
542 ActivateCell();
543 else if (IsEditing() && !aController->GetWindow().IsEnabled())
544 DeactivateCell();
545 else if (IsEditing() && !aController->GetWindow().HasChildPathFocus())
546 AsynchGetFocus();
548 if (IsEditing() && aController->GetWindow().IsEnabled() && aController->WantMouseEvent())
549 { // forwards the event to the control
551 // If the field has been moved previously, we have to adjust the position
553 aController->GetWindow().GrabFocus();
555 // the position of the event relative to the controller's window
556 Point aPos = _rEvt.GetPosPixel() - _rEvt.GetRect().TopLeft();
557 // the (child) window which should really get the event
558 Window* pRealHandler = aController->GetWindow().FindWindow(aPos);
559 if (pRealHandler)
560 // the coords relative to this real handler
561 aPos -= pRealHandler->GetPosPixel();
562 else
563 pRealHandler = &aController->GetWindow();
565 // the faked event
566 MouseEvent aEvent(aPos, _rEvt.GetClicks(), _rEvt.GetMode(),
567 _rEvt.GetButtons(),
568 _rEvt.GetModifier());
570 pRealHandler->MouseButtonDown(aEvent);
571 if (_bUp)
572 pRealHandler->MouseButtonUp(aEvent);
574 Window *pWin = &aController->GetWindow();
575 if (!pWin->IsTracking())
577 for (pWin = pWin->GetWindow(WINDOW_FIRSTCHILD);
578 pWin && !pWin->IsTracking();
579 pWin = pWin->GetWindow(WINDOW_NEXT))
583 if (pWin && pWin->IsTracking())
584 pWin->EndTracking();
588 //------------------------------------------------------------------------------
589 void EditBrowseBox::Dispatch( sal_uInt16 _nId )
591 if ( _nId == BROWSER_ENHANCESELECTION )
592 { // this is a workaround for the bug in the base class:
593 // if the row selection is to be extended (which is what BROWSER_ENHANCESELECTION tells us)
594 // then the base class does not revert any column selections, while, for doing a "simple"
595 // selection (BROWSER_SELECT), it does. In fact, it does not only revert the col selection then,
596 // but also any current row selections.
597 // This clearly tells me that the both ids are for row selection only - there this behaviour does
598 // make sense.
599 // But here, where we have column selection, too, we take care of this ourself.
600 if ( GetSelectColumnCount( ) )
602 while ( GetSelectColumnCount( ) )
603 SelectColumnPos(
604 sal::static_int_cast< sal_uInt16 >(FirstSelectedColumn()),
605 sal_False );
606 Select();
609 BrowseBox::Dispatch( _nId );
612 //------------------------------------------------------------------------------
613 long EditBrowseBox::PreNotify(NotifyEvent& rEvt)
615 switch (rEvt.GetType())
617 case EVENT_KEYINPUT:
618 if ( (IsEditing() && Controller()->GetWindow().HasChildPathFocus())
619 || rEvt.GetWindow() == &GetDataWindow()
620 || (!IsEditing() && HasChildPathFocus())
623 const KeyEvent* pKeyEvent = rEvt.GetKeyEvent();
624 sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
625 sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift();
626 sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
627 sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
628 sal_Bool bLocalSelect= sal_False;
629 sal_Bool bNonEditOnly = sal_False;
630 sal_uInt16 nId = BROWSER_NONE;
632 if (!bAlt && !bCtrl && !bShift )
633 switch ( nCode )
635 case KEY_DOWN: nId = BROWSER_CURSORDOWN; break;
636 case KEY_UP: nId = BROWSER_CURSORUP; break;
637 case KEY_PAGEDOWN: nId = BROWSER_CURSORPAGEDOWN; break;
638 case KEY_PAGEUP: nId = BROWSER_CURSORPAGEUP; break;
639 case KEY_HOME: nId = BROWSER_CURSORHOME; break;
640 case KEY_END: nId = BROWSER_CURSOREND; break;
642 case KEY_TAB:
643 // ask if traveling to the next cell is allowed
644 if (IsTabAllowed(sal_True))
645 nId = BROWSER_CURSORRIGHT;
646 break;
648 case KEY_RETURN:
649 // save the cell content (if necessary)
650 if (IsEditing() && aController->IsModified() && !((EditBrowseBox *) this)->SaveModified())
652 // maybe we're not visible ...
653 EnableAndShow();
654 aController->GetWindow().GrabFocus();
655 return 1;
657 // ask if traveling to the next cell is allowed
658 if (IsTabAllowed(sal_True))
659 nId = BROWSER_CURSORRIGHT;
661 break;
662 case KEY_RIGHT: nId = BROWSER_CURSORRIGHT; break;
663 case KEY_LEFT: nId = BROWSER_CURSORLEFT; break;
664 case KEY_SPACE: nId = BROWSER_SELECT; bNonEditOnly = bLocalSelect = sal_True;break;
667 if ( !bAlt && !bCtrl && bShift )
668 switch ( nCode )
670 case KEY_DOWN: nId = BROWSER_SELECTDOWN; bLocalSelect = sal_True;break;
671 case KEY_UP: nId = BROWSER_SELECTUP; bLocalSelect = sal_True;break;
672 case KEY_HOME: nId = BROWSER_SELECTHOME; bLocalSelect = sal_True;break;
673 case KEY_END: nId = BROWSER_SELECTEND; bLocalSelect = sal_True;break;
674 case KEY_TAB:
675 if (IsTabAllowed(sal_False))
676 nId = BROWSER_CURSORLEFT;
677 break;
680 if ( !bAlt && bCtrl && bShift )
681 switch ( nCode )
683 case KEY_SPACE: nId = BROWSER_SELECTCOLUMN; bLocalSelect = sal_True; break;
687 if ( !bAlt && bCtrl && !bShift )
688 switch ( nCode )
690 case KEY_DOWN: nId = BROWSER_SCROLLUP; break;
691 case KEY_UP: nId = BROWSER_SCROLLDOWN; break;
692 case KEY_PAGEDOWN: nId = BROWSER_CURSORENDOFFILE; break;
693 case KEY_PAGEUP: nId = BROWSER_CURSORTOPOFFILE; break;
694 case KEY_HOME: nId = BROWSER_CURSORTOPOFSCREEN; break;
695 case KEY_END: nId = BROWSER_CURSORENDOFSCREEN; break;
696 case KEY_SPACE: nId = BROWSER_ENHANCESELECTION; bLocalSelect = sal_True;break;
700 if ( ( nId != BROWSER_NONE )
701 && ( !IsEditing()
702 || ( !bNonEditOnly
703 && aController->MoveAllowed( *pKeyEvent )
708 if (nId == BROWSER_SELECT || BROWSER_SELECTCOLUMN == nId )
710 // save the cell content (if necessary)
711 if (IsEditing() && aController->IsModified() && !((EditBrowseBox *) this)->SaveModified())
713 // maybe we're not visible ...
714 EnableAndShow();
715 aController->GetWindow().GrabFocus();
716 return 1;
720 Dispatch(nId);
722 if (bLocalSelect && (GetSelectRowCount() || GetSelection() != NULL))
723 DeactivateCell();
724 return 1;
728 return BrowseBox::PreNotify(rEvt);
731 //------------------------------------------------------------------------------
732 sal_Bool EditBrowseBox::IsTabAllowed(sal_Bool) const
734 return sal_True;
737 //------------------------------------------------------------------------------
738 long EditBrowseBox::Notify(NotifyEvent& rEvt)
740 switch (rEvt.GetType())
742 case EVENT_GETFOCUS:
743 DetermineFocus( getRealGetFocusFlags( this ) );
744 break;
746 case EVENT_LOSEFOCUS:
747 DetermineFocus( 0 );
748 break;
750 return BrowseBox::Notify(rEvt);
753 //------------------------------------------------------------------------------
754 void EditBrowseBox::StateChanged( StateChangedType nType )
756 BrowseBox::StateChanged( nType );
758 bool bNeedCellReActivation = false;
759 if ( nType == STATE_CHANGE_MIRRORING )
761 bNeedCellReActivation = true;
763 else if ( nType == STATE_CHANGE_ZOOM )
765 ImplInitSettings( sal_True, sal_False, sal_False );
766 bNeedCellReActivation = true;
768 else if ( nType == STATE_CHANGE_CONTROLFONT )
770 ImplInitSettings( sal_True, sal_False, sal_False );
771 Invalidate();
773 else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
775 ImplInitSettings( sal_False, sal_True, sal_False );
776 Invalidate();
778 else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
780 ImplInitSettings( sal_False, sal_False, sal_True );
781 Invalidate();
783 else if (nType == STATE_CHANGE_STYLE)
785 WinBits nStyle = GetStyle();
786 if (!(nStyle & WB_NOTABSTOP) )
787 nStyle |= WB_TABSTOP;
789 SetStyle(nStyle);
791 if ( bNeedCellReActivation )
793 if ( IsEditing() )
795 DeactivateCell();
796 ActivateCell();
801 //------------------------------------------------------------------------------
802 void EditBrowseBox::DataChanged( const DataChangedEvent& rDCEvt )
804 BrowseBox::DataChanged( rDCEvt );
806 if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS ) ||
807 ( rDCEvt.GetType() == DATACHANGED_DISPLAY )) &&
808 ( rDCEvt.GetFlags() & SETTINGS_STYLE ))
810 ImplInitSettings( sal_True, sal_True, sal_True );
811 Invalidate();
815 //------------------------------------------------------------------------------
816 void EditBrowseBox::ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground )
818 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
820 if (bFont)
822 Font aFont = rStyleSettings.GetFieldFont();
823 if (IsControlFont())
825 GetDataWindow().SetControlFont(GetControlFont());
826 aFont.Merge(GetControlFont());
828 else
829 GetDataWindow().SetControlFont();
831 GetDataWindow().SetZoomedPointFont(aFont);
834 if ( bFont || bForeground )
836 Color aTextColor = rStyleSettings.GetFieldTextColor();
837 if (IsControlForeground())
839 aTextColor = GetControlForeground();
840 GetDataWindow().SetControlForeground(aTextColor);
842 else
843 GetDataWindow().SetControlForeground();
845 GetDataWindow().SetTextColor( aTextColor );
848 if ( bBackground )
850 if (GetDataWindow().IsControlBackground())
852 GetDataWindow().SetControlBackground(GetControlBackground());
853 GetDataWindow().SetBackground(GetDataWindow().GetControlBackground());
854 GetDataWindow().SetFillColor(GetDataWindow().GetControlBackground());
856 else
858 GetDataWindow().SetControlBackground();
859 GetDataWindow().SetBackground( rStyleSettings.GetFieldColor() );
860 GetDataWindow().SetFillColor( rStyleSettings.GetFieldColor() );
865 //------------------------------------------------------------------------------
866 sal_Bool EditBrowseBox::IsCursorMoveAllowed(long nNewRow, sal_uInt16 nNewColId) const
868 sal_uInt16 nInfo = 0;
870 if (GetSelectColumnCount() || (aMouseEvent.Is() && aMouseEvent->GetRow() < 0))
871 nInfo |= COLSELECT;
872 if ((GetSelection() != NULL && GetSelectRowCount()) ||
873 (aMouseEvent.Is() && aMouseEvent->GetColumnId() == HandleColumnId))
874 nInfo |= ROWSELECT;
875 if (!nInfo && nNewRow != nEditRow)
876 nInfo |= ROWCHANGE;
877 if (!nInfo && nNewColId != nEditCol)
878 nInfo |= COLCHANGE;
880 if (nInfo == 0) // nothing happened
881 return sal_True;
883 // save the cell content
884 if (IsEditing() && aController->IsModified() && !((EditBrowseBox *) this)->SaveModified())
886 // maybe we're not visible ...
887 EnableAndShow();
888 aController->GetWindow().GrabFocus();
889 return sal_False;
892 EditBrowseBox * pTHIS = const_cast<EditBrowseBox *> (this);
894 // save the cell content if
895 // a) a selection is beeing made
896 // b) the row is changing
897 if (IsModified() && (nInfo & (ROWCHANGE | COLSELECT | ROWSELECT)) &&
898 !pTHIS->SaveRow())
900 if (nInfo & COLSELECT ||
901 nInfo & ROWSELECT)
903 // cancel selected
904 pTHIS->SetNoSelection();
907 if (IsEditing())
909 if (!Controller()->GetWindow().IsVisible())
911 EnableAndShow();
913 aController->GetWindow().GrabFocus();
915 return sal_False;
918 if (nNewRow != nEditRow)
920 Window& rWindow = GetDataWindow();
921 if ((nEditRow >= 0) && (GetBrowserFlags() & EBBF_NO_HANDLE_COLUMN_CONTENT) == 0)
923 Rectangle aRect = GetFieldRectPixel(nEditRow, 0, sal_False );
924 // status cell should be painted if and only if text is displayed
925 // note: bPaintStatus is mutable, but Solaris has problems with assigning
926 // probably because it is part of a bitfield
927 pTHIS->bPaintStatus = static_cast< sal_Bool >
928 (( GetBrowserFlags() & EBBF_HANDLE_COLUMN_TEXT ) == EBBF_HANDLE_COLUMN_TEXT );
929 rWindow.Invalidate(aRect);
930 pTHIS->bPaintStatus = sal_True;
933 // don't paint during row change
934 rWindow.EnablePaint(sal_False);
936 // the last veto chance for derived classes
937 if (!pTHIS->CursorMoving(nNewRow, nNewColId))
939 pTHIS->InvalidateStatusCell(nEditRow);
940 rWindow.EnablePaint(sal_True);
941 return sal_False;
943 else
945 rWindow.EnablePaint(sal_True);
946 return sal_True;
949 else
950 return pTHIS->CursorMoving(nNewRow, nNewColId);
953 //------------------------------------------------------------------------------
954 void EditBrowseBox::ColumnMoved(sal_uInt16 nId)
956 BrowseBox::ColumnMoved(nId);
957 if (IsEditing())
959 Rectangle aRect( GetCellRect(nEditRow, nEditCol, sal_False));
960 CellControllerRef aControllerRef = Controller();
961 ResizeController(aControllerRef, aRect);
962 Controller()->GetWindow().GrabFocus();
966 //------------------------------------------------------------------------------
967 sal_Bool EditBrowseBox::SaveRow()
969 return sal_True;
972 //------------------------------------------------------------------------------
973 sal_Bool EditBrowseBox::CursorMoving(long, sal_uInt16)
975 ((EditBrowseBox *) this)->DeactivateCell(sal_False);
976 return sal_True;
979 //------------------------------------------------------------------------------
980 void EditBrowseBox::CursorMoved()
982 long nNewRow = GetCurRow();
983 if (nEditRow != nNewRow)
985 if ((GetBrowserFlags() & EBBF_NO_HANDLE_COLUMN_CONTENT) == 0)
986 InvalidateStatusCell(nNewRow);
987 nEditRow = nNewRow;
989 ActivateCell();
990 GetDataWindow().EnablePaint(sal_True);
991 // should not be called here because the descant event is not needed here
992 //BrowseBox::CursorMoved();
995 //------------------------------------------------------------------------------
996 void EditBrowseBox::EndScroll()
998 if (IsEditing())
1000 Rectangle aRect = GetCellRect(nEditRow, nEditCol, sal_False);
1001 ResizeController(aController,aRect);
1002 AsynchGetFocus();
1004 BrowseBox::EndScroll();
1007 //------------------------------------------------------------------------------
1008 void EditBrowseBox::ActivateCell(long nRow, sal_uInt16 nCol, sal_Bool bCellFocus)
1010 if (IsEditing())
1011 return;
1013 nEditCol = nCol;
1015 if ((GetSelectRowCount() && GetSelection() != NULL) || GetSelectColumnCount() ||
1016 (aMouseEvent.Is() && (aMouseEvent.IsDown() || aMouseEvent->GetClicks() > 1))) // nothing happens on MouseDown
1018 return;
1021 if (nEditRow >= 0 && nEditCol > HandleColumnId)
1023 aController = GetController(nRow, nCol);
1024 if (aController.Is())
1026 Rectangle aRect( GetCellRect(nEditRow, nEditCol, sal_False));
1027 ResizeController(aController, aRect);
1029 InitController(aController, nEditRow, nEditCol);
1031 aController->ClearModified();
1032 aController->SetModifyHdl(LINK(this,EditBrowseBox,ModifyHdl));
1033 EnableAndShow();
1035 if ( isAccessibleAlive() )
1036 implCreateActiveAccessible();
1038 // activate the cell only of the browser has the focus
1039 if ( bHasFocus && bCellFocus )
1040 AsynchGetFocus();
1042 else
1044 // no controller -> we have a new "active descendant"
1045 if ( isAccessibleAlive() && HasFocus() )
1047 commitTableEvent(
1048 ACTIVE_DESCENDANT_CHANGED,
1049 makeAny( CreateAccessibleCell( nRow, GetColumnPos( nCol ) ) ),
1050 Any()
1057 //------------------------------------------------------------------------------
1058 void EditBrowseBox::DeactivateCell(sal_Bool bUpdate)
1060 if (IsEditing())
1062 if ( isAccessibleAlive() )
1064 commitBrowseBoxEvent( CHILD, Any(), makeAny( m_aImpl->m_xActiveCell ) );
1065 m_aImpl->clearActiveCell();
1068 aOldController = aController;
1069 aController.Clear();
1071 // reset the modify handler
1072 aOldController->SetModifyHdl(Link());
1074 if (bHasFocus)
1075 GrabFocus(); // ensure that we have (and keep) the focus
1077 HideAndDisable(aOldController);
1079 // update if requested
1080 if (bUpdate)
1081 Update();
1083 nOldEditCol = nEditCol;
1084 nOldEditRow = nEditRow;
1086 // release the controller (asynchronously)
1087 if (nEndEvent)
1088 Application::RemoveUserEvent(nEndEvent);
1089 nEndEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,EndEditHdl));
1093 //------------------------------------------------------------------------------
1094 Rectangle EditBrowseBox::GetCellRect(long nRow, sal_uInt16 nColId, sal_Bool bRel) const
1096 Rectangle aRect( GetFieldRectPixel(nRow, nColId, bRel));
1097 if ((GetMode() & BROWSER_CURSOR_WO_FOCUS) == BROWSER_CURSOR_WO_FOCUS)
1099 aRect.Top() += 1;
1100 aRect.Bottom() -= 1;
1102 return aRect;
1105 //------------------------------------------------------------------------------
1106 IMPL_LINK_NOARG(EditBrowseBox, EndEditHdl)
1108 nEndEvent = 0;
1109 ReleaseController(aOldController, nOldEditRow, nOldEditCol);
1111 aOldController = CellControllerRef();
1112 nOldEditRow = -1;
1113 nOldEditCol = 0;
1115 return 0;
1118 //------------------------------------------------------------------------------
1119 IMPL_LINK_NOARG(EditBrowseBox, ModifyHdl)
1121 if (nCellModifiedEvent)
1122 Application::RemoveUserEvent(nCellModifiedEvent);
1123 nCellModifiedEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,CellModifiedHdl));
1124 return 0;
1127 //------------------------------------------------------------------------------
1128 IMPL_LINK_NOARG(EditBrowseBox, CellModifiedHdl)
1130 nCellModifiedEvent = 0;
1131 CellModified();
1132 return 0;
1135 //------------------------------------------------------------------------------
1136 void EditBrowseBox::ColumnResized( sal_uInt16 )
1138 if (IsEditing())
1140 Rectangle aRect( GetCellRect(nEditRow, nEditCol, sal_False));
1141 CellControllerRef aControllerRef = Controller();
1142 ResizeController(aControllerRef, aRect);
1143 Controller()->GetWindow().GrabFocus();
1147 //------------------------------------------------------------------------------
1148 sal_uInt16 EditBrowseBox::AppendColumn(const String& rName, sal_uInt16 nWidth, sal_uInt16 nPos, sal_uInt16 nId)
1150 if (nId == BROWSER_INVALIDID)
1152 // look for the next free id
1153 for (nId = ColCount(); nId > 0 && GetColumnPos(nId) != BROWSER_INVALIDID; nId--)
1156 if (!nId)
1158 // if there is no handle column
1159 // increment the id
1160 if ( ColCount() == 0 || GetColumnId(0) != HandleColumnId )
1161 nId = ColCount() + 1;
1165 DBG_ASSERT(nId, "EditBrowseBox::AppendColumn: invalid id!");
1167 long w = nWidth;
1168 if (!w)
1169 w = GetDefaultColumnWidth(rName);
1171 InsertDataColumn(nId, rName, w, (HIB_CENTER | HIB_VCENTER | HIB_CLICKABLE), nPos);
1172 return nId;
1175 //------------------------------------------------------------------------------
1176 void EditBrowseBox::Resize()
1178 BrowseBox::Resize();
1180 // if the window is smaller than "title line height" + "control area",
1181 // do nothing
1182 if (GetOutputSizePixel().Height() <
1183 (GetControlArea().GetHeight() + GetDataWindow().GetPosPixel().Y()))
1184 return;
1186 // the size of the control area
1187 Point aPoint(GetControlArea().TopLeft());
1188 sal_uInt16 nX = (sal_uInt16)aPoint.X();
1190 ArrangeControls(nX, (sal_uInt16)aPoint.Y());
1192 if (!nX)
1193 nX = USHRT_MAX;
1194 ReserveControlArea((sal_uInt16)nX);
1197 //------------------------------------------------------------------------------
1198 void EditBrowseBox::ArrangeControls(sal_uInt16&, sal_uInt16)
1202 //------------------------------------------------------------------------------
1203 CellController* EditBrowseBox::GetController(long, sal_uInt16)
1205 return NULL;
1208 //-----------------------------------------------------------------------------
1209 void EditBrowseBox::ResizeController(CellControllerRef& rController, const Rectangle& rRect)
1211 rController->GetWindow().SetPosSizePixel(rRect.TopLeft(), rRect.GetSize());
1214 //------------------------------------------------------------------------------
1215 void EditBrowseBox::InitController(CellControllerRef&, long, sal_uInt16)
1219 //------------------------------------------------------------------------------
1220 void EditBrowseBox::ReleaseController(CellControllerRef&, long, sal_uInt16)
1224 //------------------------------------------------------------------------------
1225 void EditBrowseBox::CellModified()
1230 //------------------------------------------------------------------------------
1231 sal_Bool EditBrowseBox::SaveModified()
1233 return sal_True;
1236 //------------------------------------------------------------------------------
1237 void EditBrowseBox::DoubleClick(const BrowserMouseEvent& rEvt)
1239 // when double clicking on the column, the optimum size will be calculated
1240 sal_uInt16 nColId = rEvt.GetColumnId();
1241 if (nColId != HandleColumnId)
1242 SetColumnWidth(nColId, GetAutoColumnWidth(nColId));
1245 //------------------------------------------------------------------------------
1246 sal_uInt32 EditBrowseBox::GetAutoColumnWidth(sal_uInt16 nColId)
1248 sal_uInt32 nCurColWidth = GetColumnWidth(nColId);
1249 sal_uInt32 nMinColWidth = CalcZoom(20); // minimum
1250 sal_uInt32 nNewColWidth = nMinColWidth;
1251 long nMaxRows = std::min(long(GetVisibleRows()), GetRowCount());
1252 long nLastVisRow = GetTopRow() + nMaxRows - 1;
1254 if (GetTopRow() <= nLastVisRow) // calc the column with using the cell contents
1256 for (long i = GetTopRow(); i <= nLastVisRow; ++i)
1257 nNewColWidth = std::max(nNewColWidth,GetTotalCellWidth(i,nColId) + 12);
1259 if (nNewColWidth == nCurColWidth) // size has not changed
1260 nNewColWidth = GetDefaultColumnWidth(GetColumnTitle(nColId));
1262 else
1263 nNewColWidth = GetDefaultColumnWidth(GetColumnTitle(nColId));
1264 return nNewColWidth;
1267 //------------------------------------------------------------------------------
1268 sal_uInt32 EditBrowseBox::GetTotalCellWidth(long, sal_uInt16)
1270 return 0;
1273 //------------------------------------------------------------------------------
1274 void EditBrowseBox::InvalidateHandleColumn()
1276 Rectangle aHdlFieldRect( GetFieldRectPixel( 0, 0 ));
1277 Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() );
1278 aInvalidRect.Right() = aHdlFieldRect.Right();
1279 Invalidate( aInvalidRect );
1282 //------------------------------------------------------------------------------
1283 void EditBrowseBox::PaintTristate(OutputDevice&, const Rectangle& rRect,const TriState& eState,sal_Bool _bEnabled) const
1285 pCheckBoxPaint->GetBox().SetState(eState);
1286 pCheckBoxPaint->SetPosSizePixel(rRect.TopLeft(), rRect.GetSize());
1288 // First update the parent, preventing that while painting this window
1289 // an update for the parent is done (because it's in the queue already)
1290 // which may lead to hiding this window immediately
1291 // #95598# comment out OJ
1292 /* if (pCheckBoxPaint->GetParent())
1293 pCheckBoxPaint->GetParent()->Update();
1295 pCheckBoxPaint->GetBox().Enable(_bEnabled);
1296 pCheckBoxPaint->Show();
1297 pCheckBoxPaint->SetParentUpdateMode( sal_False );
1298 pCheckBoxPaint->Update();
1299 pCheckBoxPaint->Hide();
1300 pCheckBoxPaint->SetParentUpdateMode( sal_True );
1303 //------------------------------------------------------------------------------
1304 void EditBrowseBox::AsynchGetFocus()
1306 if (nStartEvent)
1307 Application::RemoveUserEvent(nStartEvent);
1309 m_pFocusWhileRequest = Application::GetFocusWindow();
1310 nStartEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,StartEditHdl));
1313 //------------------------------------------------------------------------------
1314 void EditBrowseBox::SetBrowserFlags(sal_Int32 nFlags)
1316 if (m_nBrowserFlags == nFlags)
1317 return;
1319 sal_Bool RowPicturesChanges = ((m_nBrowserFlags & EBBF_NO_HANDLE_COLUMN_CONTENT) !=
1320 (nFlags & EBBF_NO_HANDLE_COLUMN_CONTENT));
1321 m_nBrowserFlags = nFlags;
1323 if (RowPicturesChanges)
1324 InvalidateStatusCell(GetCurRow());
1326 //------------------------------------------------------------------------------
1327 inline void EditBrowseBox::HideAndDisable(CellControllerRef& rController)
1329 rController->suspend();
1331 //------------------------------------------------------------------------------
1332 inline void EditBrowseBox::EnableAndShow() const
1334 Controller()->resume();
1336 //===============================================================================
1338 DBG_NAME(CellController);
1339 //------------------------------------------------------------------------------
1340 CellController::CellController(Control* pW)
1341 :pWindow( pW )
1342 ,bSuspended( sal_True )
1344 DBG_CTOR(CellController,NULL);
1346 DBG_ASSERT(pWindow, "CellController::CellController: missing the window!");
1347 DBG_ASSERT(!pWindow->IsVisible(), "CellController::CellController: window should not be visible!");
1350 //-----------------------------------------------------------------------------
1351 CellController::~CellController()
1354 DBG_DTOR(CellController,NULL);
1357 //-----------------------------------------------------------------------------
1358 void CellController::suspend( )
1360 DBG_ASSERT( bSuspended == !GetWindow().IsVisible(), "CellController::suspend: inconsistence!" );
1361 if ( !isSuspended( ) )
1363 CommitModifications();
1364 GetWindow().Hide( );
1365 GetWindow().Disable( );
1366 bSuspended = sal_True;
1370 //-----------------------------------------------------------------------------
1371 void CellController::resume( )
1373 DBG_ASSERT( bSuspended == !GetWindow().IsVisible(), "CellController::resume: inconsistence!" );
1374 if ( isSuspended( ) )
1376 GetWindow().Enable( );
1377 GetWindow().Show( );
1378 bSuspended = sal_False;
1382 //-----------------------------------------------------------------------------
1383 void CellController::CommitModifications()
1385 // nothing to do in this base class
1388 //-----------------------------------------------------------------------------
1389 sal_Bool CellController::WantMouseEvent() const
1391 return sal_False;
1394 //-----------------------------------------------------------------------------
1395 void CellController::SetModified()
1399 //-----------------------------------------------------------------------------
1400 sal_Bool CellController::MoveAllowed(const KeyEvent&) const
1402 return sal_True;
1404 // .......................................................................
1405 } // namespace svt
1406 // .......................................................................
1408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */