1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <vcl/settings.hxx>
32 #include <svtools/svtresid.hxx>
34 #include <svtools/svtools.hrc>
37 #include <tools/multisel.hxx>
38 #include "editbrowseboximpl.hxx"
39 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
40 #include <com/sun/star/accessibility/XAccessible.hpp>
41 #include <comphelper/types.hxx>
50 sal_uInt16
getRealGetFocusFlags( vcl::Window
* _pWindow
)
52 sal_uInt16 nFlags
= 0;
53 while ( _pWindow
&& !nFlags
)
55 nFlags
= _pWindow
->GetGetFocusFlags( );
56 _pWindow
= _pWindow
->GetParent();
62 using namespace ::com::sun::star::uno
;
63 using namespace com::sun::star::accessibility::AccessibleEventId
;
64 using com::sun::star::accessibility::XAccessible
;
67 IEditImplementation::~IEditImplementation()
75 void EditBrowserHeader::DoubleClick()
77 sal_uInt16 nColId
= GetCurItemId();
80 sal_uInt32 nAutoWidth
= static_cast<EditBrowseBox
*>(GetParent())->GetAutoColumnWidth(nColId
);
81 if (nAutoWidth
!= static_cast<EditBrowseBox
*>(GetParent())->GetColumnWidth(nColId
))
83 static_cast<EditBrowseBox
*>(GetParent())->SetColumnWidth(nColId
, nAutoWidth
);
84 static_cast<EditBrowseBox
*>(GetParent())->ColumnResized(nColId
);
94 void EditBrowseBox::BrowserMouseEventPtr::Clear()
100 void EditBrowseBox::BrowserMouseEventPtr::Set(const BrowserMouseEvent
* pEvt
, bool bIsDown
)
110 pEvent
= new BrowserMouseEvent(pEvt
->GetWindow(),
121 void EditBrowseBox::impl_construct()
123 m_aImpl
.reset(new EditBrowseBoxImpl());
125 SetCompoundControl(true);
126 SetGridLineColor( Color( COL_LIGHTGRAY
) );
128 ImplInitSettings(true, true, true);
130 pCheckBoxPaint
= VclPtr
<CheckBoxControl
>::Create(&GetDataWindow());
131 pCheckBoxPaint
->SetPaintTransparent( true );
132 pCheckBoxPaint
->SetBackground();
136 EditBrowseBox::EditBrowseBox(vcl::Window
* pParent
, const ResId
& rId
, EditBrowseBoxFlags nBrowserFlags
, BrowserMode _nMode
)
137 :BrowseBox( pParent
, rId
, _nMode
)
140 ,nCellModifiedEvent(0)
141 ,m_pFocusWhileRequest(0)
149 ,bActiveBeforeTracking( false )
150 ,m_nBrowserFlags(nBrowserFlags
)
157 EditBrowseBox::EditBrowseBox( vcl::Window
* pParent
, EditBrowseBoxFlags nBrowserFlags
, WinBits nBits
, BrowserMode _nMode
)
158 :BrowseBox( pParent
, nBits
, _nMode
)
161 ,nCellModifiedEvent(0)
162 ,m_pFocusWhileRequest(0)
170 ,bActiveBeforeTracking( false )
171 ,m_nBrowserFlags(nBrowserFlags
)
178 void EditBrowseBox::Init()
184 EditBrowseBox::~EditBrowseBox()
189 void EditBrowseBox::dispose()
192 Application::RemoveUserEvent(nStartEvent
);
194 Application::RemoveUserEvent(nEndEvent
);
195 if (nCellModifiedEvent
)
196 Application::RemoveUserEvent(nCellModifiedEvent
);
198 pCheckBoxPaint
.disposeAndClear();
199 m_pFocusWhileRequest
.clear();
201 BrowseBox::dispose();
205 void EditBrowseBox::RemoveRows()
208 nOldEditRow
= nEditRow
= nPaintRow
= -1;
209 nEditCol
= nOldEditCol
= 0;
213 VclPtr
<BrowserHeader
> EditBrowseBox::CreateHeaderBar(BrowseBox
* pParent
)
215 pHeader
= imp_CreateHeaderBar(pParent
);
217 pHeader
->SetUpdateMode(false);
222 VclPtr
<BrowserHeader
> EditBrowseBox::imp_CreateHeaderBar(BrowseBox
* pParent
)
224 return VclPtr
<EditBrowserHeader
>::Create(pParent
);
228 void EditBrowseBox::LoseFocus()
230 BrowseBox::LoseFocus();
235 void EditBrowseBox::GetFocus()
237 BrowseBox::GetFocus();
239 // This should handle the case that the BrowseBox (or one of its children)
240 // gets the focus from outside by pressing Tab
241 if (IsEditing() && Controller()->GetWindow().IsVisible())
242 Controller()->GetWindow().GrabFocus();
244 DetermineFocus( getRealGetFocusFlags( this ) );
248 bool EditBrowseBox::SeekRow(long nRow
)
255 IMPL_LINK_NOARG(EditBrowseBox
, StartEditHdl
)
261 if (!aController
->GetWindow().HasFocus() && (m_pFocusWhileRequest
.get() == Application::GetFocusWindow()))
262 aController
->GetWindow().GrabFocus();
268 void EditBrowseBox::PaintField( OutputDevice
& rDev
, const Rectangle
& rRect
,
269 sal_uInt16 nColumnId
) const
271 if (nColumnId
== HandleColumnId
)
274 PaintStatusCell(rDev
, rRect
);
278 // don't paint the current cell
279 if (&rDev
== &GetDataWindow())
280 // but only if we're painting onto our data win (which is the usual painting)
281 if (nPaintRow
== nEditRow
)
283 if (IsEditing() && nEditCol
== nColumnId
&& aController
->GetWindow().IsVisible())
286 PaintCell(rDev
, rRect
, nColumnId
);
291 Image
EditBrowseBox::GetImage(RowStatus eStatus
) const
293 if ( !m_aStatusImages
.GetImageCount() )
295 const_cast<EditBrowseBox
*>(this)->m_aStatusImages
= ImageList( SvtResId( RID_SVTOOLS_IMAGELIST_EDITBROWSEBOX
) );
299 bool bNeedMirror
= IsRTLEnabled();
303 aImage
= m_aStatusImages
.GetImage(IMG_EBB_CURRENT
);
306 aImage
= m_aStatusImages
.GetImage(IMG_EBB_CURRENTNEW
);
309 aImage
= m_aStatusImages
.GetImage(IMG_EBB_MODIFIED
);
310 bNeedMirror
= false; // the pen is not mirrored
313 aImage
= m_aStatusImages
.GetImage(IMG_EBB_NEW
);
316 aImage
= m_aStatusImages
.GetImage(IMG_EBB_DELETED
);
319 aImage
= m_aStatusImages
.GetImage(IMG_EBB_PRIMARYKEY
);
321 case CURRENT_PRIMARYKEY
:
322 aImage
= m_aStatusImages
.GetImage(IMG_EBB_CURRENT_PRIMARYKEY
);
325 aImage
= m_aStatusImages
.GetImage(IMG_EBB_FILTER
);
328 aImage
= m_aStatusImages
.GetImage(IMG_EBB_HEADERFOOTER
);
335 BitmapEx
aBitmap( aImage
.GetBitmapEx() );
336 aBitmap
.Mirror( BmpMirrorFlags::Horizontal
);
337 aImage
= Image( aBitmap
);
343 void EditBrowseBox::PaintStatusCell(OutputDevice
& rDev
, const Rectangle
& rRect
) const
348 RowStatus eStatus
= GetRowStatus( nPaintRow
);
349 EditBrowseBoxFlags nBrowserFlags
= GetBrowserFlags();
351 if (nBrowserFlags
& EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
)
354 // draw the text of the header column
355 if (nBrowserFlags
& EditBrowseBoxFlags::HANDLE_COLUMN_TEXT
)
357 rDev
.DrawText( rRect
, GetCellText( nPaintRow
, 0 ),
358 DrawTextFlags::Center
| DrawTextFlags::VCenter
| DrawTextFlags::Clip
);
361 else if (eStatus
!= CLEAN
&& rDev
.GetOutDevType() == OUTDEV_WINDOW
)
363 Image
aImage(GetImage(eStatus
));
364 // calc the image position
365 Size
aImageSize(aImage
.GetSizePixel());
366 aImageSize
.Width() = CalcZoom(aImageSize
.Width());
367 aImageSize
.Height() = CalcZoom(aImageSize
.Height());
368 Point
aPos( rRect
.TopLeft() );
370 if ( ( aImageSize
.Width() > rRect
.GetWidth() ) || ( aImageSize
.Height() > rRect
.GetHeight() ) )
371 rDev
.SetClipRegion(vcl::Region(rRect
));
373 if ( aImageSize
.Width() < rRect
.GetWidth() )
374 aPos
.X() += ( rRect
.GetWidth() - aImageSize
.Width() ) / 2;
376 if ( aImageSize
.Height() < rRect
.GetHeight() )
377 aPos
.Y() += ( rRect
.GetHeight() - aImageSize
.Height() ) / 2;
380 rDev
.DrawImage( aPos
, aImageSize
, aImage
);
382 rDev
.DrawImage( aPos
, aImage
);
384 if (rDev
.IsClipRegion())
385 rDev
.SetClipRegion();
390 void EditBrowseBox::ImplStartTracking()
392 bActiveBeforeTracking
= IsEditing();
393 if ( bActiveBeforeTracking
)
399 BrowseBox::ImplStartTracking();
403 void EditBrowseBox::ImplTracking()
405 BrowseBox::ImplTracking();
409 void EditBrowseBox::ImplEndTracking()
411 if ( bActiveBeforeTracking
)
413 bActiveBeforeTracking
= false;
415 BrowseBox::ImplEndTracking();
419 void EditBrowseBox::RowHeightChanged()
423 Rectangle
aRect( GetCellRect( nEditRow
, nEditCol
, false ) );
424 CellControllerRef
aCellController( Controller() );
425 ResizeController( aCellController
, aRect
);
426 aCellController
->GetWindow().GrabFocus();
429 BrowseBox::RowHeightChanged();
433 EditBrowseBox::RowStatus
EditBrowseBox::GetRowStatus(long) const
439 void EditBrowseBox::KeyInput( const KeyEvent
& rEvt
)
441 sal_uInt16 nCode
= rEvt
.GetKeyCode().GetCode();
442 bool bShift
= rEvt
.GetKeyCode().IsShift();
443 bool bCtrl
= rEvt
.GetKeyCode().IsMod1();
448 if (!bCtrl
&& !bShift
&& IsTabAllowed(true))
450 Dispatch(BROWSER_CURSORRIGHT
);
453 BrowseBox::KeyInput(rEvt
);
456 if (!bCtrl
&& !bShift
)
458 if (IsTabAllowed(true))
459 Dispatch(BROWSER_CURSORRIGHT
);
461 // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now
462 // that tab isn't allowed here. So give the Control class a chance
463 Control::KeyInput(rEvt
);
466 else if (!bCtrl
&& bShift
)
468 if (IsTabAllowed(false))
469 Dispatch(BROWSER_CURSORLEFT
);
471 // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now
472 // that tab isn't allowed here. So give the Control class a chance
473 Control::KeyInput(rEvt
);
478 BrowseBox::KeyInput(rEvt
);
483 void EditBrowseBox::MouseButtonDown(const BrowserMouseEvent
& rEvt
)
485 // absorb double clicks
486 if (rEvt
.GetClicks() > 1 && rEvt
.GetRow() >= 0)
489 // we are about to leave the current cell. If there is a "this cell has been modified" notification
490 // pending (asynchronously), this may be deadly -> do it synchronously
491 if ( nCellModifiedEvent
)
493 Application::RemoveUserEvent( nCellModifiedEvent
);
494 nCellModifiedEvent
= 0;
495 LINK( this, EditBrowseBox
, CellModifiedHdl
).Call( NULL
);
498 if (rEvt
.GetColumnId() == HandleColumnId
)
499 { // it was the handle column. save the current cell content if necessary
500 // (clicking on the handle column results in selecting the current row)
501 if (IsEditing() && aController
->IsModified())
505 aMouseEvent
.Set(&rEvt
,true);
506 BrowseBox::MouseButtonDown(rEvt
);
509 if (m_nBrowserFlags
& EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN
)
511 // the base class does not travel upon MouseButtonDown, but implActivateCellOnMouseEvent assumes we traveled ...
512 GoToRowColumnId( rEvt
.GetRow(), rEvt
.GetColumnId() );
513 if (rEvt
.GetRow() >= 0)
514 implActivateCellOnMouseEvent(rEvt
, false);
519 void EditBrowseBox::MouseButtonUp( const BrowserMouseEvent
& rEvt
)
521 // absorb double clicks
522 if (rEvt
.GetClicks() > 1 && rEvt
.GetRow() >= 0)
525 aMouseEvent
.Set(&rEvt
,false);
526 BrowseBox::MouseButtonUp(rEvt
);
529 if (!(m_nBrowserFlags
& EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN
))
530 if (rEvt
.GetRow() >= 0)
531 implActivateCellOnMouseEvent(rEvt
, true);
535 void EditBrowseBox::implActivateCellOnMouseEvent(const BrowserMouseEvent
& _rEvt
, bool _bUp
)
539 else if (IsEditing() && !aController
->GetWindow().IsEnabled())
541 else if (IsEditing() && !aController
->GetWindow().HasChildPathFocus())
544 if (IsEditing() && aController
->GetWindow().IsEnabled() && aController
->WantMouseEvent())
545 { // forwards the event to the control
547 // If the field has been moved previously, we have to adjust the position
549 aController
->GetWindow().GrabFocus();
551 // the position of the event relative to the controller's window
552 Point aPos
= _rEvt
.GetPosPixel() - _rEvt
.GetRect().TopLeft();
553 // the (child) window which should really get the event
554 vcl::Window
* pRealHandler
= aController
->GetWindow().FindWindow(aPos
);
556 // the coords relative to this real handler
557 aPos
-= pRealHandler
->GetPosPixel();
559 pRealHandler
= &aController
->GetWindow();
562 MouseEvent
aEvent(aPos
, _rEvt
.GetClicks(), _rEvt
.GetMode(),
564 _rEvt
.GetModifier());
566 pRealHandler
->MouseButtonDown(aEvent
);
568 pRealHandler
->MouseButtonUp(aEvent
);
570 vcl::Window
*pWin
= &aController
->GetWindow();
571 if (!pWin
->IsTracking())
573 for (pWin
= pWin
->GetWindow(GetWindowType::FirstChild
);
574 pWin
&& !pWin
->IsTracking();
575 pWin
= pWin
->GetWindow(GetWindowType::Next
))
579 if (pWin
&& pWin
->IsTracking())
585 void EditBrowseBox::Dispatch( sal_uInt16 _nId
)
587 if ( _nId
== BROWSER_ENHANCESELECTION
)
588 { // this is a workaround for the bug in the base class:
589 // if the row selection is to be extended (which is what BROWSER_ENHANCESELECTION tells us)
590 // then the base class does not revert any column selections, while, for doing a "simple"
591 // selection (BROWSER_SELECT), it does. In fact, it does not only revert the col selection then,
592 // but also any current row selections.
593 // This clearly tells me that the both ids are for row selection only - there this behaviour does
595 // But here, where we have column selection, too, we take care of this ourself.
596 if ( GetSelectColumnCount( ) )
598 while ( GetSelectColumnCount( ) )
600 sal::static_int_cast
< sal_uInt16
>(FirstSelectedColumn()),
605 BrowseBox::Dispatch( _nId
);
608 bool EditBrowseBox::PreNotify(NotifyEvent
& rEvt
)
610 if (rEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
612 if ( (IsEditing() && Controller()->GetWindow().HasChildPathFocus())
613 || rEvt
.GetWindow() == &GetDataWindow()
614 || (!IsEditing() && HasChildPathFocus())
617 const KeyEvent
* pKeyEvent
= rEvt
.GetKeyEvent();
618 sal_uInt16 nCode
= pKeyEvent
->GetKeyCode().GetCode();
619 bool bShift
= pKeyEvent
->GetKeyCode().IsShift();
620 bool bCtrl
= pKeyEvent
->GetKeyCode().IsMod1();
621 bool bAlt
= pKeyEvent
->GetKeyCode().IsMod2();
622 bool bLocalSelect
= false;
623 bool bNonEditOnly
= false;
624 sal_uInt16 nId
= BROWSER_NONE
;
626 if (!bAlt
&& !bCtrl
&& !bShift
)
629 case KEY_DOWN
: nId
= BROWSER_CURSORDOWN
; break;
630 case KEY_UP
: nId
= BROWSER_CURSORUP
; break;
631 case KEY_PAGEDOWN
: nId
= BROWSER_CURSORPAGEDOWN
; break;
632 case KEY_PAGEUP
: nId
= BROWSER_CURSORPAGEUP
; break;
633 case KEY_HOME
: nId
= BROWSER_CURSORHOME
; break;
634 case KEY_END
: nId
= BROWSER_CURSOREND
; break;
637 // ask if traveling to the next cell is allowed
638 if (IsTabAllowed(true))
639 nId
= BROWSER_CURSORRIGHT
;
643 // save the cell content (if necessary)
644 if (IsEditing() && aController
->IsModified() && !SaveModified())
646 // maybe we're not visible ...
648 aController
->GetWindow().GrabFocus();
651 // ask if traveling to the next cell is allowed
652 if (IsTabAllowed(true))
653 nId
= BROWSER_CURSORRIGHT
;
656 case KEY_RIGHT
: nId
= BROWSER_CURSORRIGHT
; break;
657 case KEY_LEFT
: nId
= BROWSER_CURSORLEFT
; break;
658 case KEY_SPACE
: nId
= BROWSER_SELECT
; bNonEditOnly
= bLocalSelect
= true; break;
661 if ( !bAlt
&& !bCtrl
&& bShift
)
664 case KEY_DOWN
: nId
= BROWSER_SELECTDOWN
; bLocalSelect
= true; break;
665 case KEY_UP
: nId
= BROWSER_SELECTUP
; bLocalSelect
= true; break;
666 case KEY_HOME
: nId
= BROWSER_SELECTHOME
; bLocalSelect
= true; break;
667 case KEY_END
: nId
= BROWSER_SELECTEND
; bLocalSelect
= true; break;
669 if (IsTabAllowed(false))
670 nId
= BROWSER_CURSORLEFT
;
674 if ( !bAlt
&& bCtrl
&& bShift
)
677 case KEY_SPACE
: nId
= BROWSER_SELECTCOLUMN
; bLocalSelect
= true; break;
681 if ( !bAlt
&& bCtrl
&& !bShift
)
684 case KEY_DOWN
: nId
= BROWSER_SCROLLUP
; break;
685 case KEY_UP
: nId
= BROWSER_SCROLLDOWN
; break;
686 case KEY_PAGEDOWN
: nId
= BROWSER_CURSORENDOFFILE
; break;
687 case KEY_PAGEUP
: nId
= BROWSER_CURSORTOPOFFILE
; break;
688 case KEY_HOME
: nId
= BROWSER_CURSORTOPOFSCREEN
; break;
689 case KEY_END
: nId
= BROWSER_CURSORENDOFSCREEN
; break;
690 case KEY_SPACE
: nId
= BROWSER_ENHANCESELECTION
; bLocalSelect
= true; break;
694 if ( ( nId
!= BROWSER_NONE
)
697 && aController
->MoveAllowed( *pKeyEvent
)
702 if (nId
== BROWSER_SELECT
|| BROWSER_SELECTCOLUMN
== nId
)
704 // save the cell content (if necessary)
705 if (IsEditing() && aController
->IsModified() && !SaveModified())
707 // maybe we're not visible ...
709 aController
->GetWindow().GrabFocus();
716 if (bLocalSelect
&& (GetSelectRowCount() || GetSelection() != NULL
))
722 return BrowseBox::PreNotify(rEvt
);
725 bool EditBrowseBox::IsTabAllowed(bool) const
731 bool EditBrowseBox::Notify(NotifyEvent
& rEvt
)
733 switch (rEvt
.GetType())
735 case MouseNotifyEvent::GETFOCUS
:
736 DetermineFocus( getRealGetFocusFlags( this ) );
739 case MouseNotifyEvent::LOSEFOCUS
:
746 return BrowseBox::Notify(rEvt
);
750 void EditBrowseBox::StateChanged( StateChangedType nType
)
752 BrowseBox::StateChanged( nType
);
754 bool bNeedCellReActivation
= false;
755 if ( nType
== StateChangedType::Mirroring
)
757 bNeedCellReActivation
= true;
759 else if ( nType
== StateChangedType::Zoom
)
761 ImplInitSettings( true, false, false );
762 bNeedCellReActivation
= true;
764 else if ( nType
== StateChangedType::ControlFont
)
766 ImplInitSettings( true, false, false );
769 else if ( nType
== StateChangedType::ControlForeground
)
771 ImplInitSettings( false, true, false );
774 else if ( nType
== StateChangedType::ControlBackground
)
776 ImplInitSettings( false, false, true );
779 else if (nType
== StateChangedType::Style
)
781 WinBits nStyle
= GetStyle();
782 if (!(nStyle
& WB_NOTABSTOP
) )
783 nStyle
|= WB_TABSTOP
;
787 if ( bNeedCellReActivation
)
798 void EditBrowseBox::DataChanged( const DataChangedEvent
& rDCEvt
)
800 BrowseBox::DataChanged( rDCEvt
);
802 if ((( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) ||
803 ( rDCEvt
.GetType() == DataChangedEventType::DISPLAY
)) &&
804 ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
806 ImplInitSettings( true, true, true );
811 void EditBrowseBox::ImplInitSettings( bool bFont
, bool bForeground
, bool bBackground
)
813 const StyleSettings
& rStyleSettings
= GetSettings().GetStyleSettings();
817 GetDataWindow().ApplyControlFont(GetDataWindow(), rStyleSettings
.GetFieldFont());
820 if (bFont
|| bForeground
)
822 GetDataWindow().ApplyControlForeground(GetDataWindow(), rStyleSettings
.GetFieldTextColor());
825 if (bBackground
) // FIXME: Outside of Paint Hierarchy
827 if (GetDataWindow().IsControlBackground())
829 GetDataWindow().SetControlBackground(GetControlBackground());
830 GetDataWindow().SetBackground(GetDataWindow().GetControlBackground());
831 GetDataWindow().SetFillColor(GetDataWindow().GetControlBackground());
835 GetDataWindow().SetControlBackground();
836 GetDataWindow().SetBackground(rStyleSettings
.GetFieldColor());
837 GetDataWindow().SetFillColor(rStyleSettings
.GetFieldColor());
843 bool EditBrowseBox::IsCursorMoveAllowed(long nNewRow
, sal_uInt16 nNewColId
) const
845 sal_uInt16 nInfo
= 0;
847 if (GetSelectColumnCount() || (aMouseEvent
.Is() && aMouseEvent
->GetRow() < 0))
849 if ((GetSelection() != NULL
&& GetSelectRowCount()) ||
850 (aMouseEvent
.Is() && aMouseEvent
->GetColumnId() == HandleColumnId
))
852 if (!nInfo
&& nNewRow
!= nEditRow
)
854 if (!nInfo
&& nNewColId
!= nEditCol
)
857 if (nInfo
== 0) // nothing happened
860 // save the cell content
861 if (IsEditing() && aController
->IsModified() && !const_cast<EditBrowseBox
*>(this)->SaveModified())
863 // maybe we're not visible ...
865 aController
->GetWindow().GrabFocus();
869 EditBrowseBox
* pTHIS
= const_cast<EditBrowseBox
*> (this);
871 // save the cell content if
872 // a) a selection is being made
873 // b) the row is changing
874 if (IsModified() && (nInfo
& (ROWCHANGE
| COLSELECT
| ROWSELECT
)) &&
877 if (nInfo
& COLSELECT
||
881 pTHIS
->SetNoSelection();
886 if (!Controller()->GetWindow().IsVisible())
890 aController
->GetWindow().GrabFocus();
895 if (nNewRow
!= nEditRow
)
897 vcl::Window
& rWindow
= GetDataWindow();
898 if ((nEditRow
>= 0) && !(GetBrowserFlags() & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
))
900 Rectangle aRect
= GetFieldRectPixel(nEditRow
, 0, false );
901 // status cell should be painted if and only if text is displayed
902 // note: bPaintStatus is mutable, but Solaris has problems with assigning
903 // probably because it is part of a bitfield
904 pTHIS
->bPaintStatus
= ( GetBrowserFlags() & EditBrowseBoxFlags::HANDLE_COLUMN_TEXT
) == EditBrowseBoxFlags::HANDLE_COLUMN_TEXT
;
905 rWindow
.Invalidate(aRect
);
906 pTHIS
->bPaintStatus
= true;
909 // don't paint during row change
910 rWindow
.EnablePaint(false);
912 // the last veto chance for derived classes
913 if (!pTHIS
->CursorMoving(nNewRow
, nNewColId
))
915 pTHIS
->InvalidateStatusCell(nEditRow
);
916 rWindow
.EnablePaint(true);
921 rWindow
.EnablePaint(true);
926 return pTHIS
->CursorMoving(nNewRow
, nNewColId
);
930 void EditBrowseBox::ColumnMoved(sal_uInt16 nId
)
932 BrowseBox::ColumnMoved(nId
);
935 Rectangle
aRect( GetCellRect(nEditRow
, nEditCol
, false));
936 CellControllerRef aControllerRef
= Controller();
937 ResizeController(aControllerRef
, aRect
);
938 Controller()->GetWindow().GrabFocus();
943 bool EditBrowseBox::SaveRow()
949 bool EditBrowseBox::CursorMoving(long, sal_uInt16
)
951 DeactivateCell(false);
956 void EditBrowseBox::CursorMoved()
958 long nNewRow
= GetCurRow();
959 if (nEditRow
!= nNewRow
)
961 if (!(GetBrowserFlags() & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
))
962 InvalidateStatusCell(nNewRow
);
966 GetDataWindow().EnablePaint(true);
967 // should not be called here because the descant event is not needed here
968 //BrowseBox::CursorMoved();
972 void EditBrowseBox::EndScroll()
976 Rectangle aRect
= GetCellRect(nEditRow
, nEditCol
, false);
977 ResizeController(aController
,aRect
);
980 BrowseBox::EndScroll();
984 void EditBrowseBox::ActivateCell(long nRow
, sal_uInt16 nCol
, bool bCellFocus
)
991 if ((GetSelectRowCount() && GetSelection() != NULL
) || GetSelectColumnCount() ||
992 (aMouseEvent
.Is() && (aMouseEvent
.IsDown() || aMouseEvent
->GetClicks() > 1))) // nothing happens on MouseDown
997 if (nEditRow
>= 0 && nEditCol
> HandleColumnId
)
999 aController
= GetController(nRow
, nCol
);
1000 if (aController
.Is())
1002 Rectangle
aRect( GetCellRect(nEditRow
, nEditCol
, false));
1003 ResizeController(aController
, aRect
);
1005 InitController(aController
, nEditRow
, nEditCol
);
1007 aController
->ClearModified();
1008 aController
->SetModifyHdl(LINK(this,EditBrowseBox
,ModifyHdl
));
1011 if ( isAccessibleAlive() )
1012 implCreateActiveAccessible();
1014 // activate the cell only of the browser has the focus
1015 if ( bHasFocus
&& bCellFocus
)
1020 // no controller -> we have a new "active descendant"
1021 if ( isAccessibleAlive() && HasFocus() )
1024 ACTIVE_DESCENDANT_CHANGED
,
1025 makeAny( CreateAccessibleCell( nRow
, GetColumnPos( nCol
-1) ) ),
1034 void EditBrowseBox::DeactivateCell(bool bUpdate
)
1038 if ( isAccessibleAlive() )
1040 commitBrowseBoxEvent( CHILD
, Any(), makeAny( m_aImpl
->m_xActiveCell
) );
1041 m_aImpl
->clearActiveCell();
1044 aOldController
= aController
;
1045 aController
.Clear();
1047 // reset the modify handler
1048 aOldController
->SetModifyHdl(Link
<>());
1051 GrabFocus(); // ensure that we have (and keep) the focus
1053 HideAndDisable(aOldController
);
1055 // update if requested
1059 nOldEditCol
= nEditCol
;
1060 nOldEditRow
= nEditRow
;
1062 // release the controller (asynchronously)
1064 Application::RemoveUserEvent(nEndEvent
);
1065 nEndEvent
= Application::PostUserEvent(LINK(this,EditBrowseBox
,EndEditHdl
), NULL
, true);
1070 Rectangle
EditBrowseBox::GetCellRect(long nRow
, sal_uInt16 nColId
, bool bRel
) const
1072 Rectangle
aRect( GetFieldRectPixel(nRow
, nColId
, bRel
));
1073 if ((GetMode() & BrowserMode::CURSOR_WO_FOCUS
) == BrowserMode::CURSOR_WO_FOCUS
)
1076 aRect
.Bottom() -= 1;
1082 IMPL_LINK_NOARG(EditBrowseBox
, EndEditHdl
)
1085 ReleaseController(aOldController
, nOldEditRow
, nOldEditCol
);
1087 aOldController
= CellControllerRef();
1095 IMPL_LINK_NOARG(EditBrowseBox
, ModifyHdl
)
1097 if (nCellModifiedEvent
)
1098 Application::RemoveUserEvent(nCellModifiedEvent
);
1099 nCellModifiedEvent
= Application::PostUserEvent(LINK(this,EditBrowseBox
,CellModifiedHdl
), NULL
, true);
1104 IMPL_LINK_NOARG(EditBrowseBox
, CellModifiedHdl
)
1106 nCellModifiedEvent
= 0;
1112 void EditBrowseBox::ColumnResized( sal_uInt16
)
1116 Rectangle
aRect( GetCellRect(nEditRow
, nEditCol
, false));
1117 CellControllerRef aControllerRef
= Controller();
1118 ResizeController(aControllerRef
, aRect
);
1119 Controller()->GetWindow().GrabFocus();
1124 sal_uInt16
EditBrowseBox::AppendColumn(const OUString
& rName
, sal_uInt16 nWidth
, sal_uInt16 nPos
, sal_uInt16 nId
)
1126 if (nId
== BROWSER_INVALIDID
)
1128 // look for the next free id
1129 for (nId
= ColCount(); nId
> 0 && GetColumnPos(nId
) != BROWSER_INVALIDID
; nId
--)
1134 // if there is no handle column
1136 if ( ColCount() == 0 || GetColumnId(0) != HandleColumnId
)
1137 nId
= ColCount() + 1;
1141 DBG_ASSERT(nId
, "EditBrowseBox::AppendColumn: invalid id!");
1145 w
= GetDefaultColumnWidth(rName
);
1147 InsertDataColumn(nId
, rName
, w
, (HeaderBarItemBits::CENTER
| HeaderBarItemBits::VCENTER
| HeaderBarItemBits::CLICKABLE
), nPos
);
1152 void EditBrowseBox::Resize()
1154 BrowseBox::Resize();
1156 // if the window is smaller than "title line height" + "control area",
1158 if (GetOutputSizePixel().Height() <
1159 (GetControlArea().GetHeight() + GetDataWindow().GetPosPixel().Y()))
1162 // the size of the control area
1163 Point
aPoint(GetControlArea().TopLeft());
1164 sal_uInt16 nX
= (sal_uInt16
)aPoint
.X();
1166 ArrangeControls(nX
, (sal_uInt16
)aPoint
.Y());
1170 ReserveControlArea((sal_uInt16
)nX
);
1174 void EditBrowseBox::ArrangeControls(sal_uInt16
&, sal_uInt16
)
1179 CellController
* EditBrowseBox::GetController(long, sal_uInt16
)
1185 void EditBrowseBox::ResizeController(CellControllerRef
& rController
, const Rectangle
& rRect
)
1187 rController
->GetWindow().SetPosSizePixel(rRect
.TopLeft(), rRect
.GetSize());
1191 void EditBrowseBox::InitController(CellControllerRef
&, long, sal_uInt16
)
1196 void EditBrowseBox::ReleaseController(CellControllerRef
&, long, sal_uInt16
)
1201 void EditBrowseBox::CellModified()
1207 bool EditBrowseBox::SaveModified()
1213 void EditBrowseBox::DoubleClick(const BrowserMouseEvent
& rEvt
)
1215 // when double clicking on the column, the optimum size will be calculated
1216 sal_uInt16 nColId
= rEvt
.GetColumnId();
1217 if (nColId
!= HandleColumnId
)
1218 SetColumnWidth(nColId
, GetAutoColumnWidth(nColId
));
1222 sal_uInt32
EditBrowseBox::GetAutoColumnWidth(sal_uInt16 nColId
)
1224 sal_uInt32 nCurColWidth
= GetColumnWidth(nColId
);
1225 sal_uInt32 nMinColWidth
= CalcZoom(20); // minimum
1226 sal_uInt32 nNewColWidth
= nMinColWidth
;
1227 long nMaxRows
= std::min(long(GetVisibleRows()), GetRowCount());
1228 long nLastVisRow
= GetTopRow() + nMaxRows
- 1;
1230 if (GetTopRow() <= nLastVisRow
) // calc the column with using the cell contents
1232 for (long i
= GetTopRow(); i
<= nLastVisRow
; ++i
)
1233 nNewColWidth
= std::max(nNewColWidth
,GetTotalCellWidth(i
,nColId
) + 12);
1235 if (nNewColWidth
== nCurColWidth
) // size has not changed
1236 nNewColWidth
= GetDefaultColumnWidth(GetColumnTitle(nColId
));
1239 nNewColWidth
= GetDefaultColumnWidth(GetColumnTitle(nColId
));
1240 return nNewColWidth
;
1244 sal_uInt32
EditBrowseBox::GetTotalCellWidth(long, sal_uInt16
)
1250 void EditBrowseBox::InvalidateHandleColumn()
1252 Rectangle
aHdlFieldRect( GetFieldRectPixel( 0, 0 ));
1253 Rectangle
aInvalidRect( Point(0,0), GetOutputSizePixel() );
1254 aInvalidRect
.Right() = aHdlFieldRect
.Right();
1255 Invalidate( aInvalidRect
);
1259 void EditBrowseBox::PaintTristate(OutputDevice
&, const Rectangle
& rRect
, const TriState
& eState
, bool _bEnabled
) const
1261 pCheckBoxPaint
->GetBox().SetState(eState
);
1262 pCheckBoxPaint
->SetPosSizePixel(rRect
.TopLeft(), rRect
.GetSize());
1264 // First update the parent, preventing that while painting this window
1265 // an update for the parent is done (because it's in the queue already)
1266 // which may lead to hiding this window immediately
1267 // #95598# comment out OJ
1268 /* if (pCheckBoxPaint->GetParent())
1269 pCheckBoxPaint->GetParent()->Update();
1271 pCheckBoxPaint
->GetBox().Enable(_bEnabled
);
1272 pCheckBoxPaint
->Show();
1273 pCheckBoxPaint
->SetParentUpdateMode( false );
1274 pCheckBoxPaint
->Update();
1275 pCheckBoxPaint
->Hide();
1276 pCheckBoxPaint
->SetParentUpdateMode( true );
1280 void EditBrowseBox::AsynchGetFocus()
1283 Application::RemoveUserEvent(nStartEvent
);
1285 m_pFocusWhileRequest
= Application::GetFocusWindow();
1286 nStartEvent
= Application::PostUserEvent(LINK(this,EditBrowseBox
,StartEditHdl
), NULL
, true);
1290 void EditBrowseBox::SetBrowserFlags(EditBrowseBoxFlags nFlags
)
1292 if (m_nBrowserFlags
== nFlags
)
1295 bool RowPicturesChanges
= ((m_nBrowserFlags
& EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
) !=
1296 (nFlags
& EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT
));
1297 m_nBrowserFlags
= nFlags
;
1299 if (RowPicturesChanges
)
1300 InvalidateStatusCell(GetCurRow());
1303 inline void EditBrowseBox::HideAndDisable(CellControllerRef
& rController
)
1305 rController
->suspend();
1308 inline void EditBrowseBox::EnableAndShow() const
1310 Controller()->resume();
1315 CellController::CellController(Control
* pW
)
1320 DBG_ASSERT(pWindow
, "CellController::CellController: missing the window!");
1321 DBG_ASSERT(!pWindow
->IsVisible(), "CellController::CellController: window should not be visible!");
1325 CellController::~CellController()
1331 void CellController::suspend( )
1333 DBG_ASSERT( bSuspended
== !GetWindow().IsVisible(), "CellController::suspend: inconsistence!" );
1334 if ( !isSuspended( ) )
1336 CommitModifications();
1337 GetWindow().Hide( );
1338 GetWindow().Disable( );
1344 void CellController::resume( )
1346 DBG_ASSERT( bSuspended
== !GetWindow().IsVisible(), "CellController::resume: inconsistence!" );
1347 if ( isSuspended( ) )
1349 GetWindow().Enable( );
1350 GetWindow().Show( );
1356 void CellController::CommitModifications()
1358 // nothing to do in this base class
1362 bool CellController::WantMouseEvent() const
1368 void CellController::SetModified()
1373 bool CellController::MoveAllowed(const KeyEvent
&) const
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */