| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| #include <svtools/editbrowsebox.hxx> |
| #include <vcl/decoview.hxx> |
| #include <svtools/fmtfield.hxx> |
| #include <svtools/xtextedt.hxx> |
| |
| #include <algorithm> |
| |
| // ....................................................................... |
| namespace svt |
| { |
| // ....................................................................... |
| |
| TYPEINIT0(CellController); |
| TYPEINIT1(EditCellController, CellController); |
| TYPEINIT1(SpinCellController, CellController); |
| TYPEINIT1(CheckBoxCellController, CellController); |
| TYPEINIT1(ComboBoxCellController, CellController); |
| TYPEINIT1(ListBoxCellController, CellController); |
| |
| TYPEINIT1( FormattedFieldCellController, EditCellController ); |
| |
| //================================================================== |
| //= ComboBoxControl |
| //================================================================== |
| ComboBoxControl::ComboBoxControl(Window* pParent, WinBits nWinStyle) |
| :ComboBox(pParent, nWinStyle|WB_DROPDOWN|WB_NOBORDER) |
| { |
| EnableAutoSize(sal_False); |
| EnableAutocomplete(sal_True); |
| SetDropDownLineCount(5); |
| } |
| |
| //------------------------------------------------------------------ |
| long ComboBoxControl::PreNotify( NotifyEvent& rNEvt ) |
| { |
| switch (rNEvt.GetType()) |
| { |
| case EVENT_KEYINPUT: |
| if (!IsInDropDown()) |
| { |
| const KeyEvent *pEvt = rNEvt.GetKeyEvent(); |
| const KeyCode rKey = pEvt->GetKeyCode(); |
| |
| if ((rKey.GetCode() == KEY_UP || rKey.GetCode() == KEY_DOWN) && |
| (!pEvt->GetKeyCode().IsShift() && pEvt->GetKeyCode().IsMod1())) |
| { |
| // select next resp. previous entry |
| int nPos = GetEntryPos(GetText()); |
| nPos = nPos + (rKey.GetCode() == KEY_DOWN ? 1 : -1); |
| if (nPos < 0) |
| nPos = 0; |
| if (nPos >= GetEntryCount()) |
| nPos = GetEntryCount() - 1; |
| SetText(GetEntry(sal::static_int_cast< sal_uInt16 >(nPos))); |
| return 1; |
| } |
| } |
| break; |
| } |
| return ComboBox::PreNotify(rNEvt); |
| } |
| |
| //================================================================== |
| //= ComboBoxCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| ComboBoxCellController::ComboBoxCellController(ComboBoxControl* pWin) |
| :CellController(pWin) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool ComboBoxCellController::MoveAllowed(const KeyEvent& rEvt) const |
| { |
| ComboBoxControl& rBox = GetComboBox(); |
| switch (rEvt.GetKeyCode().GetCode()) |
| { |
| case KEY_END: |
| case KEY_RIGHT: |
| { |
| Selection aSel = rBox.GetSelection(); |
| return !aSel && aSel.Max() == rBox.GetText().Len(); |
| } |
| case KEY_HOME: |
| case KEY_LEFT: |
| { |
| Selection aSel = rBox.GetSelection(); |
| return !aSel && aSel.Min() == 0; |
| } |
| case KEY_UP: |
| case KEY_DOWN: |
| if (rBox.IsInDropDown()) |
| return sal_False; |
| if (!rEvt.GetKeyCode().IsShift() && |
| rEvt.GetKeyCode().IsMod1()) |
| return sal_False; |
| // drop down the list box |
| else if (rEvt.GetKeyCode().IsMod2() && rEvt.GetKeyCode().GetCode() == KEY_DOWN) |
| return sal_False; |
| case KEY_PAGEUP: |
| case KEY_PAGEDOWN: |
| case KEY_RETURN: |
| if (rBox.IsInDropDown()) |
| return sal_False; |
| default: |
| return sal_True; |
| } |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool ComboBoxCellController::IsModified() const |
| { |
| return GetComboBox().GetSavedValue() != GetComboBox().GetText(); |
| } |
| |
| //------------------------------------------------------------------ |
| void ComboBoxCellController::ClearModified() |
| { |
| GetComboBox().SaveValue(); |
| } |
| |
| //------------------------------------------------------------------ |
| void ComboBoxCellController::SetModifyHdl(const Link& rLink) |
| { |
| GetComboBox().SetModifyHdl(rLink); |
| } |
| |
| //================================================================== |
| //= ListBoxControl |
| //================================================================== |
| //------------------------------------------------------------------ |
| ListBoxControl::ListBoxControl(Window* pParent, WinBits nWinStyle) |
| :ListBox(pParent, nWinStyle|WB_DROPDOWN|WB_NOBORDER) |
| { |
| EnableAutoSize(sal_False); |
| EnableMultiSelection(sal_False); |
| SetDropDownLineCount(20); |
| } |
| |
| //------------------------------------------------------------------ |
| long ListBoxControl::PreNotify( NotifyEvent& rNEvt ) |
| { |
| switch (rNEvt.GetType()) |
| { |
| case EVENT_KEYINPUT: |
| if (!IsInDropDown()) |
| { |
| const KeyEvent *pEvt = rNEvt.GetKeyEvent(); |
| const KeyCode rKey = pEvt->GetKeyCode(); |
| |
| if ((rKey.GetCode() == KEY_UP || rKey.GetCode() == KEY_DOWN) && |
| (!pEvt->GetKeyCode().IsShift() && pEvt->GetKeyCode().IsMod1())) |
| { |
| // select next resp. previous entry |
| int nPos = GetSelectEntryPos(); |
| nPos = nPos + (rKey.GetCode() == KEY_DOWN ? 1 : -1); |
| if (nPos < 0) |
| nPos = 0; |
| if (nPos >= GetEntryCount()) |
| nPos = GetEntryCount() - 1; |
| SelectEntryPos(sal::static_int_cast< sal_uInt16 >(nPos)); |
| Select(); // for calling Modify |
| return 1; |
| } |
| else if (GetParent()->PreNotify(rNEvt)) |
| return 1; |
| } |
| break; |
| } |
| return ListBox::PreNotify(rNEvt); |
| } |
| |
| //================================================================== |
| //= ListBoxCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| ListBoxCellController::ListBoxCellController(ListBoxControl* pWin) |
| :CellController(pWin) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool ListBoxCellController::MoveAllowed(const KeyEvent& rEvt) const |
| { |
| ListBoxControl& rBox = GetListBox(); |
| switch (rEvt.GetKeyCode().GetCode()) |
| { |
| case KEY_UP: |
| case KEY_DOWN: |
| if (!rEvt.GetKeyCode().IsShift() && |
| rEvt.GetKeyCode().IsMod1()) |
| return sal_False; |
| // drop down the list box |
| else |
| if (rEvt.GetKeyCode().IsMod2() && rEvt.GetKeyCode().GetCode() == KEY_DOWN) |
| return sal_False; |
| case KEY_PAGEUP: |
| case KEY_PAGEDOWN: |
| if (rBox.IsTravelSelect()) |
| return sal_False; |
| default: |
| return sal_True; |
| } |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool ListBoxCellController::IsModified() const |
| { |
| return GetListBox().GetSelectEntryPos() != GetListBox().GetSavedValue(); |
| } |
| |
| //------------------------------------------------------------------ |
| void ListBoxCellController::ClearModified() |
| { |
| GetListBox().SaveValue(); |
| } |
| |
| //------------------------------------------------------------------ |
| void ListBoxCellController::SetModifyHdl(const Link& rLink) |
| { |
| GetListBox().SetSelectHdl(rLink); |
| } |
| |
| //================================================================== |
| //= CheckBoxControl |
| //================================================================== |
| //------------------------------------------------------------------ |
| CheckBoxControl::CheckBoxControl(Window* pParent, WinBits nWinStyle) |
| :Control(pParent, nWinStyle) |
| { |
| const Wallpaper& rParentBackground = pParent->GetBackground(); |
| if ( (pParent->GetStyle() & WB_CLIPCHILDREN) || rParentBackground.IsFixed() ) |
| SetBackground( rParentBackground ); |
| else |
| { |
| SetPaintTransparent( sal_True ); |
| SetBackground(); |
| } |
| |
| EnableChildTransparentMode(); |
| |
| pBox = new TriStateBox(this,WB_CENTER|WB_VCENTER); |
| pBox->EnableChildTransparentMode(); |
| pBox->SetPaintTransparent( sal_True ); |
| pBox->SetClickHdl( LINK( this, CheckBoxControl, OnClick ) ); |
| pBox->Show(); |
| } |
| |
| //------------------------------------------------------------------ |
| CheckBoxControl::~CheckBoxControl() |
| { |
| delete pBox; |
| } |
| |
| //------------------------------------------------------------------ |
| IMPL_LINK( CheckBoxControl, OnClick, void*, EMPTYARG ) |
| { |
| m_aClickLink.Call(pBox); |
| return m_aModifyLink.Call(pBox); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxControl::Resize() |
| { |
| Control::Resize(); |
| pBox->SetPosSizePixel(Point(0,0),GetSizePixel()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void CheckBoxControl::DataChanged( const DataChangedEvent& _rEvent ) |
| { |
| if ( _rEvent.GetType() == DATACHANGED_SETTINGS ) |
| pBox->SetSettings( GetSettings() ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void CheckBoxControl::StateChanged( StateChangedType nStateChange ) |
| { |
| Control::StateChanged(nStateChange); |
| if ( nStateChange == STATE_CHANGE_ZOOM ) |
| pBox->SetZoom(GetZoom()); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxControl::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) |
| { |
| pBox->Draw(pDev,rPos,rSize,nFlags); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxControl::GetFocus() |
| { |
| pBox->GrabFocus(); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxControl::Paint(const Rectangle& rClientRect) |
| { |
| Control::Paint(rClientRect); |
| if (HasFocus()) |
| ShowFocus(aFocusRect); |
| } |
| |
| //------------------------------------------------------------------ |
| long CheckBoxControl::PreNotify(NotifyEvent& rEvt) |
| { |
| switch (rEvt.GetType()) |
| { |
| case EVENT_GETFOCUS: |
| ShowFocus(aFocusRect); |
| break; |
| case EVENT_LOSEFOCUS: |
| HideFocus(); |
| } |
| return Control::PreNotify(rEvt); |
| } |
| |
| //================================================================== |
| //= CheckBoxCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| sal_Bool CheckBoxCellController::WantMouseEvent() const |
| { |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------ |
| CheckBox& CheckBoxCellController::GetCheckBox() const |
| { |
| return ((CheckBoxControl &)GetWindow()).GetBox(); |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool CheckBoxCellController::IsModified() const |
| { |
| return GetCheckBox().GetSavedValue() != GetCheckBox().GetState(); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxCellController::ClearModified() |
| { |
| GetCheckBox().SaveValue(); |
| } |
| |
| //------------------------------------------------------------------ |
| void CheckBoxCellController::SetModifyHdl(const Link& rLink) |
| { |
| ((CheckBoxControl &)GetWindow()).SetModifyHdl(rLink); |
| } |
| |
| //================================================================== |
| //= MultiLineEditImplementation |
| //================================================================== |
| //------------------------------------------------------------------ |
| String MultiLineEditImplementation::GetText( LineEnd aSeparator ) const |
| { |
| return const_cast< MultiLineEditImplementation* >( this )->GetEditWindow().GetText( aSeparator ); |
| } |
| |
| //------------------------------------------------------------------ |
| String MultiLineEditImplementation::GetSelected( LineEnd aSeparator ) const |
| { |
| return const_cast< MultiLineEditImplementation* >( this )->GetEditWindow().GetSelected( aSeparator ); |
| } |
| |
| //================================================================== |
| //= EditCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| EditCellController::EditCellController( Edit* _pEdit ) |
| :CellController( _pEdit ) |
| ,m_pEditImplementation( new EditImplementation( *_pEdit ) ) |
| ,m_bOwnImplementation( sal_True ) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| EditCellController::EditCellController( MultiLineTextCell* _pEdit ) |
| :CellController( _pEdit ) |
| ,m_pEditImplementation( new MultiLineEditImplementation( *_pEdit ) ) |
| ,m_bOwnImplementation( sal_True ) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| EditCellController::EditCellController( IEditImplementation* _pImplementation ) |
| :CellController( &_pImplementation->GetControl() ) |
| ,m_pEditImplementation( _pImplementation ) |
| ,m_bOwnImplementation( sal_False ) |
| { |
| } |
| |
| //----------------------------------------------------------------------------- |
| EditCellController::~EditCellController( ) |
| { |
| if ( m_bOwnImplementation ) |
| DELETEZ( m_pEditImplementation ); |
| } |
| |
| //----------------------------------------------------------------------------- |
| void EditCellController::SetModified() |
| { |
| m_pEditImplementation->SetModified(); |
| } |
| |
| //----------------------------------------------------------------------------- |
| void EditCellController::ClearModified() |
| { |
| m_pEditImplementation->ClearModified(); |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool EditCellController::MoveAllowed(const KeyEvent& rEvt) const |
| { |
| sal_Bool bResult; |
| switch (rEvt.GetKeyCode().GetCode()) |
| { |
| case KEY_END: |
| case KEY_RIGHT: |
| { |
| Selection aSel = m_pEditImplementation->GetSelection(); |
| bResult = !aSel && aSel.Max() == m_pEditImplementation->GetText( LINEEND_LF ).Len(); |
| } break; |
| case KEY_HOME: |
| case KEY_LEFT: |
| { |
| Selection aSel = m_pEditImplementation->GetSelection(); |
| bResult = !aSel && aSel.Min() == 0; |
| } break; |
| default: |
| bResult = sal_True; |
| } |
| return bResult; |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool EditCellController::IsModified() const |
| { |
| return m_pEditImplementation->IsModified(); |
| } |
| |
| //------------------------------------------------------------------ |
| void EditCellController::SetModifyHdl(const Link& rLink) |
| { |
| m_pEditImplementation->SetModifyHdl(rLink); |
| } |
| |
| //================================================================== |
| //= SpinCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| SpinCellController::SpinCellController(SpinField* pWin) |
| :CellController(pWin) |
| { |
| } |
| |
| //----------------------------------------------------------------------------- |
| void SpinCellController::SetModified() |
| { |
| GetSpinWindow().SetModifyFlag(); |
| } |
| |
| //----------------------------------------------------------------------------- |
| void SpinCellController::ClearModified() |
| { |
| GetSpinWindow().ClearModifyFlag(); |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool SpinCellController::MoveAllowed(const KeyEvent& rEvt) const |
| { |
| sal_Bool bResult; |
| switch (rEvt.GetKeyCode().GetCode()) |
| { |
| case KEY_END: |
| case KEY_RIGHT: |
| { |
| Selection aSel = GetSpinWindow().GetSelection(); |
| bResult = !aSel && aSel.Max() == GetSpinWindow().GetText().Len(); |
| } break; |
| case KEY_HOME: |
| case KEY_LEFT: |
| { |
| Selection aSel = GetSpinWindow().GetSelection(); |
| bResult = !aSel && aSel.Min() == 0; |
| } break; |
| default: |
| bResult = sal_True; |
| } |
| return bResult; |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool SpinCellController::IsModified() const |
| { |
| return GetSpinWindow().IsModified(); |
| } |
| |
| //------------------------------------------------------------------ |
| void SpinCellController::SetModifyHdl(const Link& rLink) |
| { |
| GetSpinWindow().SetModifyHdl(rLink); |
| } |
| |
| //================================================================== |
| //= FormattedFieldCellController |
| //================================================================== |
| //------------------------------------------------------------------ |
| FormattedFieldCellController::FormattedFieldCellController( FormattedField* _pFormatted ) |
| :EditCellController( _pFormatted ) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| void FormattedFieldCellController::CommitModifications() |
| { |
| static_cast< FormattedField& >( GetWindow() ).Commit(); |
| } |
| |
| //================================================================== |
| //= MultiLineTextCell |
| //================================================================== |
| //------------------------------------------------------------------ |
| void MultiLineTextCell::Modify() |
| { |
| GetTextEngine()->SetModified( sal_True ); |
| MultiLineEdit::Modify(); |
| } |
| |
| //------------------------------------------------------------------ |
| sal_Bool MultiLineTextCell::dispatchKeyEvent( const KeyEvent& _rEvent ) |
| { |
| Selection aOldSelection( GetSelection() ); |
| |
| sal_Bool bWasModified = IsModified(); |
| ClearModifyFlag( ); |
| |
| sal_Bool bHandled = GetTextView()->KeyInput( _rEvent ); |
| |
| sal_Bool bIsModified = IsModified(); |
| if ( bWasModified && !bIsModified ) |
| // not sure whether this can really happen |
| SetModifyFlag(); |
| |
| if ( bHandled ) // the view claimed it handled the key input |
| { |
| // unfortunately, KeyInput also returns <TRUE/> (means "I handled this key input") |
| // when nothing really changed. Let's care for this. |
| Selection aNewSelection( GetSelection() ); |
| if ( aNewSelection != aOldSelection // selection changed |
| || bIsModified // or some other modification |
| ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| //------------------------------------------------------------------ |
| long MultiLineTextCell::PreNotify( NotifyEvent& rNEvt ) |
| { |
| if ( rNEvt.GetType() == EVENT_KEYINPUT ) |
| { |
| if ( IsWindowOrChild( rNEvt.GetWindow() ) ) |
| { |
| // give the text view a chance to handle the keys |
| // this is necessary since a lot of keys which are normally handled |
| // by this view (in KeyInput) are intercepted by the EditBrowseBox, |
| // which uses them for other reasons. An example is the KeyUp key, |
| // which is used by both the text view and the edit browse box |
| |
| const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent(); |
| const KeyCode& rKeyCode = pKeyEvent->GetKeyCode(); |
| sal_uInt16 nCode = rKeyCode.GetCode(); |
| |
| if ( ( nCode == KEY_RETURN ) && ( rKeyCode.GetModifier() == KEY_MOD1 ) ) |
| { |
| KeyEvent aEvent( pKeyEvent->GetCharCode(), |
| KeyCode( KEY_RETURN ), |
| pKeyEvent->GetRepeat() |
| ); |
| if ( dispatchKeyEvent( aEvent ) ) |
| return 1; |
| } |
| |
| if ( ( nCode != KEY_TAB ) && ( nCode != KEY_RETURN ) ) // everything but tab and enter |
| { |
| if ( dispatchKeyEvent( *pKeyEvent ) ) |
| return 1; |
| } |
| } |
| } |
| return MultiLineEdit::PreNotify( rNEvt ); |
| } |
| |
| // ....................................................................... |
| } // namespace svt |
| // ....................................................................... |
| |
| |