diff options
author | Michael Stahl <mstahl@redhat.com> | 2014-05-26 17:43:14 +0200 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2014-05-27 11:13:02 +0200 |
commit | 35029b250318b3a4f02cef5194abdd3f68311c43 (patch) | |
tree | 5026ab2dab620dcdcae84e574483ce3c325e5a78 /sw/source/uibase/ribbar/inputwin.cxx | |
parent | f8d26c68e48e52265d4f20a1527bf52828c046ad (diff) |
sw: move sw/source/core/uibase to sw/source/uibase
It's too confusing to have UI code inside of core; the important part is
that it's separated from the optional UI code in swui library.
Change-Id: I640a52723d5802faf08f3b8eaa03cd937fd93449
Diffstat (limited to 'sw/source/uibase/ribbar/inputwin.cxx')
-rw-r--r-- | sw/source/uibase/ribbar/inputwin.cxx | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/sw/source/uibase/ribbar/inputwin.cxx b/sw/source/uibase/ribbar/inputwin.cxx new file mode 100644 index 000000000000..c3caec60a7fe --- /dev/null +++ b/sw/source/uibase/ribbar/inputwin.cxx @@ -0,0 +1,636 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <comphelper/string.hxx> +#include <officecfg/Office/Common.hxx> +#include <tools/gen.hxx> +#include <sfx2/imgmgr.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/ruler.hxx> +#include <svl/zforlist.hxx> +#include <svl/stritem.hxx> +#include <vcl/settings.hxx> + +#include "swtypes.hxx" +#include "cmdid.h" +#include "swmodule.hxx" +#include "wrtsh.hxx" +#include "view.hxx" +#include "calc.hxx" +#include "inputwin.hxx" +#include "fldbas.hxx" +#include "fldmgr.hxx" +#include "frmfmt.hxx" +#include "cellatr.hxx" +#include "edtwin.hxx" +#include "helpid.h" +#include "access.hrc" + +// Only for the UpdateRange: Delete the box in which the stacked cursor is positioned. +#include "pam.hxx" + +#include "swundo.hxx" +#include "ribbar.hrc" +#include "inputwin.hrc" + +#include <IDocumentContentOperations.hxx> + +SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT ) + +SwInputWindow::SwInputWindow( Window* pParent, SfxBindings* pBind ) + : ToolBox( pParent , SW_RES( RID_TBX_FORMULA )), + aPos( this, SW_RES(ED_POS)), + aEdit( this, WB_3DLOOK|WB_TABSTOP|WB_BORDER|WB_NOHIDESELECTION), + aPopMenu( SW_RES(MN_CALC_POPUP)), + pMgr(0), + pWrtShell(0), + pView(0), + pBindings(pBind), + aAktTableName(aEmptyOUStr) + , m_bDoesUndo(true) + , m_bResetUndo(false) + , m_bCallUndo(false) +{ + bFirst = true; + bActive = bIsTable = bDelSel = false; + + FreeResource(); + + aEdit.SetSizePixel( aEdit.CalcMinimumSize() ); + + SfxImageManager* pManager = SfxImageManager::GetImageManager( SW_MOD() ); + pManager->RegisterToolBox(this); + + pView = ::GetActiveView(); + pWrtShell = pView ? pView->GetWrtShellPtr() : 0; + + InsertWindow( ED_POS, &aPos, 0, 0); + SetItemText(ED_POS, SW_RESSTR(STR_ACCESS_FORMULA_TYPE)); + aPos.SetAccessibleName(SW_RESSTR(STR_ACCESS_FORMULA_TYPE)); + SetAccessibleName(SW_RESSTR(STR_ACCESS_FORMULA_TOOLBAR)); + InsertSeparator ( 1 ); + InsertSeparator (); + InsertWindow( ED_FORMULA, &aEdit); + SetItemText(ED_FORMULA, SW_RESSTR(STR_ACCESS_FORMULA_TEXT)); + aEdit.SetAccessibleName(SW_RESSTR(STR_ACCESS_FORMULA_TEXT)); + SetHelpId(ED_FORMULA, HID_EDIT_FORMULA); + + SetItemImage( FN_FORMULA_CALC, pManager->GetImage(FN_FORMULA_CALC )); + SetItemImage( FN_FORMULA_CANCEL, pManager->GetImage(FN_FORMULA_CANCEL )); + SetItemImage( FN_FORMULA_APPLY, pManager->GetImage(FN_FORMULA_APPLY )); + + SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | TIB_DROPDOWNONLY ); + SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl )); + + Size aSizeTbx = CalcWindowSizePixel(); + Size aEditSize = aEdit.GetSizePixel(); + Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) ); + long nMaxHeight = (aEditSize.Height() > aItemRect.GetHeight()) ? aEditSize.Height() : aItemRect.GetHeight(); + if( nMaxHeight+2 > aSizeTbx.Height() ) + aSizeTbx.Height() = nMaxHeight+2; + Size aSize = GetSizePixel(); + aSize.Height() = aSizeTbx.Height(); + SetSizePixel( aSize ); + + // align edit and item vcentered + Size aPosSize = aPos.GetSizePixel(); + aPosSize.Height() = nMaxHeight; + aEditSize.Height() = nMaxHeight; + Point aPosPos = aPos.GetPosPixel(); + Point aEditPos = aEdit.GetPosPixel(); + aPosPos.Y() = (aSize.Height() - nMaxHeight)/2 + 1; + aEditPos.Y() = (aSize.Height() - nMaxHeight)/2 + 1; + aPos.SetPosSizePixel( aPosPos, aPosSize ); + aEdit.SetPosSizePixel( aEditPos, aEditSize ); + + aPopMenu.SetSelectHdl(LINK( this, SwInputWindow, MenuHdl )); +} + +SwInputWindow::~SwInputWindow() +{ + SfxImageManager::GetImageManager( SW_MOD() )->ReleaseToolBox(this); + + // wake rulers + if(pView) + { + pView->GetHRuler().SetActive( true ); + pView->GetVRuler().SetActive( true ); + } + delete pMgr; + if(pWrtShell) + pWrtShell->EndSelTblCells(); + + CleanupUglyHackWithUndo(); +} + +void SwInputWindow::CleanupUglyHackWithUndo() +{ + if (m_bResetUndo) + { + if (pWrtShell) + { + DelBoxCntnt(); + pWrtShell->DoUndo(m_bDoesUndo); + if (m_bCallUndo) + { + pWrtShell->Undo(); + } + } + m_bResetUndo = false; // #i117122# once is enough :) + } +} + +void SwInputWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + { + // update item images + SwModule *pMod = SW_MOD(); + SfxImageManager *pImgMgr = SfxImageManager::GetImageManager( pMod ); + SetItemImage( FN_FORMULA_CALC, pImgMgr->GetImage(FN_FORMULA_CALC )); + SetItemImage( FN_FORMULA_CANCEL, pImgMgr->GetImage(FN_FORMULA_CANCEL )); + SetItemImage( FN_FORMULA_APPLY, pImgMgr->GetImage(FN_FORMULA_APPLY )); + } + + ToolBox::DataChanged( rDCEvt ); +} + +void SwInputWindow::Resize() +{ + ToolBox::Resize(); + + long nWidth = GetSizePixel().Width(); + long nLeft = aEdit.GetPosPixel().X(); + Size aEditSize = aEdit.GetSizePixel(); + + aEditSize.Width() = std::max( ((long)(nWidth - nLeft - 5)), (long)0 ); + aEdit.SetSizePixel( aEditSize ); + aEdit.Invalidate(); +} + +void SwInputWindow::ShowWin() +{ + bIsTable = false; + // stop rulers + if(pView) + { + pView->GetHRuler().SetActive( false ); + pView->GetVRuler().SetActive( false ); + + OSL_ENSURE(pWrtShell, "no WrtShell!"); + // Cursor in table + bIsTable = pWrtShell->IsCrsrInTbl() ? sal_True : sal_False; + + if( bFirst ) + pWrtShell->SelTblCells( LINK( this, SwInputWindow, + SelTblCellsNotify) ); + if( bIsTable ) + { + const OUString& rPos = pWrtShell->GetBoxNms(); + sal_Int32 nPos = 0; + short nSrch = -1; + while( (nPos = rPos.indexOf( ':',nPos + 1 ) ) != -1 ) + nSrch = (short) nPos; + aPos.SetText( rPos.copy( ++nSrch ) ); + aAktTableName = pWrtShell->GetTableFmt()->GetName(); + } + else + aPos.SetText(SW_RESSTR(STR_TBL_FORMULA)); + + // Edit current field + OSL_ENSURE(pMgr == 0, "FieldManager not deleted"); + pMgr = new SwFldMgr; + + // Formular should always begin with "=" , so set here + OUString sEdit('='); + if( pMgr->GetCurFld() && TYP_FORMELFLD == pMgr->GetCurTypeId() ) + { + sEdit += pMgr->GetCurFldPar2(); + } + else if( bFirst ) + { + if( bIsTable ) + { + m_bResetUndo = true; + SAL_WARN_IF( + officecfg::Office::Common::Undo::Steps::get() <= 0, + "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0"); + + m_bDoesUndo = pWrtShell->DoesUndo(); + if( !m_bDoesUndo ) + { + pWrtShell->DoUndo( true ); + } + + if( !pWrtShell->SwCrsrShell::HasSelection() ) + { + pWrtShell->MoveSection( fnSectionCurr, fnSectionStart ); + pWrtShell->SetMark(); + pWrtShell->MoveSection( fnSectionCurr, fnSectionEnd ); + } + if( pWrtShell->SwCrsrShell::HasSelection() ) + { + pWrtShell->StartUndo( UNDO_DELETE ); + pWrtShell->Delete(); + if( 0 != pWrtShell->EndUndo( UNDO_DELETE )) + { + m_bCallUndo = true; + } + } + pWrtShell->DoUndo(false); + + SfxItemSet aSet( pWrtShell->GetAttrPool(), RES_BOXATR_FORMULA, RES_BOXATR_FORMULA ); + if( pWrtShell->GetTblBoxFormulaAttrs( aSet )) + sEdit += ((SwTblBoxFormula&)aSet.Get( RES_BOXATR_FORMULA )).GetFormula(); + } + } + + if( bFirst ) + { + // Set WrtShell flags correctly + pWrtShell->SttSelect(); + pWrtShell->EndSelect(); + } + + bFirst = false; + + aEdit.SetModifyHdl( LINK( this, SwInputWindow, ModifyHdl )); + + aEdit.SetText( sEdit ); + aEdit.SetSelection( Selection( sEdit.getLength(), sEdit.getLength() ) ); + sOldFml = sEdit; + + aEdit.Invalidate(); + aEdit.Update(); + aEdit.GrabFocus(); + // For input cut the UserInterface + + pView->GetEditWin().LockKeyInput(true); + pView->GetViewFrame()->GetDispatcher()->Lock(true); + pWrtShell->Push(); + } + ToolBox::Show(); +} + +IMPL_LINK( SwInputWindow, MenuHdl, Menu *, pMenu ) +{ +static const char * const aStrArr[] = { + sCalc_Phd, + sCalc_Sqrt, + sCalc_Or, + sCalc_Xor, + sCalc_And, + sCalc_Not, + sCalc_Eq, + sCalc_Neq, + sCalc_Leq, + sCalc_Geq, + sCalc_L, + sCalc_G, + sCalc_Sum, + sCalc_Mean, + sCalc_Min, + sCalc_Max, + sCalc_Sin, + sCalc_Cos, + sCalc_Tan, + sCalc_Asin, + sCalc_Acos, + sCalc_Atan, + sCalc_Pow, + "|", + sCalc_Round +}; + + sal_uInt16 nId = pMenu->GetCurItemId(); + if ( nId <= MN_CALC_ROUND ) + { + OUString aTmp( OUString::createFromAscii(aStrArr[nId - 1]) ); + aTmp += " "; + aEdit.ReplaceSelected( aTmp ); + } + return 0; +} + +IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl) +{ + sal_uInt16 nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + switch ( nCurID ) + { + case FN_FORMULA_CALC : + { + aPopMenu.Execute( this, GetItemRect( FN_FORMULA_CALC ), POPUPMENU_NOMOUSEUPCLOSE ); + break; + default: + break; + } + } + + return sal_True; +} + +void SwInputWindow::Click( ) +{ + sal_uInt16 nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + switch ( nCurID ) + { + case FN_FORMULA_CANCEL: + { + CancelFormula(); + } + break; + case FN_FORMULA_APPLY: + { + ApplyFormula(); + } + break; + } +} + +void SwInputWindow::ApplyFormula() +{ + pView->GetViewFrame()->GetDispatcher()->Lock(false); + pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + pWrtShell->Pop( false ); + + // Formular should always begin with "=", so remove it here again + OUString sEdit(comphelper::string::strip(aEdit.GetText(), ' ')); + if( !sEdit.isEmpty() && '=' == sEdit[0] ) + sEdit = sEdit.copy( 1 ); + SfxStringItem aParam(FN_EDIT_FORMULA, sEdit); + + pWrtShell->EndSelTblCells(); + pView->GetEditWin().GrabFocus(); + const SfxPoolItem* aArgs[2]; + aArgs[0] = &aParam; + aArgs[1] = 0; + pView->GetViewFrame()->GetBindings().Execute( FN_EDIT_FORMULA, aArgs, 0, SFX_CALLMODE_ASYNCHRON ); +} + +void SwInputWindow::CancelFormula() +{ + if(pView) + { + pView->GetViewFrame()->GetDispatcher()->Lock( false ); + pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + pWrtShell->Pop( false ); + + if( bDelSel ) + pWrtShell->EnterStdMode(); + + pWrtShell->EndSelTblCells(); + + pView->GetEditWin().GrabFocus(); + + pView->GetViewFrame()->GetDispatcher()->Execute( FN_EDIT_FORMULA, SFX_CALLMODE_ASYNCHRON); + } +} + +const sal_Unicode CH_LRE = 0x202a; +const sal_Unicode CH_PDF = 0x202c; + +IMPL_LINK( SwInputWindow, SelTblCellsNotify, SwWrtShell *, pCaller ) +{ + if(bIsTable) + { + SwFrmFmt* pTblFmt = pCaller->GetTableFmt(); + OUString sBoxNms( pCaller->GetBoxNms() ); + OUString sTblNm; + if( pTblFmt && aAktTableName != pTblFmt->GetName() ) + sTblNm = pTblFmt->GetName(); + + aEdit.UpdateRange( sBoxNms, sTblNm ); + + OUString sNew; + sNew += OUString(CH_LRE); + sNew += aEdit.GetText(); + sNew += OUString(CH_PDF); + + if( sNew != sOldFml ) + { + // The WrtShell is in the table selection, + // then cancel the table selection otherwise, the cursor is + // positioned "in the forest" and the live update does not work! + pWrtShell->StartAllAction(); + + SwPaM aPam( *pWrtShell->GetStkCrsr()->GetPoint() ); + aPam.Move( fnMoveBackward, fnGoSection ); + aPam.SetMark(); + aPam.Move( fnMoveForward, fnGoSection ); + + IDocumentContentOperations* pIDCO = pWrtShell->getIDocumentContentOperations(); + pIDCO->DeleteRange( aPam ); + pIDCO->InsertString( aPam, sNew ); + pWrtShell->EndAllAction(); + sOldFml = sNew; + } + } + else + aEdit.GrabFocus(); + return 0; +} + +void SwInputWindow::SetFormula( const OUString& rFormula, bool bDelFlag ) +{ + OUString sEdit('='); + if( !rFormula.isEmpty() ) + { + if( '=' == rFormula[0] ) + sEdit = rFormula; + else + sEdit += rFormula; + } + aEdit.SetText( sEdit ); + aEdit.SetSelection( Selection( sEdit.getLength(), sEdit.getLength() ) ); + aEdit.Invalidate(); + bDelSel = bDelFlag; +} + +IMPL_LINK_NOARG(SwInputWindow, ModifyHdl) +{ + if (bIsTable && m_bResetUndo) + { + pWrtShell->StartAllAction(); + DelBoxCntnt(); + OUString sNew; + sNew += OUString(CH_LRE); + sNew += aEdit.GetText(); + sNew += OUString(CH_PDF); + pWrtShell->SwEditShell::Insert2( sNew ); + pWrtShell->EndAllAction(); + sOldFml = sNew; + } + return 0; +} + +void SwInputWindow::DelBoxCntnt() +{ + if( bIsTable ) + { + pWrtShell->StartAllAction(); + pWrtShell->ClearMark(); + pWrtShell->Pop( false ); + pWrtShell->Push(); + pWrtShell->MoveSection( fnSectionCurr, fnSectionStart ); + pWrtShell->SetMark(); + pWrtShell->MoveSection( fnSectionCurr, fnSectionEnd ); + pWrtShell->SwEditShell::Delete(); + pWrtShell->EndAllAction(); + } +} + +void InputEdit::KeyInput(const KeyEvent& rEvent) +{ + const KeyCode aCode = rEvent.GetKeyCode(); + if(aCode == KEY_RETURN || aCode == KEY_F2 ) + ((SwInputWindow*)GetParent())->ApplyFormula(); + else if(aCode == KEY_ESCAPE ) + ((SwInputWindow*)GetParent())->CancelFormula(); + else + Edit::KeyInput(rEvent); +} + +void InputEdit::UpdateRange(const OUString& rBoxes, + const OUString& rName ) +{ + if( rBoxes.isEmpty() ) + { + GrabFocus(); + return; + } + const sal_Unicode cOpen = '<', cClose = '>', + cOpenBracket = '('; + OUString aPrefix = rName; + if(!rName.isEmpty()) + aPrefix += "."; + OUString aBoxes = aPrefix; + aBoxes += rBoxes; + Selection aSelection(GetSelection()); + sal_uInt16 nSel = (sal_uInt16) aSelection.Len(); + // OS: The following expression ensures that in the overwrite mode, + // the selected closing parenthesis will be not deleted. + if( nSel && ( nSel > 1 || + GetText()[ (sal_uInt16)aSelection.Min() ] != cClose )) + Cut(); + else + aSelection.Max() = aSelection.Min(); + OUString aActText(GetText()); + const sal_uInt16 nLen = aActText.getLength(); + if( !nLen ) + { + OUString aStr = OUStringBuffer(). + append(cOpen).append(aBoxes).append(cClose). + makeStringAndClear(); + SetText(aStr); + sal_Int32 nPos = aStr.indexOf( cClose ); + OSL_ENSURE(nPos != -1, "delimiter not found"); + ++nPos; + SetSelection( Selection( nPos, nPos )); + } + else + { + bool bFound = false; + sal_Unicode cCh; + sal_uInt16 nPos, nEndPos = 0, nStartPos = (sal_uInt16) aSelection.Min(); + if( nStartPos-- ) + { + do { + if( cOpen == (cCh = aActText[ nStartPos ] ) || + cOpenBracket == cCh ) + { + bFound = cCh == cOpen; + break; + } + } while( nStartPos-- > 0 ); + } + if( bFound ) + { + bFound = false; + nEndPos = nStartPos; + while( nEndPos < nLen ) + { + if( cClose == (cCh = aActText[ nEndPos ])) + { + bFound = true; + break; + } + ++nEndPos; + } + // Only if the current position lies in the range or right behind. + if( bFound && !( nStartPos < (sal_uInt16)aSelection.Max() && + (sal_uInt16)aSelection.Max() <= nEndPos + 1 )) + bFound = false; + } + if( bFound ) + { + nPos = ++nStartPos + 1; // We want behind + aActText = aActText.replaceAt( nStartPos, nEndPos - nStartPos, aBoxes ); + nPos = nPos + aBoxes.getLength(); + } + else + { + OUString aTmp = OUStringBuffer(). + append(cOpen).append(aBoxes).append(cClose). + makeStringAndClear(); + nPos = (sal_uInt16)aSelection.Min(); + aActText = aActText.replaceAt( nPos, 0, aTmp ); + nPos = nPos + aTmp.getLength(); + } + if( GetText() != OUString(aActText) ) + { + SetText( aActText ); + SetSelection( Selection( nPos, nPos ) ); + } + } + GrabFocus(); + +} + +SwInputChild::SwInputChild(Window* _pParent, + sal_uInt16 nId, + SfxBindings* pBindings, + SfxChildWinInfo* ) : + SfxChildWindow( _pParent, nId ) +{ + pDispatch = pBindings->GetDispatcher(); + pWindow = new SwInputWindow( _pParent, pBindings ); + ((SwInputWindow*)pWindow)->ShowWin(); + eChildAlignment = SFX_ALIGN_LOWESTTOP; +} + +SwInputChild::~SwInputChild() +{ + if(pDispatch) + pDispatch->Lock(false); +} + +SfxChildWinInfo SwInputChild::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); \ + return aInfo; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |