update credits
[LibreOffice.git] / sw / source / ui / ribbar / inputwin.cxx
blob375c280aa30075302a10db707731097ac2cd7fde
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 "sal/config.h"
22 #include <comphelper/string.hxx>
23 #include <officecfg/Office/Common.hxx>
24 #include <tools/gen.hxx>
25 #include <sfx2/imgmgr.hxx>
26 #include <sfx2/viewfrm.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <svx/ruler.hxx>
29 #include <svl/zforlist.hxx>
30 #include <svl/stritem.hxx>
32 #include "swtypes.hxx"
33 #include "cmdid.h"
34 #include "swmodule.hxx"
35 #include "wrtsh.hxx"
36 #include "view.hxx"
37 #include "calc.hxx"
38 #include "inputwin.hxx"
39 #include "fldbas.hxx"
40 #include "fldmgr.hxx"
41 #include "frmfmt.hxx"
42 #include "cellatr.hxx"
43 #include "edtwin.hxx"
44 #include "helpid.h"
46 // Only for the UpdateRange: Delete the box in which the stacked cursor is positioned.
47 #include "pam.hxx"
49 #include "swundo.hxx"
50 #include "ribbar.hrc"
51 #include "inputwin.hrc"
53 #include <IDocumentContentOperations.hxx>
55 SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT )
57 SwInputWindow::SwInputWindow( Window* pParent, SfxBindings* pBind )
58 : ToolBox( pParent , SW_RES( RID_TBX_FORMULA )),
59 aPos( this, SW_RES(ED_POS)),
60 aEdit( this, WB_3DLOOK|WB_TABSTOP|WB_BORDER|WB_NOHIDESELECTION),
61 aPopMenu( SW_RES(MN_CALC_POPUP)),
62 pMgr(0),
63 pWrtShell(0),
64 pView(0),
65 pBindings(pBind),
66 aAktTableName(aEmptyStr)
67 , m_bDoesUndo(true)
68 , m_bResetUndo(false)
69 , m_bCallUndo(false)
71 bFirst = sal_True;
72 bActive = bIsTable = bDelSel = sal_False;
74 FreeResource();
76 aEdit.SetSizePixel( aEdit.CalcMinimumSize() );
78 SfxImageManager* pManager = SfxImageManager::GetImageManager( SW_MOD() );
79 pManager->RegisterToolBox(this);
81 pView = ::GetActiveView();
82 pWrtShell = pView ? pView->GetWrtShellPtr() : 0;
84 InsertWindow( ED_POS, &aPos, 0, 0);
85 InsertSeparator ( 1 );
86 InsertSeparator ();
87 InsertWindow( ED_FORMULA, &aEdit);
88 SetHelpId(ED_FORMULA, HID_EDIT_FORMULA);
90 SetItemImage( FN_FORMULA_CALC, pManager->GetImage(FN_FORMULA_CALC ));
91 SetItemImage( FN_FORMULA_CANCEL, pManager->GetImage(FN_FORMULA_CANCEL ));
92 SetItemImage( FN_FORMULA_APPLY, pManager->GetImage(FN_FORMULA_APPLY ));
94 SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | TIB_DROPDOWNONLY );
95 SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl ));
97 Size aSizeTbx = CalcWindowSizePixel();
98 Size aEditSize = aEdit.GetSizePixel();
99 Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) );
100 long nMaxHeight = (aEditSize.Height() > aItemRect.GetHeight()) ? aEditSize.Height() : aItemRect.GetHeight();
101 if( nMaxHeight+2 > aSizeTbx.Height() )
102 aSizeTbx.Height() = nMaxHeight+2;
103 Size aSize = GetSizePixel();
104 aSize.Height() = aSizeTbx.Height();
105 SetSizePixel( aSize );
107 // align edit and item vcentered
108 Size aPosSize = aPos.GetSizePixel();
109 aPosSize.Height() = nMaxHeight;
110 aEditSize.Height() = nMaxHeight;
111 Point aPosPos = aPos.GetPosPixel();
112 Point aEditPos = aEdit.GetPosPixel();
113 aPosPos.Y() = (aSize.Height() - nMaxHeight)/2 + 1;
114 aEditPos.Y() = (aSize.Height() - nMaxHeight)/2 + 1;
115 aPos.SetPosSizePixel( aPosPos, aPosSize );
116 aEdit.SetPosSizePixel( aEditPos, aEditSize );
118 aPopMenu.SetSelectHdl(LINK( this, SwInputWindow, MenuHdl ));
121 SwInputWindow::~SwInputWindow()
123 SfxImageManager::GetImageManager( SW_MOD() )->ReleaseToolBox(this);
125 // wake rulers
126 if(pView)
128 pView->GetHRuler().SetActive( sal_True );
129 pView->GetVRuler().SetActive( sal_True );
131 delete pMgr;
132 if(pWrtShell)
133 pWrtShell->EndSelTblCells();
135 CleanupUglyHackWithUndo();
138 void SwInputWindow::CleanupUglyHackWithUndo()
140 if (m_bResetUndo)
142 DelBoxCntnt();
143 pWrtShell->DoUndo(m_bDoesUndo);
144 if (m_bCallUndo)
146 pWrtShell->Undo();
148 m_bResetUndo = false; // #i117122# once is enough :)
152 void SwInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
154 if ( rDCEvt.GetType() == DATACHANGED_SETTINGS && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
156 // update item images
157 SwModule *pMod = SW_MOD();
158 SfxImageManager *pImgMgr = SfxImageManager::GetImageManager( pMod );
159 SetItemImage( FN_FORMULA_CALC, pImgMgr->GetImage(FN_FORMULA_CALC ));
160 SetItemImage( FN_FORMULA_CANCEL, pImgMgr->GetImage(FN_FORMULA_CANCEL ));
161 SetItemImage( FN_FORMULA_APPLY, pImgMgr->GetImage(FN_FORMULA_APPLY ));
164 ToolBox::DataChanged( rDCEvt );
167 void SwInputWindow::Resize()
169 ToolBox::Resize();
171 long nWidth = GetSizePixel().Width();
172 long nLeft = aEdit.GetPosPixel().X();
173 Size aEditSize = aEdit.GetSizePixel();
175 aEditSize.Width() = std::max( ((long)(nWidth - nLeft - 5)), (long)0 );
176 aEdit.SetSizePixel( aEditSize );
177 aEdit.Invalidate();
180 void SwInputWindow::ShowWin()
182 bIsTable = sal_False;
183 // stop rulers
184 if(pView)
186 pView->GetHRuler().SetActive( sal_False );
187 pView->GetVRuler().SetActive( sal_False );
189 OSL_ENSURE(pWrtShell, "no WrtShell!");
190 // Cursor in table
191 bIsTable = pWrtShell->IsCrsrInTbl() ? sal_True : sal_False;
193 if( bFirst )
194 pWrtShell->SelTblCells( LINK( this, SwInputWindow,
195 SelTblCellsNotify) );
196 if( bIsTable )
198 const String& rPos = pWrtShell->GetBoxNms();
199 sal_uInt16 nPos = 0;
200 short nSrch = -1;
201 while( (nPos = rPos.Search( ':',nPos + 1 ) ) != STRING_NOTFOUND )
202 nSrch = (short) nPos;
203 aPos.SetText( rPos.Copy( ++nSrch ) );
204 aAktTableName = pWrtShell->GetTableFmt()->GetName();
206 else
207 aPos.SetText(SW_RESSTR(STR_TBL_FORMULA));
209 // Edit current field
210 OSL_ENSURE(pMgr == 0, "FieldManager not deleted");
211 pMgr = new SwFldMgr;
213 // Formular should always begin with "=" , so set here
214 String sEdit = OUString('=');
215 if( pMgr->GetCurFld() && TYP_FORMELFLD == pMgr->GetCurTypeId() )
217 sEdit += pMgr->GetCurFldPar2();
219 else if( bFirst )
221 if( bIsTable )
223 m_bResetUndo = true;
224 SAL_WARN_IF(
225 officecfg::Office::Common::Undo::Steps::get() <= 0,
226 "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0");
228 m_bDoesUndo = pWrtShell->DoesUndo();
229 if( !m_bDoesUndo )
231 pWrtShell->DoUndo( sal_True );
234 if( !pWrtShell->SwCrsrShell::HasSelection() )
236 pWrtShell->MoveSection( fnSectionCurr, fnSectionStart );
237 pWrtShell->SetMark();
238 pWrtShell->MoveSection( fnSectionCurr, fnSectionEnd );
240 if( pWrtShell->SwCrsrShell::HasSelection() )
242 pWrtShell->StartUndo( UNDO_DELETE );
243 pWrtShell->Delete();
244 if( 0 != pWrtShell->EndUndo( UNDO_DELETE ))
246 m_bCallUndo = true;
249 pWrtShell->DoUndo(false);
251 SfxItemSet aSet( pWrtShell->GetAttrPool(), RES_BOXATR_FORMULA, RES_BOXATR_FORMULA );
252 if( pWrtShell->GetTblBoxFormulaAttrs( aSet ))
253 sEdit += ((SwTblBoxFormula&)aSet.Get( RES_BOXATR_FORMULA )).GetFormula();
257 if( bFirst )
259 // Set WrtShell flags correctly
260 pWrtShell->SttSelect();
261 pWrtShell->EndSelect();
264 bFirst = sal_False;
266 aEdit.SetModifyHdl( LINK( this, SwInputWindow, ModifyHdl ));
268 aEdit.SetText( sEdit );
269 aEdit.SetSelection( Selection( sEdit.Len(), sEdit.Len() ) );
270 sOldFml = sEdit;
272 aEdit.Invalidate();
273 aEdit.Update();
274 aEdit.GrabFocus();
275 // For input cut the UserInterface
277 pView->GetEditWin().LockKeyInput(sal_True);
278 pView->GetViewFrame()->GetDispatcher()->Lock(sal_True);
279 pWrtShell->Push();
281 ToolBox::Show();
284 IMPL_LINK( SwInputWindow, MenuHdl, Menu *, pMenu )
286 static const char * const aStrArr[] = {
287 sCalc_Phd,
288 sCalc_Sqrt,
289 sCalc_Or,
290 sCalc_Xor,
291 sCalc_And,
292 sCalc_Not,
293 sCalc_Eq,
294 sCalc_Neq,
295 sCalc_Leq,
296 sCalc_Geq,
297 sCalc_L,
298 sCalc_G,
299 sCalc_Sum,
300 sCalc_Mean,
301 sCalc_Min,
302 sCalc_Max,
303 sCalc_Sin,
304 sCalc_Cos,
305 sCalc_Tan,
306 sCalc_Asin,
307 sCalc_Acos,
308 sCalc_Atan,
309 sCalc_Pow,
310 "|",
311 sCalc_Round
314 sal_uInt16 nId = pMenu->GetCurItemId();
315 if ( nId <= MN_CALC_ROUND )
317 String aTmp( OUString::createFromAscii(aStrArr[nId - 1]) );
318 aTmp += ' ';
319 aEdit.ReplaceSelected( aTmp );
321 return 0;
324 IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl)
326 sal_uInt16 nCurID = GetCurItemId();
327 EndSelection(); // reset back CurItemId !
328 switch ( nCurID )
330 case FN_FORMULA_CALC :
332 aPopMenu.Execute( this, GetItemRect( FN_FORMULA_CALC ), POPUPMENU_NOMOUSEUPCLOSE );
333 break;
334 default:
335 break;
339 return sal_True;
342 void SwInputWindow::Click( )
344 sal_uInt16 nCurID = GetCurItemId();
345 EndSelection(); // reset back CurItemId !
346 switch ( nCurID )
348 case FN_FORMULA_CANCEL:
350 CancelFormula();
352 break;
353 case FN_FORMULA_APPLY:
355 ApplyFormula();
357 break;
361 void SwInputWindow::ApplyFormula()
363 pView->GetViewFrame()->GetDispatcher()->Lock(sal_False);
364 pView->GetEditWin().LockKeyInput(sal_False);
365 CleanupUglyHackWithUndo();
366 pWrtShell->Pop( sal_False );
368 // Formular should always begin with "=", so remove it here again
369 String sEdit(comphelper::string::strip(aEdit.GetText(), ' '));
370 if( sEdit.Len() && '=' == sEdit.GetChar( 0 ) )
371 sEdit.Erase( 0, 1 );
372 SfxStringItem aParam(FN_EDIT_FORMULA, sEdit);
374 pWrtShell->EndSelTblCells();
375 pView->GetEditWin().GrabFocus();
376 const SfxPoolItem* aArgs[2];
377 aArgs[0] = &aParam;
378 aArgs[1] = 0;
379 pView->GetViewFrame()->GetBindings().Execute( FN_EDIT_FORMULA, aArgs, 0, SFX_CALLMODE_ASYNCHRON );
382 void SwInputWindow::CancelFormula()
384 if(pView)
386 pView->GetViewFrame()->GetDispatcher()->Lock( sal_False );
387 pView->GetEditWin().LockKeyInput(sal_False);
388 CleanupUglyHackWithUndo();
389 pWrtShell->Pop( sal_False );
391 if( bDelSel )
392 pWrtShell->EnterStdMode();
394 pWrtShell->EndSelTblCells();
396 pView->GetEditWin().GrabFocus();
398 pView->GetViewFrame()->GetDispatcher()->Execute( FN_EDIT_FORMULA, SFX_CALLMODE_ASYNCHRON);
401 const sal_Unicode CH_LRE = 0x202a;
402 const sal_Unicode CH_PDF = 0x202c;
404 IMPL_LINK( SwInputWindow, SelTblCellsNotify, SwWrtShell *, pCaller )
406 if(bIsTable)
408 SwFrmFmt* pTblFmt = pCaller->GetTableFmt();
409 String sBoxNms( pCaller->GetBoxNms() );
410 String sTblNm;
411 if( pTblFmt && aAktTableName != pTblFmt->GetName() )
412 sTblNm = pTblFmt->GetName();
414 aEdit.UpdateRange( sBoxNms, sTblNm );
416 String sNew;
417 sNew += CH_LRE;
418 sNew += aEdit.GetText();
419 sNew += CH_PDF;
421 if( sNew != sOldFml )
423 // The WrtShell is in the table selection,
424 // then cancel the table selection otherwise, the cursor is
425 // positioned "in the forest" and the live update does not work!
426 pWrtShell->StartAllAction();
428 SwPaM aPam( *pWrtShell->GetStkCrsr()->GetPoint() );
429 aPam.Move( fnMoveBackward, fnGoSection );
430 aPam.SetMark();
431 aPam.Move( fnMoveForward, fnGoSection );
433 IDocumentContentOperations* pIDCO = pWrtShell->getIDocumentContentOperations();
434 pIDCO->DeleteRange( aPam );
435 pIDCO->InsertString( aPam, sNew );
436 pWrtShell->EndAllAction();
437 sOldFml = sNew;
440 else
441 aEdit.GrabFocus();
442 return 0;
446 void SwInputWindow::SetFormula( const String& rFormula, sal_Bool bDelFlag )
448 String sEdit = OUString('=');
449 if( rFormula.Len() )
451 if( '=' == rFormula.GetChar( 0 ) )
452 sEdit = rFormula;
453 else
454 sEdit += rFormula;
456 aEdit.SetText( sEdit );
457 aEdit.SetSelection( Selection( sEdit.Len(), sEdit.Len() ) );
458 aEdit.Invalidate();
459 bDelSel = bDelFlag;
462 IMPL_LINK_NOARG(SwInputWindow, ModifyHdl)
464 if (bIsTable && m_bResetUndo)
466 pWrtShell->StartAllAction();
467 DelBoxCntnt();
468 String sNew;
469 sNew += CH_LRE;
470 sNew += aEdit.GetText();
471 sNew += CH_PDF;
472 pWrtShell->SwEditShell::Insert2( sNew );
473 pWrtShell->EndAllAction();
474 sOldFml = sNew;
476 return 0;
480 void SwInputWindow::DelBoxCntnt()
482 if( bIsTable )
484 pWrtShell->StartAllAction();
485 pWrtShell->ClearMark();
486 pWrtShell->Pop( sal_False );
487 pWrtShell->Push();
488 pWrtShell->MoveSection( fnSectionCurr, fnSectionStart );
489 pWrtShell->SetMark();
490 pWrtShell->MoveSection( fnSectionCurr, fnSectionEnd );
491 pWrtShell->SwEditShell::Delete();
492 pWrtShell->EndAllAction();
496 void InputEdit::KeyInput(const KeyEvent& rEvent)
498 const KeyCode aCode = rEvent.GetKeyCode();
499 if(aCode == KEY_RETURN || aCode == KEY_F2 )
500 ((SwInputWindow*)GetParent())->ApplyFormula();
501 else if(aCode == KEY_ESCAPE )
502 ((SwInputWindow*)GetParent())->CancelFormula();
503 else
504 Edit::KeyInput(rEvent);
507 void InputEdit::UpdateRange(const String& rBoxes,
508 const String& rName )
510 if( !rBoxes.Len() )
512 GrabFocus();
513 return;
515 const sal_Unicode cOpen = '<', cClose = '>',
516 cOpenBracket = '(';
517 String aPrefix = rName;
518 if(rName.Len())
519 aPrefix += '.';
520 String aBoxes = aPrefix;
521 aBoxes += rBoxes;
522 Selection aSelection(GetSelection());
523 sal_uInt16 nSel = (sal_uInt16) aSelection.Len();
524 // OS: The following expression ensures that in the overwrite mode,
525 // the selected closing parenthesis will be not deleted.
526 if( nSel && ( nSel > 1 ||
527 GetText()[ (sal_uInt16)aSelection.Min() ] != cClose ))
528 Cut();
529 else
530 aSelection.Max() = aSelection.Min();
531 String aActText(GetText());
532 const sal_uInt16 nLen = aActText.Len();
533 if( !nLen )
535 String aStr = OUStringBuffer().
536 append(cOpen).append(aBoxes).append(cClose).
537 makeStringAndClear();
538 SetText(aStr);
539 sal_uInt16 nPos = aStr.Search( cClose );
540 OSL_ENSURE(nPos < aStr.Len(), "delimiter not found");
541 ++nPos;
542 SetSelection( Selection( nPos, nPos ));
544 else
546 bool bFound = false;
547 sal_Unicode cCh;
548 sal_uInt16 nPos, nEndPos = 0, nStartPos = (sal_uInt16) aSelection.Min();
549 if( nStartPos-- )
551 do {
552 if( cOpen == (cCh = aActText.GetChar( nStartPos ) ) ||
553 cOpenBracket == cCh )
555 bFound = cCh == cOpen;
556 break;
558 } while( nStartPos-- > 0 );
560 if( bFound )
562 bFound = false;
563 nEndPos = nStartPos;
564 while( nEndPos < nLen )
566 if( cClose == (cCh = aActText.GetChar( nEndPos )))
568 bFound = true;
569 break;
571 ++nEndPos;
573 // Only if the current position lies in the range or right behind.
574 if( bFound && !( nStartPos < (sal_uInt16)aSelection.Max() &&
575 (sal_uInt16)aSelection.Max() <= nEndPos + 1 ))
576 bFound = false;
578 if( bFound )
580 nPos = ++nStartPos + 1; // We want behind
581 aActText.Erase( nStartPos, nEndPos - nStartPos );
582 aActText.Insert( aBoxes, nStartPos );
583 nPos = nPos + aBoxes.Len();
585 else
587 OUString aTmp = OUStringBuffer().
588 append(cOpen).append(aBoxes).append(cClose).
589 makeStringAndClear();
590 nPos = (sal_uInt16)aSelection.Min();
591 aActText.Insert( aTmp, nPos );
592 nPos = nPos + aTmp.getLength();
594 if( GetText() != OUString(aActText) )
596 SetText( aActText );
597 SetSelection( Selection( nPos, nPos ) );
600 GrabFocus();
604 SwInputChild::SwInputChild(Window* _pParent,
605 sal_uInt16 nId,
606 SfxBindings* pBindings,
607 SfxChildWinInfo* ) :
608 SfxChildWindow( _pParent, nId )
610 pDispatch = pBindings->GetDispatcher();
611 pWindow = new SwInputWindow( _pParent, pBindings );
612 ((SwInputWindow*)pWindow)->ShowWin();
613 eChildAlignment = SFX_ALIGN_LOWESTTOP;
616 SwInputChild::~SwInputChild()
618 if(pDispatch)
619 pDispatch->Lock(sal_False);
623 SfxChildWinInfo SwInputChild::GetInfo() const
625 SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); \
626 return aInfo;
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */