Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <algorithm>
21 :
22 : #include "scitems.hxx"
23 : #include <editeng/eeitem.hxx>
24 :
25 : #include <sfx2/app.hxx>
26 : #include <editeng/adjustitem.hxx>
27 : #include <editeng/editview.hxx>
28 : #include <editeng/editstat.hxx>
29 : #include <editeng/frmdiritem.hxx>
30 : #include <editeng/lspcitem.hxx>
31 : #include <sfx2/bindings.hxx>
32 : #include <sfx2/viewfrm.hxx>
33 : #include <sfx2/dispatch.hxx>
34 : #include <sfx2/event.hxx>
35 : #include <sfx2/imgmgr.hxx>
36 : #include <stdlib.h>
37 : #include <editeng/scriptspaceitem.hxx>
38 : #include <editeng/scripttypeitem.hxx>
39 : #include <vcl/cursor.hxx>
40 : #include <vcl/help.hxx>
41 : #include <vcl/settings.hxx>
42 : #include <svl/stritem.hxx>
43 :
44 : #include "inputwin.hxx"
45 : #include "scmod.hxx"
46 : #include "uiitems.hxx"
47 : #include "global.hxx"
48 : #include "scresid.hxx"
49 : #include "sc.hrc"
50 : #include "globstr.hrc"
51 : #include "reffact.hxx"
52 : #include "editutil.hxx"
53 : #include "inputhdl.hxx"
54 : #include "tabvwsh.hxx"
55 : #include "document.hxx"
56 : #include "docsh.hxx"
57 : #include "appoptio.hxx"
58 : #include "rangenam.hxx"
59 : #include <formula/compiler.hrc>
60 : #include "dbdata.hxx"
61 : #include "rangeutl.hxx"
62 : #include "docfunc.hxx"
63 : #include "funcdesc.hxx"
64 : #include "markdata.hxx"
65 : #include <editeng/fontitem.hxx>
66 : #include <com/sun/star/accessibility/XAccessible.hpp>
67 : #include "AccessibleEditObject.hxx"
68 : #include "AccessibleText.hxx"
69 : #include <svtools/miscopt.hxx>
70 : #include <comphelper/string.hxx>
71 : #include <com/sun/star/frame/XLayoutManager.hpp>
72 : #include <com/sun/star/frame/XModel.hpp>
73 : #include <com/sun/star/frame/XController.hpp>
74 :
75 : #define THESIZE 1000000 // Should be more than enough!
76 : #define TBX_WINDOW_HEIGHT 22 // in pixel - TODO: The same on all systems?
77 : #define LEFT_OFFSET 5
78 : #define INPUTWIN_MULTILINES 6
79 : const long BUTTON_OFFSET = 2; ///< space between input line and the button to expand / collapse
80 : const long ADDITIONAL_BORDER = 1; ///< height of the line at the bottom
81 : const long ADDITIONAL_SPACE = 4; ///< additional vertical space when the multiline edit has more lines
82 :
83 : using com::sun::star::uno::Reference;
84 : using com::sun::star::uno::UNO_QUERY;
85 :
86 : using com::sun::star::frame::XLayoutManager;
87 : using com::sun::star::frame::XModel;
88 : using com::sun::star::frame::XFrame;
89 : using com::sun::star::frame::XController;
90 : using com::sun::star::beans::XPropertySet;
91 :
92 : enum ScNameInputType
93 : {
94 : SC_NAME_INPUT_CELL,
95 : SC_NAME_INPUT_RANGE,
96 : SC_NAME_INPUT_NAMEDRANGE,
97 : SC_NAME_INPUT_DATABASE,
98 : SC_NAME_INPUT_ROW,
99 : SC_NAME_INPUT_SHEET,
100 : SC_NAME_INPUT_DEFINE,
101 : SC_NAME_INPUT_BAD_NAME,
102 : SC_NAME_INPUT_BAD_SELECTION,
103 : SC_MANAGE_NAMES
104 : };
105 :
106 676 : ScTextWndBase::ScTextWndBase( vcl::Window* pParent, WinBits nStyle )
107 676 : : Window ( pParent, nStyle )
108 : {
109 676 : if ( IsNativeControlSupported( CTRL_EDITBOX, PART_ENTIRE_CONTROL ) )
110 : {
111 0 : SetType( WINDOW_CALCINPUTLINE );
112 0 : SetBorderStyle( WindowBorderStyle::NWF );
113 : }
114 676 : }
115 :
116 : // class ScInputWindowWrapper
117 :
118 390 : SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper,FID_INPUTLINE_STATUS)
119 :
120 338 : ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window* pParentP,
121 : sal_uInt16 nId,
122 : SfxBindings* pBindings,
123 : SfxChildWinInfo* /* pInfo */ )
124 338 : : SfxChildWindow( pParentP, nId )
125 : {
126 338 : VclPtr<ScInputWindow> pWin=VclPtr<ScInputWindow>::Create( pParentP, pBindings );
127 338 : pWindow = pWin;
128 :
129 338 : pWin->Show();
130 :
131 338 : pWin->SetSizePixel( pWin->CalcWindowSizePixel() );
132 :
133 338 : eChildAlignment = SfxChildAlignment::LOWESTTOP;
134 338 : pBindings->Invalidate( FID_TOGGLEINPUTLINE );
135 338 : }
136 :
137 : /**
138 : * GetInfo is disposed of if there's a SFX_IMPL_TOOLBOX!
139 : */
140 346 : SfxChildWinInfo ScInputWindowWrapper::GetInfo() const
141 : {
142 346 : SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
143 346 : return aInfo;
144 : }
145 :
146 : #define IMAGE(id) pImgMgr->SeekImage(id)
147 676 : static inline bool lcl_isExperimentalMode()
148 : {
149 : // make inputbar feature on by default, leave the switch for the
150 : // moment in case we need to back it out easily
151 676 : return true;
152 : }
153 :
154 : // class ScInputWindow
155 :
156 338 : static VclPtr<ScTextWndBase> lcl_chooseRuntimeImpl( vcl::Window* pParent, SfxBindings* pBind )
157 : {
158 338 : ScTabViewShell* pViewSh = NULL;
159 338 : SfxDispatcher* pDisp = pBind->GetDispatcher();
160 338 : if ( pDisp )
161 : {
162 338 : SfxViewFrame* pViewFrm = pDisp->GetFrame();
163 338 : if ( pViewFrm )
164 338 : pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
165 : }
166 :
167 338 : if ( !lcl_isExperimentalMode() )
168 0 : return VclPtr<ScTextWnd>::Create( pParent, pViewSh );
169 338 : return VclPtr<ScInputBarGroup>::Create( pParent, pViewSh );
170 : }
171 :
172 338 : ScInputWindow::ScInputWindow( vcl::Window* pParent, SfxBindings* pBind ) :
173 : // With WB_CLIPCHILDREN otherwise we get flickering
174 : ToolBox ( pParent, WinBits(WB_CLIPCHILDREN) ),
175 : aWndPos ( VclPtr<ScPosWnd>::Create(this) ),
176 : pRuntimeWindow ( lcl_chooseRuntimeImpl( this, pBind ) ),
177 338 : aTextWindow ( *pRuntimeWindow ),
178 : pInputHdl ( NULL ),
179 : aTextOk ( ScResId( SCSTR_QHELP_BTNOK ) ), // Not always new as a Resource
180 : aTextCancel ( ScResId( SCSTR_QHELP_BTNCANCEL ) ),
181 : aTextSum ( ScResId( SCSTR_QHELP_BTNSUM ) ),
182 : aTextEqual ( ScResId( SCSTR_QHELP_BTNEQUAL ) ),
183 : mnMaxY (0),
184 : bIsOkCancelMode ( false ),
185 : bInResize ( false ),
186 676 : mbIsMultiLine ( lcl_isExperimentalMode() )
187 : {
188 338 : ScModule* pScMod = SC_MOD();
189 338 : SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
190 :
191 : // #i73615# don't rely on SfxViewShell::Current while constructing the input line
192 : // (also for GetInputHdl below)
193 338 : ScTabViewShell* pViewSh = NULL;
194 338 : SfxDispatcher* pDisp = pBind->GetDispatcher();
195 338 : if ( pDisp )
196 : {
197 338 : SfxViewFrame* pViewFrm = pDisp->GetFrame();
198 338 : if ( pViewFrm )
199 338 : pViewSh = PTR_CAST( ScTabViewShell, pViewFrm->GetViewShell() );
200 : }
201 : OSL_ENSURE( pViewSh, "no view shell for input window" );
202 :
203 : // Position window, 3 buttons, input window
204 338 : InsertWindow (1, aWndPos.get(), ToolBoxItemBits::NONE, 0);
205 338 : InsertSeparator (1);
206 338 : InsertItem (SID_INPUT_FUNCTION, IMAGE(SID_INPUT_FUNCTION), ToolBoxItemBits::NONE, 2);
207 338 : InsertItem (SID_INPUT_SUM, IMAGE(SID_INPUT_SUM), ToolBoxItemBits::NONE, 3);
208 338 : InsertItem (SID_INPUT_EQUAL, IMAGE(SID_INPUT_EQUAL), ToolBoxItemBits::NONE, 4);
209 338 : InsertSeparator (5);
210 338 : InsertWindow (7, &aTextWindow, ToolBoxItemBits::NONE, 6);
211 :
212 338 : aWndPos ->SetQuickHelpText(ScResId(SCSTR_QHELP_POSWND));
213 338 : aWndPos ->SetHelpId (HID_INSWIN_POS);
214 338 : aTextWindow.SetQuickHelpText(ScResId(SCSTR_QHELP_INPUTWND));
215 338 : aTextWindow.SetHelpId (HID_INSWIN_INPUT);
216 :
217 : // No SetHelpText: the helptexts come from the Help
218 338 : SetItemText (SID_INPUT_FUNCTION, ScResId(SCSTR_QHELP_BTNCALC));
219 338 : SetHelpId (SID_INPUT_FUNCTION, HID_INSWIN_CALC);
220 :
221 338 : SetItemText (SID_INPUT_SUM, aTextSum);
222 338 : SetHelpId (SID_INPUT_SUM, HID_INSWIN_SUMME);
223 :
224 338 : SetItemText (SID_INPUT_EQUAL, aTextEqual);
225 338 : SetHelpId (SID_INPUT_EQUAL, HID_INSWIN_FUNC);
226 :
227 338 : SetHelpId( HID_SC_INPUTWIN ); // For the whole input row
228 :
229 338 : aWndPos ->Show();
230 338 : aTextWindow.Show();
231 :
232 338 : pInputHdl = SC_MOD()->GetInputHdl( pViewSh, false ); // use own handler even if ref-handler is set
233 338 : if (pInputHdl)
234 338 : pInputHdl->SetInputWindow( this );
235 :
236 338 : if (pInputHdl && !pInputHdl->GetFormString().isEmpty())
237 : {
238 : // Switch over while the Function AutoPilot is active
239 : // -> show content of the Function AutoPilot again
240 : // Also show selection (remember at the InputHdl)
241 0 : aTextWindow.SetTextString( pInputHdl->GetFormString() );
242 : }
243 338 : else if (pInputHdl && pInputHdl->IsInputMode())
244 : {
245 : // If the input row was hidden while editing (e.g. when editing a formula
246 : // and then switching to another document or the help), display the text
247 : // we just edited from the InputHandler
248 0 : aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Dispaly text
249 0 : if ( pInputHdl->IsTopMode() )
250 0 : pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus ends up at the bottom anyways
251 : }
252 338 : else if (pViewSh)
253 338 : pViewSh->UpdateInputHandler(true); // Absolutely necessary update
254 :
255 338 : pImgMgr->RegisterToolBox(this);
256 338 : SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULA));
257 338 : }
258 :
259 1008 : ScInputWindow::~ScInputWindow()
260 : {
261 336 : disposeOnce();
262 672 : }
263 :
264 336 : void ScInputWindow::dispose()
265 : {
266 336 : bool bDown = ( ScGlobal::pSysLocale == NULL ); // after Clear?
267 :
268 : // if any view's input handler has a pointer to this input window, reset it
269 : // (may be several ones, #74522#)
270 : // member pInputHdl is not used here
271 :
272 336 : if ( !bDown )
273 : {
274 336 : TypeId aScType = TYPE(ScTabViewShell);
275 336 : SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
276 1017 : while ( pSh )
277 : {
278 345 : ScInputHandler* pHdl = static_cast<ScTabViewShell*>(pSh)->GetInputHandler();
279 345 : if ( pHdl && pHdl->GetInputWindow() == this )
280 : {
281 336 : pHdl->SetInputWindow( NULL );
282 336 : pHdl->StopInputWinEngine( false ); // reset pTopView pointer
283 : }
284 345 : pSh = SfxViewShell::GetNext( *pSh, &aScType );
285 : }
286 : }
287 :
288 336 : SfxImageManager::GetImageManager( *SC_MOD() )->ReleaseToolBox( this );
289 :
290 336 : pRuntimeWindow.disposeAndClear();
291 336 : aWndPos.disposeAndClear();
292 :
293 336 : ToolBox::dispose();
294 336 : }
295 :
296 150 : void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
297 : {
298 : // Is called in the Activate of the View ...
299 150 : if ( pNew != pInputHdl )
300 : {
301 : // On Reload (last version) the pInputHdl is the InputHandler of the old, deleted
302 : // ViewShell: so don't touch it here!
303 0 : pInputHdl = pNew;
304 0 : if (pInputHdl)
305 0 : pInputHdl->SetInputWindow( this );
306 : }
307 150 : }
308 :
309 0 : bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList)
310 : {
311 0 : bool bSubTotal = false;
312 0 : ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
313 0 : if ( pViewSh )
314 : {
315 0 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
316 0 : size_t nRangeCount (pRangeList->size());
317 0 : size_t nRangeIndex (0);
318 0 : while (!bSubTotal && nRangeIndex < nRangeCount)
319 : {
320 0 : const ScRange* pRange = (*pRangeList)[nRangeIndex];
321 0 : if( pRange )
322 : {
323 0 : SCTAB nTabEnd(pRange->aEnd.Tab());
324 0 : SCTAB nTab(pRange->aStart.Tab());
325 0 : while (!bSubTotal && nTab <= nTabEnd)
326 : {
327 0 : SCROW nRowEnd(pRange->aEnd.Row());
328 0 : SCROW nRow(pRange->aStart.Row());
329 0 : while (!bSubTotal && nRow <= nRowEnd)
330 : {
331 0 : if (pDoc->RowFiltered(nRow, nTab))
332 0 : bSubTotal = true;
333 : else
334 0 : ++nRow;
335 : }
336 0 : ++nTab;
337 : }
338 : }
339 0 : ++nRangeIndex;
340 : }
341 :
342 0 : const ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
343 0 : ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
344 0 : for (; !bSubTotal && itr != itrEnd; ++itr)
345 : {
346 0 : const ScDBData& rDB = *itr;
347 0 : if (!rDB.HasAutoFilter())
348 0 : continue;
349 :
350 0 : nRangeIndex = 0;
351 0 : while (!bSubTotal && nRangeIndex < nRangeCount)
352 : {
353 0 : const ScRange* pRange = (*pRangeList)[nRangeIndex];
354 0 : if( pRange )
355 : {
356 0 : ScRange aDBArea;
357 0 : rDB.GetArea(aDBArea);
358 0 : if (aDBArea.Intersects(*pRange))
359 0 : bSubTotal = true;
360 : }
361 0 : ++nRangeIndex;
362 : }
363 : }
364 : }
365 0 : return bSubTotal;
366 : }
367 :
368 0 : void ScInputWindow::Select()
369 : {
370 0 : ScModule* pScMod = SC_MOD();
371 0 : ToolBox::Select();
372 :
373 0 : switch ( GetCurItemId() )
374 : {
375 : case SID_INPUT_FUNCTION:
376 : {
377 : //! new method at ScModule to query if function autopilot is open
378 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
379 0 : if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
380 : {
381 : pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
382 0 : SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
383 :
384 : // The Toolbox will be disabled anyways, so we don't need to switch here,
385 : // regardless whether it succeeded or not!
386 : // SetOkCancelMode();
387 : }
388 : }
389 0 : break;
390 :
391 : case SID_INPUT_CANCEL:
392 0 : pScMod->InputCancelHandler();
393 0 : SetSumAssignMode();
394 0 : break;
395 :
396 : case SID_INPUT_OK:
397 0 : pScMod->InputEnterHandler();
398 0 : SetSumAssignMode();
399 0 : aTextWindow.Invalidate(); // Or else the Selection remains
400 0 : break;
401 :
402 : case SID_INPUT_SUM:
403 : {
404 0 : ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
405 0 : if ( pViewSh )
406 : {
407 0 : const ScMarkData& rMark = pViewSh->GetViewData().GetMarkData();
408 0 : if ( rMark.IsMarked() || rMark.IsMultiMarked() )
409 : {
410 0 : ScRangeList aMarkRangeList;
411 0 : rMark.FillRangeListWithMarks( &aMarkRangeList, false );
412 0 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
413 :
414 : // check if one of the marked ranges is empty
415 0 : bool bEmpty = false;
416 0 : const size_t nCount = aMarkRangeList.size();
417 0 : for ( size_t i = 0; i < nCount; ++i )
418 : {
419 0 : const ScRange aRange( *aMarkRangeList[i] );
420 0 : if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
421 0 : aRange.aStart.Col(), aRange.aStart.Row(),
422 0 : aRange.aEnd.Col(), aRange.aEnd.Row() ) )
423 : {
424 0 : bEmpty = true;
425 0 : break;
426 : }
427 : }
428 :
429 0 : if ( bEmpty )
430 : {
431 0 : ScRangeList aRangeList;
432 0 : const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
433 0 : if ( bDataFound )
434 : {
435 0 : ScAddress aAddr = aRangeList.back()->aEnd;
436 0 : aAddr.IncRow();
437 0 : const bool bSubTotal( UseSubTotal( &aRangeList ) );
438 0 : pViewSh->EnterAutoSum( aRangeList, bSubTotal, aAddr );
439 0 : }
440 : }
441 : else
442 : {
443 0 : const bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
444 0 : for ( size_t i = 0; i < nCount; ++i )
445 : {
446 0 : const ScRange aRange( *aMarkRangeList[i] );
447 0 : const bool bSetCursor = ( i == nCount - 1 );
448 0 : const bool bContinue = ( i != 0 );
449 0 : if ( !pViewSh->AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
450 : {
451 0 : pViewSh->MarkRange( aRange, false, false );
452 0 : pViewSh->SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
453 0 : const ScRangeList aRangeList;
454 0 : ScAddress aAddr = aRange.aEnd;
455 0 : aAddr.IncRow();
456 : const OUString aFormula = pViewSh->GetAutoSumFormula(
457 0 : aRangeList, bSubTotal, aAddr );
458 0 : SetFuncString( aFormula );
459 0 : break;
460 : }
461 : }
462 0 : }
463 : }
464 : else // Only insert into input row
465 : {
466 0 : ScRangeList aRangeList;
467 0 : const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
468 0 : const bool bSubTotal( UseSubTotal( &aRangeList ) );
469 0 : ScAddress aAddr = pViewSh->GetViewData().GetCurPos();
470 0 : const OUString aFormula = pViewSh->GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
471 0 : SetFuncString( aFormula );
472 :
473 0 : if ( bDataFound && pScMod->IsEditMode() )
474 : {
475 0 : ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
476 0 : if ( pHdl )
477 : {
478 0 : pHdl->InitRangeFinder( aFormula );
479 :
480 : //! SetSelection at the InputHandler?
481 : //! Set bSelIsRef?
482 0 : const sal_Int32 nOpen = aFormula.indexOf('(');
483 0 : const sal_Int32 nLen = aFormula.getLength();
484 0 : if ( nOpen != -1 && nLen > nOpen )
485 : {
486 0 : sal_uInt8 nAdd(1);
487 0 : if (bSubTotal)
488 0 : nAdd = 3;
489 0 : ESelection aSel(0,nOpen+nAdd,0,nLen-1);
490 0 : EditView* pTableView = pHdl->GetTableView();
491 0 : if (pTableView)
492 0 : pTableView->SetSelection(aSel);
493 0 : EditView* pTopView = pHdl->GetTopView();
494 0 : if (pTopView)
495 0 : pTopView->SetSelection(aSel);
496 : }
497 : }
498 0 : }
499 : }
500 : }
501 : }
502 0 : break;
503 :
504 : case SID_INPUT_EQUAL:
505 : {
506 0 : aTextWindow.StartEditEngine();
507 0 : if ( pScMod->IsEditMode() ) // Isn't if e.g. protected
508 : {
509 0 : aTextWindow.StartEditEngine();
510 :
511 0 : sal_Int32 nStartPos = 1;
512 0 : sal_Int32 nEndPos = 1;
513 :
514 0 : ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
515 0 : if ( pViewSh )
516 : {
517 0 : const OUString& rString = aTextWindow.GetTextString();
518 0 : const sal_Int32 nLen = rString.getLength();
519 :
520 0 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
521 0 : CellType eCellType = pDoc->GetCellType( pViewSh->GetViewData().GetCurPos() );
522 0 : switch ( eCellType )
523 : {
524 : case CELLTYPE_VALUE:
525 : {
526 0 : nEndPos = nLen + 1;
527 0 : aTextWindow.SetTextString("=" + rString);
528 0 : break;
529 : }
530 : case CELLTYPE_STRING:
531 : case CELLTYPE_EDIT:
532 0 : nStartPos = 0;
533 0 : nEndPos = nLen;
534 0 : break;
535 : case CELLTYPE_FORMULA:
536 0 : nEndPos = nLen;
537 0 : break;
538 : default:
539 0 : aTextWindow.SetTextString("=");
540 0 : break;
541 : }
542 : }
543 :
544 0 : EditView* pView = aTextWindow.GetEditView();
545 0 : if (pView)
546 : {
547 0 : pView->SetSelection( ESelection(0, nStartPos, 0, nEndPos) );
548 0 : pScMod->InputChanged(pView);
549 0 : SetOkCancelMode();
550 0 : pView->SetEditEngineUpdateMode(true);
551 : }
552 : }
553 0 : break;
554 : }
555 : }
556 0 : }
557 :
558 190 : void ScInputWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
559 : {
560 190 : ToolBox::Paint(rRenderContext, rRect);
561 :
562 : // draw a line at the bottom to distinguish that from the grid
563 : // (we have space for that thanks to ADDITIONAL_BORDER)
564 190 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
565 190 : rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
566 :
567 190 : Size aSize = GetSizePixel();
568 190 : rRenderContext.DrawLine(Point(0, aSize.Height() - 1),
569 380 : Point(aSize.Width() - 1, aSize.Height() - 1));
570 190 : }
571 :
572 2178 : void ScInputWindow::Resize()
573 : {
574 2178 : ToolBox::Resize();
575 2178 : if ( mbIsMultiLine )
576 : {
577 2178 : aTextWindow.Resize();
578 2178 : Size aSize = GetSizePixel();
579 2178 : aSize.Height() = CalcWindowSizePixel().Height() + ADDITIONAL_BORDER;
580 2178 : ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
581 2178 : if ( pGroupBar )
582 : {
583 : // To ensure smooth display and prevent the items in the toolbar being
584 : // repositioned ( vertically ) we lock the vertical positioning of the toolbox
585 : // items when we are displaying > 1 line.
586 : // So, we need to adjust the height of the toolbox accordingly. If we don't
587 : // then the largest item ( e.g. the GroupBar window ) will actually be
588 : // positioned such that the toolbar will cut off the bottom of that item
589 2178 : if ( pGroupBar->GetNumLines() > 1 )
590 0 : aSize.Height() += pGroupBar->GetVertOffset() + ADDITIONAL_SPACE;
591 : }
592 2178 : SetSizePixel(aSize);
593 2178 : Invalidate();
594 : }
595 : else
596 : {
597 0 : long nWidth = GetSizePixel().Width();
598 0 : long nLeft = aTextWindow.GetPosPixel().X();
599 0 : Size aSize = aTextWindow.GetSizePixel();
600 :
601 0 : aSize.Width() = std::max( ((long)(nWidth - nLeft - 5)), (long)0 );
602 :
603 0 : aTextWindow.SetSizePixel( aSize );
604 0 : aTextWindow.Invalidate();
605 : }
606 2178 : }
607 :
608 0 : void ScInputWindow::SetFuncString( const OUString& rString, bool bDoEdit )
609 : {
610 : //! new method at ScModule to query if function autopilot is open
611 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
612 0 : EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
613 0 : aTextWindow.StartEditEngine();
614 :
615 0 : ScModule* pScMod = SC_MOD();
616 0 : if ( pScMod->IsEditMode() )
617 : {
618 0 : if ( bDoEdit )
619 0 : aTextWindow.GrabFocus();
620 0 : aTextWindow.SetTextString( rString );
621 0 : EditView* pView = aTextWindow.GetEditView();
622 0 : if (pView)
623 : {
624 0 : sal_Int32 nLen = rString.getLength();
625 :
626 0 : if ( nLen > 0 )
627 : {
628 0 : nLen--;
629 0 : pView->SetSelection( ESelection( 0, nLen, 0, nLen ) );
630 : }
631 :
632 0 : pScMod->InputChanged(pView);
633 0 : if ( bDoEdit )
634 0 : SetOkCancelMode(); // Not the case if immediately followed by Enter/Cancel
635 :
636 0 : pView->SetEditEngineUpdateMode(true);
637 : }
638 : }
639 0 : }
640 :
641 1316 : void ScInputWindow::SetPosString( const OUString& rStr )
642 : {
643 1316 : aWndPos->SetPos( rStr );
644 1316 : }
645 :
646 1074 : void ScInputWindow::SetTextString( const OUString& rString )
647 : {
648 1074 : if (rString.getLength() <= 32767)
649 1074 : aTextWindow.SetTextString(rString);
650 : else
651 0 : aTextWindow.SetTextString(rString.copy(0, 32767));
652 1074 : }
653 :
654 0 : void ScInputWindow::SetOkCancelMode()
655 : {
656 : //! new method at ScModule to query if function autopilot is open
657 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
658 0 : EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
659 :
660 0 : ScModule* pScMod = SC_MOD();
661 0 : SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
662 0 : if (!bIsOkCancelMode)
663 : {
664 0 : RemoveItem( 3 ); // Remove SID_INPUT_SUM and SID_INPUT_EQUAL
665 0 : RemoveItem( 3 );
666 0 : InsertItem( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ), ToolBoxItemBits::NONE, 3 );
667 0 : InsertItem( SID_INPUT_OK, IMAGE( SID_INPUT_OK ), ToolBoxItemBits::NONE, 4 );
668 0 : SetItemText ( SID_INPUT_CANCEL, aTextCancel );
669 0 : SetHelpId ( SID_INPUT_CANCEL, HID_INSWIN_CANCEL );
670 0 : SetItemText ( SID_INPUT_OK, aTextOk );
671 0 : SetHelpId ( SID_INPUT_OK, HID_INSWIN_OK );
672 0 : bIsOkCancelMode = true;
673 : }
674 0 : }
675 :
676 1311 : void ScInputWindow::SetSumAssignMode()
677 : {
678 : //! new method at ScModule to query if function autopilot is open
679 1311 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
680 1311 : EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) );
681 :
682 1311 : ScModule* pScMod = SC_MOD();
683 1311 : SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
684 1311 : if (bIsOkCancelMode)
685 : {
686 : // Remove SID_INPUT_CANCEL, and SID_INPUT_OK
687 0 : RemoveItem( 3 );
688 0 : RemoveItem( 3 );
689 0 : InsertItem( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ), ToolBoxItemBits::NONE, 3 );
690 0 : InsertItem( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ), ToolBoxItemBits::NONE, 4 );
691 0 : SetItemText ( SID_INPUT_SUM, aTextSum );
692 0 : SetHelpId ( SID_INPUT_SUM, HID_INSWIN_SUMME );
693 0 : SetItemText ( SID_INPUT_EQUAL, aTextEqual );
694 0 : SetHelpId ( SID_INPUT_EQUAL, HID_INSWIN_FUNC );
695 0 : bIsOkCancelMode = false;
696 :
697 0 : SetFormulaMode(false); // No editing -> no formula
698 : }
699 1311 : }
700 :
701 0 : void ScInputWindow::SetFormulaMode( bool bSet )
702 : {
703 0 : aWndPos->SetFormulaMode(bSet);
704 0 : aTextWindow.SetFormulaMode(bSet);
705 0 : }
706 :
707 0 : void ScInputWindow::SetText( const OUString& rString )
708 : {
709 0 : ToolBox::SetText(rString);
710 0 : }
711 :
712 338 : OUString ScInputWindow::GetText() const
713 : {
714 338 : return ToolBox::GetText();
715 : }
716 :
717 1958 : bool ScInputWindow::IsInputActive()
718 : {
719 1958 : return aTextWindow.IsInputActive();
720 : }
721 :
722 0 : EditView* ScInputWindow::GetEditView()
723 : {
724 0 : return aTextWindow.GetEditView();
725 : }
726 :
727 0 : void ScInputWindow::MakeDialogEditView()
728 : {
729 0 : aTextWindow.MakeDialogEditView();
730 0 : }
731 :
732 191 : void ScInputWindow::StopEditEngine( bool bAll )
733 : {
734 191 : aTextWindow.StopEditEngine( bAll );
735 191 : }
736 :
737 0 : void ScInputWindow::TextGrabFocus()
738 : {
739 0 : aTextWindow.TextGrabFocus();
740 0 : }
741 :
742 0 : void ScInputWindow::TextInvalidate()
743 : {
744 0 : aTextWindow.Invalidate();
745 0 : }
746 :
747 0 : void ScInputWindow::SwitchToTextWin()
748 : {
749 : // used for shift-ctrl-F2
750 :
751 0 : aTextWindow.StartEditEngine();
752 0 : if ( SC_MOD()->IsEditMode() )
753 : {
754 0 : aTextWindow.TextGrabFocus();
755 0 : EditView* pView = aTextWindow.GetEditView();
756 0 : if (pView)
757 : {
758 0 : sal_Int32 nPara = pView->GetEditEngine()->GetParagraphCount() ? ( pView->GetEditEngine()->GetParagraphCount() - 1 ) : 0;
759 0 : sal_Int32 nLen = pView->GetEditEngine()->GetTextLen( nPara );
760 0 : ESelection aSel( nPara, nLen, nPara, nLen );
761 0 : pView->SetSelection( aSel ); // set cursor to end of text
762 : }
763 : }
764 0 : }
765 :
766 0 : void ScInputWindow::PosGrabFocus()
767 : {
768 0 : aWndPos->GrabFocus();
769 0 : }
770 :
771 1311 : void ScInputWindow::EnableButtons( bool bEnable )
772 : {
773 : // when enabling buttons, always also enable the input window itself
774 1311 : if ( bEnable && !IsEnabled() )
775 2 : Enable();
776 :
777 1311 : EnableItem( SID_INPUT_FUNCTION, bEnable );
778 1311 : EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL : SID_INPUT_SUM, bEnable );
779 1311 : EnableItem( bIsOkCancelMode ? SID_INPUT_OK : SID_INPUT_EQUAL, bEnable );
780 : // Invalidate();
781 1311 : }
782 :
783 1462 : void ScInputWindow::StateChanged( StateChangedType nType )
784 : {
785 1462 : ToolBox::StateChanged( nType );
786 :
787 1462 : if ( nType == StateChangedType::InitShow ) Resize();
788 1462 : }
789 :
790 0 : void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt )
791 : {
792 0 : if ( rDCEvt.GetType() == DataChangedEventType::SETTINGS && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
793 : {
794 : // update item images
795 0 : ScModule* pScMod = SC_MOD();
796 0 : SfxImageManager* pImgMgr = SfxImageManager::GetImageManager(*pScMod);
797 :
798 : // IMAGE macro uses pScMod, pImgMg
799 0 : SetItemImage( SID_INPUT_FUNCTION, IMAGE( SID_INPUT_FUNCTION ) );
800 0 : if ( bIsOkCancelMode )
801 : {
802 0 : SetItemImage( SID_INPUT_CANCEL, IMAGE( SID_INPUT_CANCEL ) );
803 0 : SetItemImage( SID_INPUT_OK, IMAGE( SID_INPUT_OK ) );
804 : }
805 : else
806 : {
807 0 : SetItemImage( SID_INPUT_SUM, IMAGE( SID_INPUT_SUM ) );
808 0 : SetItemImage( SID_INPUT_EQUAL, IMAGE( SID_INPUT_EQUAL ) );
809 : }
810 : }
811 :
812 0 : ToolBox::DataChanged( rDCEvt );
813 0 : }
814 :
815 0 : bool ScInputWindow::IsPointerAtResizePos()
816 : {
817 0 : if ( GetOutputSizePixel().Height() - GetPointerPosPixel().Y() <= 4 )
818 0 : return true;
819 : else
820 0 : return false;
821 : }
822 :
823 0 : void ScInputWindow::MouseMove( const MouseEvent& rMEvt )
824 : {
825 0 : if ( mbIsMultiLine )
826 : {
827 0 : Point aPosPixel = GetPointerPosPixel();
828 :
829 0 : ScInputBarGroup* pGroupBar = dynamic_cast< ScInputBarGroup* > ( pRuntimeWindow.get() );
830 :
831 0 : if ( bInResize || IsPointerAtResizePos() )
832 0 : SetPointer( Pointer( PointerStyle::WindowSSize ) );
833 : else
834 0 : SetPointer( Pointer( PointerStyle::Arrow ) );
835 :
836 0 : if ( bInResize )
837 : {
838 : // detect direction
839 0 : long nResizeThreshold = ( (long)TBX_WINDOW_HEIGHT * 0.7 );
840 0 : bool bResetPointerPos = false;
841 :
842 : // Detect attempt to expand toolbar too much
843 0 : if ( aPosPixel.Y() >= mnMaxY )
844 : {
845 0 : bResetPointerPos = true;
846 0 : aPosPixel.Y() = mnMaxY;
847 : } // or expanding down
848 0 : else if ( GetOutputSizePixel().Height() - aPosPixel.Y() < -nResizeThreshold )
849 : {
850 0 : pGroupBar->IncrementVerticalSize();
851 0 : bResetPointerPos = true;
852 : } // or shrinking up
853 0 : else if ( ( GetOutputSizePixel().Height() - aPosPixel.Y() ) > nResizeThreshold )
854 : {
855 0 : bResetPointerPos = true;
856 0 : pGroupBar->DecrementVerticalSize();
857 : }
858 :
859 0 : if ( bResetPointerPos )
860 : {
861 0 : aPosPixel.Y() = GetOutputSizePixel().Height();
862 0 : SetPointerPosPixel( aPosPixel );
863 : }
864 : }
865 : }
866 0 : ToolBox::MouseMove( rMEvt );
867 0 : }
868 :
869 0 : void ScInputWindow::MouseButtonDown( const MouseEvent& rMEvt )
870 : {
871 0 : if ( mbIsMultiLine )
872 : {
873 0 : if ( rMEvt.IsLeft() )
874 : {
875 0 : if ( IsPointerAtResizePos() )
876 : {
877 : // Don't leave the mouse pointer leave *this* window
878 0 : CaptureMouse();
879 0 : bInResize = true;
880 :
881 : // find the height of the gridwin, we don't wan't to be
882 : // able to expand the toolbar too far so we need to
883 : // calculate an upper limit
884 : // I'd prefer to leave at least a single column header and a
885 : // row but I don't know how to get that value in pixels.
886 : // Use TBX_WINDOW_HEIGHT for the moment
887 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
888 0 : mnMaxY = GetOutputSizePixel().Height() + ( pViewSh->GetGridHeight(SC_SPLIT_TOP) + pViewSh->GetGridHeight(SC_SPLIT_BOTTOM) ) - TBX_WINDOW_HEIGHT;
889 : }
890 : }
891 : }
892 0 : ToolBox::MouseButtonDown( rMEvt );
893 0 : }
894 0 : void ScInputWindow::MouseButtonUp( const MouseEvent& rMEvt )
895 : {
896 0 : if ( mbIsMultiLine )
897 : {
898 0 : ReleaseMouse();
899 0 : if ( rMEvt.IsLeft() )
900 : {
901 0 : bInResize = false;
902 0 : mnMaxY = 0;
903 : }
904 : }
905 0 : ToolBox::MouseButtonUp( rMEvt );
906 0 : }
907 :
908 338 : ScInputBarGroup::ScInputBarGroup(vcl::Window* pParent, ScTabViewShell* pViewSh)
909 : : ScTextWndBase ( pParent, WinBits(WB_HIDE | WB_TABSTOP ) ),
910 : aMultiTextWnd ( VclPtr<ScMultiTextWnd>::Create(this, pViewSh) ),
911 : aButton ( VclPtr<ImageButton>::Create(this, WB_TABSTOP | WB_RECTSTYLE | WB_SMALLSTYLE) ),
912 : aScrollBar ( VclPtr<ScrollBar>::Create(this, WB_TABSTOP | WB_VERT | WB_DRAG) ),
913 338 : nVertOffset ( 0 )
914 : {
915 338 : aMultiTextWnd->Show();
916 338 : aMultiTextWnd->SetQuickHelpText( ScResId( SCSTR_QHELP_INPUTWND ) );
917 338 : aMultiTextWnd->SetHelpId( HID_INSWIN_INPUT );
918 :
919 338 : Size aSize( GetSettings().GetStyleSettings().GetScrollBarSize(), aMultiTextWnd->GetPixelHeightForLines(1) );
920 :
921 338 : aButton->SetClickHdl( LINK( this, ScInputBarGroup, ClickHdl ) );
922 338 : aButton->SetSizePixel( aSize );
923 338 : aButton->Enable();
924 338 : aButton->SetSymbol( SymbolType::SPIN_DOWN );
925 338 : aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
926 338 : aButton->Show();
927 :
928 338 : aScrollBar->SetSizePixel( aSize );
929 338 : aScrollBar->SetScrollHdl( LINK( this, ScInputBarGroup, Impl_ScrollHdl ) );
930 338 : }
931 :
932 1008 : ScInputBarGroup::~ScInputBarGroup()
933 : {
934 336 : disposeOnce();
935 672 : }
936 :
937 336 : void ScInputBarGroup::dispose()
938 : {
939 336 : aMultiTextWnd.disposeAndClear();
940 336 : aButton.disposeAndClear();
941 336 : aScrollBar.disposeAndClear();
942 336 : ScTextWndBase::dispose();
943 336 : }
944 :
945 : void
946 0 : ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
947 : {
948 0 : aMultiTextWnd->InsertAccessibleTextData( rTextData );
949 0 : }
950 :
951 : void
952 0 : ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
953 : {
954 0 : aMultiTextWnd->RemoveAccessibleTextData( rTextData );
955 0 : }
956 :
957 : const OUString&
958 0 : ScInputBarGroup::GetTextString() const
959 : {
960 0 : return aMultiTextWnd->GetTextString();
961 : }
962 :
963 1074 : void ScInputBarGroup::SetTextString( const OUString& rString )
964 : {
965 1074 : aMultiTextWnd->SetTextString(rString);
966 1074 : }
967 :
968 3716 : void ScInputBarGroup::Resize()
969 : {
970 3716 : vcl::Window*w = GetParent();
971 : ScInputWindow *pParent;
972 3716 : pParent = dynamic_cast<ScInputWindow*>(w);
973 :
974 3716 : if (pParent == NULL)
975 : {
976 : OSL_FAIL("The parent window pointer pParent is null");
977 3716 : return;
978 : }
979 :
980 3716 : long nWidth = pParent->GetSizePixel().Width();
981 3716 : long nLeft = GetPosPixel().X();
982 :
983 3716 : Size aSize = GetSizePixel();
984 3716 : aSize.Width() = std::max(long(nWidth - nLeft - LEFT_OFFSET), long(0));
985 :
986 3716 : aScrollBar->SetPosPixel(Point( aSize.Width() - aButton->GetSizePixel().Width(), aButton->GetSizePixel().Height() ) );
987 :
988 3716 : Size aTmpSize( aSize );
989 3716 : aTmpSize.Width() = aTmpSize.Width() - aButton->GetSizePixel().Width() - BUTTON_OFFSET;
990 3716 : aMultiTextWnd->SetSizePixel(aTmpSize);
991 :
992 3716 : aMultiTextWnd->Resize();
993 :
994 3716 : aSize.Height() = aMultiTextWnd->GetSizePixel().Height();
995 :
996 3716 : SetSizePixel(aSize);
997 :
998 3716 : if (aMultiTextWnd->GetNumLines() > 1)
999 : {
1000 0 : aButton->SetSymbol( SymbolType::SPIN_UP );
1001 0 : aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_COLLAPSE_FORMULA ) );
1002 0 : Size scrollSize = aButton->GetSizePixel();
1003 0 : scrollSize.Height() = aMultiTextWnd->GetSizePixel().Height() - aButton->GetSizePixel().Height();
1004 0 : aScrollBar->SetSizePixel( scrollSize );
1005 :
1006 0 : Size aOutSz = aMultiTextWnd->GetOutputSize();
1007 :
1008 0 : aScrollBar->SetVisibleSize( aOutSz.Height() );
1009 0 : aScrollBar->SetPageSize( aOutSz.Height() );
1010 0 : aScrollBar->SetLineSize( aMultiTextWnd->GetTextHeight() );
1011 0 : aScrollBar->SetRange( Range( 0, aMultiTextWnd->GetEditEngTxtHeight() ) );
1012 :
1013 0 : aScrollBar->Resize();
1014 0 : aScrollBar->Show();
1015 : }
1016 : else
1017 : {
1018 3716 : aButton->SetSymbol( SymbolType::SPIN_DOWN );
1019 3716 : aButton->SetQuickHelpText( ScResId( SCSTR_QHELP_EXPAND_FORMULA ) );
1020 3716 : aScrollBar->Hide();
1021 : }
1022 :
1023 3716 : aButton->SetPosPixel(Point(aSize.Width() - aButton->GetSizePixel().Width(), 0));
1024 :
1025 3716 : Invalidate();
1026 : }
1027 :
1028 191 : void ScInputBarGroup::StopEditEngine( bool bAll )
1029 : {
1030 191 : aMultiTextWnd->StopEditEngine( bAll );
1031 191 : }
1032 :
1033 0 : void ScInputBarGroup::StartEditEngine()
1034 : {
1035 0 : aMultiTextWnd->StartEditEngine();
1036 0 : }
1037 :
1038 0 : void ScInputBarGroup::MakeDialogEditView()
1039 : {
1040 0 : aMultiTextWnd->MakeDialogEditView();
1041 0 : }
1042 :
1043 0 : EditView* ScInputBarGroup::GetEditView()
1044 : {
1045 0 : return aMultiTextWnd->GetEditView();
1046 : }
1047 :
1048 1958 : bool ScInputBarGroup::IsInputActive()
1049 : {
1050 1958 : return aMultiTextWnd->IsInputActive();
1051 : }
1052 :
1053 0 : void ScInputBarGroup::SetFormulaMode(bool bSet)
1054 : {
1055 0 : aMultiTextWnd->SetFormulaMode(bSet);
1056 0 : }
1057 :
1058 0 : void ScInputBarGroup::IncrementVerticalSize()
1059 : {
1060 0 : aMultiTextWnd->SetNumLines( aMultiTextWnd->GetNumLines() + 1 );
1061 0 : TriggerToolboxLayout();
1062 0 : }
1063 :
1064 0 : void ScInputBarGroup::DecrementVerticalSize()
1065 : {
1066 0 : if ( aMultiTextWnd->GetNumLines() > 1 )
1067 : {
1068 0 : aMultiTextWnd->SetNumLines( aMultiTextWnd->GetNumLines() - 1 );
1069 0 : TriggerToolboxLayout();
1070 : }
1071 0 : }
1072 :
1073 0 : IMPL_LINK_NOARG(ScInputBarGroup, ClickHdl)
1074 : {
1075 0 : vcl::Window* w = GetParent();
1076 : ScInputWindow* pParent;
1077 0 : pParent = dynamic_cast<ScInputWindow*>(w);
1078 :
1079 0 : if (pParent == NULL)
1080 : {
1081 : OSL_FAIL("The parent window pointer pParent is null");
1082 0 : return 1;
1083 : }
1084 0 : if (aMultiTextWnd->GetNumLines() > 1)
1085 : {
1086 0 : aMultiTextWnd->SetNumLines(1);
1087 : }
1088 : else
1089 : {
1090 0 : aMultiTextWnd->SetNumLines(aMultiTextWnd->GetLastNumExpandedLines());
1091 : }
1092 0 : TriggerToolboxLayout();
1093 :
1094 : // Restore focus to input line(s) if necessary
1095 0 : if ( SC_MOD()->GetInputHdl()->IsTopMode() )
1096 0 : aMultiTextWnd->GrabFocus();
1097 0 : return 0;
1098 : }
1099 :
1100 0 : void ScInputBarGroup::TriggerToolboxLayout()
1101 : {
1102 0 : vcl::Window *w=GetParent();
1103 0 : ScInputWindow &rParent = dynamic_cast<ScInputWindow&>(*w);
1104 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1105 :
1106 : // Capture the vertical position of this window in the toolbar, when we increase
1107 : // the size of the toolbar to accommodate expanded line input we need to take this
1108 : // into account
1109 0 : if ( !nVertOffset )
1110 0 : nVertOffset = rParent.GetItemPosRect( rParent.GetItemCount() - 1 ).Top();
1111 :
1112 0 : if ( pViewFrm )
1113 : {
1114 0 : Reference< com::sun::star::beans::XPropertySet > xPropSet( pViewFrm->GetFrame().GetFrameInterface(), UNO_QUERY );
1115 0 : Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1116 :
1117 0 : if ( xPropSet.is() )
1118 : {
1119 0 : com::sun::star::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
1120 0 : aValue >>= xLayoutManager;
1121 : }
1122 :
1123 0 : if ( xLayoutManager.is() )
1124 : {
1125 0 : if ( aMultiTextWnd->GetNumLines() > 1)
1126 0 : rParent.SetToolbarLayoutMode( TBX_LAYOUT_LOCKVERT );
1127 : else
1128 0 : rParent.SetToolbarLayoutMode( TBX_LAYOUT_NORMAL );
1129 0 : xLayoutManager->lock();
1130 0 : DataChangedEvent aFakeUpdate( DataChangedEventType::SETTINGS, NULL, AllSettingsFlags::STYLE );
1131 :
1132 : // this basically will trigger the reposititioning of the
1133 : // items in the toolbar from ImplFormat ( which is controlled by
1134 : // mnWinHeight ) which in turn is updated in ImplCalcItem which is
1135 : // controlled by mbCalc. Additionally the ImplFormat above is
1136 : // controlled via mbFormat. It seems the easiest way to get these
1137 : // booleans set is to send in the fake event below.
1138 0 : rParent.DataChanged( aFakeUpdate);
1139 :
1140 : // highest item in toolbar will have been calculated via the
1141 : // event above. Call resize on InputBar to pick up the height
1142 : // change
1143 0 : rParent.Resize();
1144 :
1145 : // unlock relayouts the toolbars in the 4 quadrants
1146 0 : xLayoutManager->unlock();
1147 0 : }
1148 : }
1149 0 : }
1150 :
1151 0 : IMPL_LINK_NOARG(ScInputBarGroup, Impl_ScrollHdl)
1152 : {
1153 0 : aMultiTextWnd->DoScroll();
1154 0 : return 0;
1155 : }
1156 :
1157 0 : void ScInputBarGroup::TextGrabFocus()
1158 : {
1159 0 : aMultiTextWnd->TextGrabFocus();
1160 0 : }
1161 :
1162 338 : ScMultiTextWnd::ScMultiTextWnd( ScInputBarGroup* pParen, ScTabViewShell* pViewSh )
1163 : : ScTextWnd( pParen, pViewSh ),
1164 : mrGroupBar(* pParen ),
1165 : mnLines( 1 ),
1166 : mnLastExpandedLines( INPUTWIN_MULTILINES ),
1167 338 : mbInvalidate( false )
1168 : {
1169 338 : Size aBorder;
1170 338 : aBorder = CalcWindowSize(aBorder);
1171 338 : mnBorderHeight = aBorder.Height();
1172 338 : }
1173 :
1174 672 : ScMultiTextWnd::~ScMultiTextWnd()
1175 : {
1176 672 : }
1177 :
1178 587 : void ScMultiTextWnd::Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect )
1179 : {
1180 587 : EditView* pView = GetEditView();
1181 587 : if (pView)
1182 : {
1183 587 : if (mbInvalidate)
1184 : {
1185 323 : pView->Invalidate();
1186 323 : mbInvalidate = false;
1187 : }
1188 587 : pEditView->Paint(rRect, &rRenderContext);
1189 : }
1190 587 : }
1191 :
1192 587 : EditView* ScMultiTextWnd::GetEditView()
1193 : {
1194 587 : if ( !pEditView )
1195 239 : InitEditEngine();
1196 587 : return pEditView;
1197 : }
1198 :
1199 6507 : long ScMultiTextWnd::GetPixelHeightForLines( long nLines )
1200 : {
1201 : // add padding ( for the borders of the window )
1202 6507 : return ( nLines * LogicToPixel( Size( 0, GetTextHeight() ) ).Height() ) + mnBorderHeight;
1203 : }
1204 :
1205 0 : void ScMultiTextWnd::SetNumLines( long nLines )
1206 : {
1207 0 : mnLines = nLines;
1208 0 : if ( nLines > 1 )
1209 : {
1210 0 : mnLastExpandedLines = nLines;
1211 0 : Resize();
1212 : }
1213 0 : }
1214 :
1215 6169 : void ScMultiTextWnd::Resize()
1216 : {
1217 : // Only Height is recalculated here, Width is applied from
1218 : // parent/container window
1219 6169 : Size aTextBoxSize = GetSizePixel();
1220 :
1221 6169 : aTextBoxSize.Height() = GetPixelHeightForLines( mnLines );
1222 6169 : SetSizePixel( aTextBoxSize );
1223 :
1224 6169 : if(pEditView)
1225 : {
1226 241 : Size aOutputSize = GetOutputSizePixel();
1227 241 : Rectangle aOutputArea = PixelToLogic( Rectangle( Point(), aOutputSize ));
1228 241 : pEditView->SetOutputArea( aOutputArea );
1229 :
1230 : // Don't leave an empty area at the bottom if we can move the text down.
1231 241 : long nMaxVisAreaTop = pEditEngine->GetTextHeight() - aOutputArea.GetHeight();
1232 241 : if (pEditView->GetVisArea().Top() > nMaxVisAreaTop)
1233 : {
1234 0 : pEditView->Scroll(0, pEditView->GetVisArea().Top() - nMaxVisAreaTop);
1235 : }
1236 :
1237 241 : pEditEngine->SetPaperSize( PixelToLogic( Size( aOutputSize.Width(), 10000 ) ) );
1238 : }
1239 :
1240 6169 : SetScrollBarRange();
1241 6169 : }
1242 :
1243 938 : IMPL_LINK(ScMultiTextWnd, ModifyHdl, EENotify*, pNotify)
1244 : {
1245 469 : ScTextWnd::NotifyHdl( pNotify );
1246 469 : return 0;
1247 : }
1248 :
1249 2588 : IMPL_LINK(ScMultiTextWnd, NotifyHdl, EENotify*, pNotify)
1250 : {
1251 : // need to process EE_NOTIFY_TEXTVIEWSCROLLED here
1252 : // sometimes we don't seem to get EE_NOTIFY_TEXTVIEWSCROLLED e.g. when
1253 : // we insert text at the beginning of the text so the cursor never moves
1254 : // down to generate a scroll event
1255 :
1256 1294 : if ( pNotify && ( pNotify->eNotificationType == EE_NOTIFY_TEXTVIEWSCROLLED
1257 1294 : || pNotify->eNotificationType == EE_NOTIFY_TEXTHEIGHTCHANGED ) )
1258 165 : SetScrollBarRange();
1259 1294 : return 0;
1260 : }
1261 :
1262 571 : long ScMultiTextWnd::GetEditEngTxtHeight()
1263 : {
1264 571 : return pEditView ? pEditView->GetEditEngine()->GetTextHeight() : 0;
1265 : }
1266 :
1267 7408 : void ScMultiTextWnd::SetScrollBarRange()
1268 : {
1269 7408 : if ( pEditView )
1270 : {
1271 571 : ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1272 571 : rVBar.SetRange( Range( 0, GetEditEngTxtHeight() ) );
1273 571 : long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1274 571 : rVBar.SetThumbPos( currentDocPos );
1275 : }
1276 7408 : }
1277 :
1278 : void
1279 1074 : ScMultiTextWnd::DoScroll()
1280 : {
1281 1074 : if ( pEditView )
1282 : {
1283 165 : ScrollBar& rVBar = mrGroupBar.GetScrollBar();
1284 165 : long currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1285 165 : long nDiff = currentDocPos - rVBar.GetThumbPos();
1286 165 : pEditView->Scroll( 0, nDiff );
1287 165 : currentDocPos = pEditView->GetVisArea().TopLeft().Y();
1288 165 : rVBar.SetThumbPos( currentDocPos );
1289 : }
1290 1074 : }
1291 :
1292 0 : void ScMultiTextWnd::StartEditEngine()
1293 : {
1294 : // Don't activate if we're a modal dialog ourselves (Doc-modal dialog)
1295 0 : SfxObjectShell* pObjSh = SfxObjectShell::Current();
1296 0 : if ( pObjSh && pObjSh->IsInModalMode() )
1297 0 : return;
1298 :
1299 0 : if ( !pEditView || !pEditEngine )
1300 : {
1301 0 : InitEditEngine();
1302 : }
1303 :
1304 0 : SC_MOD()->SetInputMode( SC_INPUT_TOP );
1305 :
1306 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1307 0 : if (pViewFrm)
1308 0 : pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1309 : }
1310 :
1311 239 : static void lcl_ExtendEditFontAttribs( SfxItemSet& rSet )
1312 : {
1313 239 : const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO );
1314 239 : rSet.Put( rFontItem, EE_CHAR_FONTINFO_CJK );
1315 239 : rSet.Put( rFontItem, EE_CHAR_FONTINFO_CTL );
1316 239 : const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT );
1317 239 : rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CJK );
1318 239 : rSet.Put( rHeightItem, EE_CHAR_FONTHEIGHT_CTL );
1319 239 : const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT );
1320 239 : rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CJK );
1321 239 : rSet.Put( rWeightItem, EE_CHAR_WEIGHT_CTL );
1322 239 : const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC );
1323 239 : rSet.Put( rItalicItem, EE_CHAR_ITALIC_CJK );
1324 239 : rSet.Put( rItalicItem, EE_CHAR_ITALIC_CTL );
1325 239 : const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE );
1326 239 : rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CJK );
1327 239 : rSet.Put( rLangItem, EE_CHAR_LANGUAGE_CTL );
1328 239 : }
1329 :
1330 0 : static void lcl_ModifyRTLDefaults( SfxItemSet& rSet )
1331 : {
1332 0 : rSet.Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1333 :
1334 : // always using rtl writing direction would break formulas
1335 : //rSet.Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1336 :
1337 : // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's
1338 : // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be
1339 : // increased to not see the beginning of the next line.
1340 0 : SvxLineSpacingItem aItem( SVX_LINESPACE_TWO_LINES, EE_PARA_SBL );
1341 0 : aItem.SetPropLineSpace( 200 );
1342 0 : rSet.Put( aItem );
1343 0 : }
1344 :
1345 0 : static void lcl_ModifyRTLVisArea( EditView* pEditView )
1346 : {
1347 0 : Rectangle aVisArea = pEditView->GetVisArea();
1348 0 : Size aPaper = pEditView->GetEditEngine()->GetPaperSize();
1349 0 : long nDiff = aPaper.Width() - aVisArea.Right();
1350 0 : aVisArea.Left() += nDiff;
1351 0 : aVisArea.Right() += nDiff;
1352 0 : pEditView->SetVisArea(aVisArea);
1353 0 : }
1354 :
1355 239 : void ScMultiTextWnd::InitEditEngine()
1356 : {
1357 : ScFieldEditEngine* pNew;
1358 239 : ScTabViewShell* pViewSh = GetViewShell();
1359 239 : ScDocShell* pDocSh = NULL;
1360 239 : if ( pViewSh )
1361 : {
1362 239 : pDocSh = pViewSh->GetViewData().GetDocShell();
1363 239 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1364 239 : pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1365 : }
1366 : else
1367 0 : pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1368 239 : pNew->SetExecuteURL( false );
1369 239 : pEditEngine = pNew;
1370 :
1371 239 : Size barSize=GetSizePixel();
1372 239 : pEditEngine->SetUpdateMode( false );
1373 239 : pEditEngine->SetPaperSize( PixelToLogic(Size(barSize.Width(),10000)) );
1374 : pEditEngine->SetWordDelimiters(
1375 239 : ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1376 :
1377 239 : UpdateAutoCorrFlag();
1378 :
1379 : {
1380 239 : SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1381 239 : EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
1382 239 : lcl_ExtendEditFontAttribs( *pSet );
1383 : // turn off script spacing to match DrawText output
1384 239 : pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1385 239 : if ( bIsRTL )
1386 0 : lcl_ModifyRTLDefaults( *pSet );
1387 239 : pEditEngine->SetDefaults( pSet );
1388 : }
1389 :
1390 : // If the Cell contains URLFields, they need to be taken over into the entry row,
1391 : // or else the position is not correct anymore
1392 239 : bool bFilled = false;
1393 239 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1394 239 : if ( pHdl ) //! Test if it's the right InputHdl?
1395 239 : bFilled = pHdl->GetTextAndFields( *pEditEngine );
1396 :
1397 239 : pEditEngine->SetUpdateMode( true );
1398 :
1399 : // aString is the truth ...
1400 239 : if (bFilled && pEditEngine->GetText() == aString)
1401 0 : Invalidate(); // Repaint for (filled) Field
1402 : else
1403 239 : pEditEngine->SetText(aString); // At least the right text then
1404 :
1405 239 : pEditView = new EditView( pEditEngine, this );
1406 239 : pEditView->SetInsertMode(bIsInsertMode);
1407 :
1408 : // Text from Clipboard is taken over as ASCII in a single row
1409 239 : EVControlBits n = pEditView->GetControlWord();
1410 239 : pEditView->SetControlWord( n | EVControlBits::SINGLELINEPASTE );
1411 :
1412 239 : pEditEngine->InsertView( pEditView, EE_APPEND );
1413 :
1414 239 : Resize();
1415 :
1416 239 : if ( bIsRTL )
1417 0 : lcl_ModifyRTLVisArea( pEditView );
1418 :
1419 239 : pEditEngine->SetModifyHdl(LINK(this, ScMultiTextWnd, ModifyHdl));
1420 239 : pEditEngine->SetNotifyHdl(LINK(this, ScMultiTextWnd, NotifyHdl));
1421 :
1422 239 : if (!maAccTextDatas.empty())
1423 0 : maAccTextDatas.back()->StartEdit();
1424 :
1425 : // as long as EditEngine and DrawText sometimes differ for CTL text,
1426 : // repaint now to have the EditEngine's version visible
1427 239 : if (pDocSh)
1428 : {
1429 239 : ScDocument& rDoc = pDocSh->GetDocument(); // any document
1430 239 : SvtScriptType nScript = rDoc.GetStringScriptType( aString );
1431 239 : if ( nScript & SvtScriptType::COMPLEX )
1432 0 : Invalidate();
1433 : }
1434 239 : }
1435 :
1436 191 : void ScMultiTextWnd::StopEditEngine( bool bAll )
1437 : {
1438 191 : if ( pEditEngine )
1439 80 : pEditEngine->SetNotifyHdl(Link<>());
1440 191 : ScTextWnd::StopEditEngine( bAll );
1441 191 : }
1442 :
1443 1074 : void ScMultiTextWnd::SetTextString( const OUString& rNewString )
1444 : {
1445 : // Ideally it would be best to create on demand the EditEngine/EditView here, but... for
1446 : // the initialisation scenario where a cell is first clicked on we end up with the text in the
1447 : // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview
1448 : // are synced I guess ).
1449 : // should fix that I suppose :-/ need to look a bit further into that
1450 1074 : mbInvalidate = true; // ensure next Paint ( that uses editengine ) call will call Invalidate first
1451 1074 : ScTextWnd::SetTextString( rNewString );
1452 1074 : SetScrollBarRange();
1453 1074 : DoScroll();
1454 1074 : }
1455 :
1456 338 : ScTextWnd::ScTextWnd( vcl::Window* pParent, ScTabViewShell* pViewSh )
1457 : : ScTextWndBase(pParent, WinBits(WB_HIDE | WB_BORDER)),
1458 : DragSourceHelper(this),
1459 : pEditEngine (NULL),
1460 : pEditView (NULL),
1461 : bIsInsertMode(true),
1462 : bFormulaMode (false),
1463 : bInputMode (false),
1464 338 : mpViewShell(pViewSh)
1465 : {
1466 338 : EnableRTL(false); // EditEngine can't be used with VCL EnableRTL
1467 :
1468 338 : bIsRTL = AllSettings::GetLayoutRTL();
1469 :
1470 : // always use application font, so a font with cjk chars can be installed
1471 338 : vcl::Font aAppFont = GetFont();
1472 338 : aTextFont = aAppFont;
1473 338 : aTextFont.SetSize(PixelToLogic(aAppFont.GetSize(), MAP_TWIP)); // AppFont is in pixels
1474 :
1475 338 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1476 :
1477 338 : Color aBgColor = rStyleSettings.GetWindowColor();
1478 338 : Color aTxtColor = rStyleSettings.GetWindowTextColor();
1479 :
1480 338 : aTextFont.SetTransparent(true);
1481 338 : aTextFont.SetFillColor(aBgColor);
1482 338 : aTextFont.SetColor(aTxtColor);
1483 338 : aTextFont.SetWeight(WEIGHT_NORMAL);
1484 :
1485 338 : Size aSize(1,TBX_WINDOW_HEIGHT);
1486 338 : Size aMinEditSize( Edit::GetMinimumEditSize() );
1487 338 : if( aMinEditSize.Height() > aSize.Height() )
1488 0 : aSize.Height() = aMinEditSize.Height();
1489 :
1490 338 : SetSizePixel(aSize);
1491 338 : SetBackground(aBgColor);
1492 338 : SetLineColor(COL_BLACK);
1493 338 : SetMapMode(MAP_TWIP);
1494 338 : SetPointer(PointerStyle::Text);
1495 338 : SetFont(aTextFont);
1496 338 : }
1497 :
1498 672 : ScTextWnd::~ScTextWnd()
1499 : {
1500 336 : disposeOnce();
1501 336 : }
1502 :
1503 336 : void ScTextWnd::dispose()
1504 : {
1505 672 : while (!maAccTextDatas.empty()) {
1506 0 : maAccTextDatas.back()->Dispose();
1507 : }
1508 336 : delete pEditView;
1509 336 : pEditView = NULL;
1510 336 : delete pEditEngine;
1511 336 : pEditEngine = NULL;
1512 :
1513 336 : ScTextWndBase::dispose();
1514 336 : }
1515 :
1516 0 : void ScTextWnd::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
1517 : {
1518 0 : if (pEditView)
1519 : {
1520 0 : Size aSize = rRenderContext.GetOutputSizePixel();
1521 0 : long nDiff = aSize.Height() - rRenderContext.LogicToPixel(Size(0, rRenderContext.GetTextHeight())).Height();
1522 0 : pEditView->SetOutputArea(rRenderContext.PixelToLogic(Rectangle(Point(0, (nDiff > 0) ? nDiff / 2 : 1), aSize)));
1523 :
1524 0 : pEditView->Paint(rRect, &rRenderContext);
1525 : }
1526 : else
1527 : {
1528 0 : Size aSize = GetOutputSizePixel();
1529 0 : SetFont(aTextFont);
1530 :
1531 0 : long nDiff = aSize.Height() - rRenderContext.LogicToPixel(Size(0, rRenderContext.GetTextHeight())).Height();
1532 :
1533 : // if (nDiff<2) nDiff=2; // At least 1 pixel
1534 :
1535 0 : long nStartPos = 0;
1536 0 : if (bIsRTL)
1537 : {
1538 : // right-align
1539 0 : nStartPos += aSize.Width() - rRenderContext.LogicToPixel(Size(rRenderContext.GetTextWidth(aString), 0)).Width();
1540 :
1541 : // LayoutMode isn't changed as long as ModifyRTLDefaults doesn't include SvxFrameDirectionItem
1542 : }
1543 0 : rRenderContext.DrawText(rRenderContext.PixelToLogic(Point(nStartPos, nDiff / 2)), aString);
1544 : }
1545 0 : rRenderContext.Pop();
1546 0 : }
1547 :
1548 0 : void ScTextWnd::Resize()
1549 : {
1550 0 : Invalidate();
1551 0 : }
1552 :
1553 0 : void ScTextWnd::MouseMove( const MouseEvent& rMEvt )
1554 : {
1555 0 : if (pEditView)
1556 0 : pEditView->MouseMove( rMEvt );
1557 0 : }
1558 :
1559 0 : void ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt )
1560 : {
1561 0 : if (!HasFocus())
1562 : {
1563 0 : StartEditEngine();
1564 0 : if ( SC_MOD()->IsEditMode() )
1565 0 : GrabFocus();
1566 : }
1567 :
1568 0 : if (pEditView)
1569 : {
1570 0 : pEditView->SetEditEngineUpdateMode( true );
1571 0 : pEditView->MouseButtonDown( rMEvt );
1572 : }
1573 0 : }
1574 :
1575 0 : void ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt )
1576 : {
1577 0 : if (pEditView)
1578 0 : if (pEditView->MouseButtonUp( rMEvt ))
1579 : {
1580 0 : if ( rMEvt.IsMiddle() &&
1581 0 : GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection )
1582 : {
1583 : // EditView may have pasted from selection
1584 0 : SC_MOD()->InputChanged( pEditView );
1585 : }
1586 : else
1587 0 : SC_MOD()->InputSelection( pEditView );
1588 : }
1589 0 : }
1590 :
1591 0 : void ScTextWnd::Command( const CommandEvent& rCEvt )
1592 : {
1593 0 : bInputMode = true;
1594 0 : CommandEventId nCommand = rCEvt.GetCommand();
1595 0 : if ( pEditView /* && nCommand == CommandEventId::StartDrag */ )
1596 : {
1597 0 : ScModule* pScMod = SC_MOD();
1598 0 : ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell();
1599 :
1600 : // don't modify the font defaults here - the right defaults are
1601 : // already set in StartEditEngine when the EditEngine is created
1602 :
1603 : // Prevent that the EditView is lost when switching between Views
1604 0 : pScMod->SetInEditCommand( true );
1605 0 : pEditView->Command( rCEvt );
1606 0 : pScMod->SetInEditCommand( false );
1607 :
1608 : // CommandEventId::StartDrag does not mean by far that the content was actually changed,
1609 : // so don't trigger an InputChanged.
1610 : //! Detect if dragged with Move or forbid Drag&Move somehow
1611 :
1612 0 : if ( nCommand == CommandEventId::StartDrag )
1613 : {
1614 : // Is dragged onto another View?
1615 0 : ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell();
1616 0 : if ( pEndViewSh != pStartViewSh && pStartViewSh != NULL )
1617 : {
1618 0 : ScViewData& rViewData = pStartViewSh->GetViewData();
1619 0 : ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh );
1620 0 : if ( pHdl && rViewData.HasEditView( rViewData.GetActivePart() ) )
1621 : {
1622 0 : pHdl->CancelHandler();
1623 0 : rViewData.GetView()->ShowCursor(); // Missing for KillEditView, due to being inactive
1624 : }
1625 : }
1626 : }
1627 0 : else if ( nCommand == CommandEventId::CursorPos )
1628 : {
1629 : // don't call InputChanged for CommandEventId::CursorPos
1630 : }
1631 0 : else if ( nCommand == CommandEventId::InputLanguageChange )
1632 : {
1633 : // #i55929# Font and font size state depends on input language if nothing is selected,
1634 : // so the slots have to be invalidated when the input language is changed.
1635 :
1636 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1637 0 : if (pViewFrm)
1638 : {
1639 0 : SfxBindings& rBindings = pViewFrm->GetBindings();
1640 0 : rBindings.Invalidate( SID_ATTR_CHAR_FONT );
1641 0 : rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
1642 : }
1643 : }
1644 0 : else if ( nCommand == CommandEventId::Wheel )
1645 : {
1646 : //don't call InputChanged for CommandEventId::Wheel
1647 : }
1648 : else
1649 0 : SC_MOD()->InputChanged( pEditView );
1650 : }
1651 : else
1652 0 : Window::Command(rCEvt); // Or else let the base class handle it...
1653 :
1654 0 : bInputMode = false;
1655 0 : }
1656 :
1657 0 : void ScTextWnd::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel )
1658 : {
1659 0 : if ( pEditView )
1660 : {
1661 0 : CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true );
1662 0 : pEditView->Command( aDragEvent );
1663 :
1664 : // handling of d&d to different view (CancelHandler) can't be done here,
1665 : // because the call returns before d&d is complete.
1666 : }
1667 0 : }
1668 :
1669 0 : void ScTextWnd::KeyInput(const KeyEvent& rKEvt)
1670 : {
1671 0 : bInputMode = true;
1672 0 : if (!SC_MOD()->InputKeyEvent( rKEvt ))
1673 : {
1674 0 : bool bUsed = false;
1675 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1676 0 : if ( pViewSh )
1677 0 : bUsed = pViewSh->SfxKeyInput(rKEvt); // Only accelerators, no input
1678 0 : if (!bUsed)
1679 0 : Window::KeyInput( rKEvt );
1680 : }
1681 0 : bInputMode = false;
1682 0 : }
1683 :
1684 0 : void ScTextWnd::GetFocus()
1685 : {
1686 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1687 0 : if ( pViewSh )
1688 0 : pViewSh->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top
1689 0 : }
1690 :
1691 0 : void ScTextWnd::LoseFocus()
1692 : {
1693 0 : }
1694 :
1695 0 : OUString ScTextWnd::GetText() const
1696 : {
1697 : // Override to get the text via the testtool
1698 0 : if ( pEditEngine )
1699 0 : return pEditEngine->GetText();
1700 : else
1701 0 : return GetTextString();
1702 : }
1703 :
1704 0 : void ScTextWnd::SetFormulaMode( bool bSet )
1705 : {
1706 0 : if ( bSet != bFormulaMode )
1707 : {
1708 0 : bFormulaMode = bSet;
1709 0 : UpdateAutoCorrFlag();
1710 : }
1711 0 : }
1712 :
1713 239 : void ScTextWnd::UpdateAutoCorrFlag()
1714 : {
1715 239 : if ( pEditEngine )
1716 : {
1717 239 : EEControlBits nControl = pEditEngine->GetControlWord();
1718 239 : EEControlBits nOld = nControl;
1719 239 : if ( bFormulaMode )
1720 0 : nControl &= ~EEControlBits::AUTOCORRECT; // No AutoCorrect in Formulas
1721 : else
1722 239 : nControl |= EEControlBits::AUTOCORRECT; // Else do enable it
1723 :
1724 239 : if ( nControl != nOld )
1725 239 : pEditEngine->SetControlWord( nControl );
1726 : }
1727 239 : }
1728 :
1729 0 : void ScTextWnd::StartEditEngine()
1730 : {
1731 : // Don't activate if we're a modal ourselves (Doc modal Dialog)
1732 0 : SfxObjectShell* pObjSh = SfxObjectShell::Current();
1733 0 : if ( pObjSh && pObjSh->IsInModalMode() )
1734 0 : return;
1735 :
1736 0 : if ( !pEditView || !pEditEngine )
1737 : {
1738 : ScFieldEditEngine* pNew;
1739 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1740 0 : if ( pViewSh )
1741 : {
1742 0 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1743 0 : pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1744 : }
1745 : else
1746 0 : pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1747 0 : pNew->SetExecuteURL( false );
1748 0 : pEditEngine = pNew;
1749 :
1750 0 : pEditEngine->SetUpdateMode( false );
1751 0 : pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1752 : pEditEngine->SetWordDelimiters(
1753 0 : ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1754 :
1755 0 : UpdateAutoCorrFlag();
1756 :
1757 : {
1758 0 : SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1759 0 : EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
1760 0 : lcl_ExtendEditFontAttribs( *pSet );
1761 :
1762 : // turn off script spacing to match DrawText output
1763 0 : pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
1764 0 : if ( bIsRTL )
1765 0 : lcl_ModifyRTLDefaults( *pSet );
1766 0 : pEditEngine->SetDefaults( pSet );
1767 : }
1768 :
1769 : // If the Cell contains URLFields, they need to be taken over into the entry row,
1770 : // or else the position is not correct anymore
1771 0 : bool bFilled = false;
1772 0 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1773 0 : if ( pHdl ) //! Check if it's the right InputHdl?
1774 0 : bFilled = pHdl->GetTextAndFields( *pEditEngine );
1775 :
1776 0 : pEditEngine->SetUpdateMode( true );
1777 :
1778 : // aString is the truth...
1779 0 : if (bFilled && pEditEngine->GetText() == aString)
1780 0 : Invalidate(); // Repaint for (filled) Fields
1781 : else
1782 0 : pEditEngine->SetText(aString); // At least the right text then
1783 :
1784 0 : pEditView = new EditView( pEditEngine, this );
1785 0 : pEditView->SetInsertMode(bIsInsertMode);
1786 :
1787 : // The text from the Clipboard is taken over as ASCII in a single row
1788 0 : EVControlBits n = pEditView->GetControlWord();
1789 0 : pEditView->SetControlWord( n | EVControlBits::SINGLELINEPASTE );
1790 :
1791 0 : pEditEngine->InsertView( pEditView, EE_APPEND );
1792 :
1793 0 : Resize();
1794 :
1795 0 : if ( bIsRTL )
1796 0 : lcl_ModifyRTLVisArea( pEditView );
1797 :
1798 0 : pEditEngine->SetModifyHdl(LINK(this, ScTextWnd, NotifyHdl));
1799 :
1800 0 : if (!maAccTextDatas.empty())
1801 0 : maAccTextDatas.back()->StartEdit();
1802 :
1803 : // as long as EditEngine and DrawText sometimes differ for CTL text,
1804 : // repaint now to have the EditEngine's version visible
1805 : // SfxObjectShell* pObjSh = SfxObjectShell::Current();
1806 0 : if ( pObjSh && pObjSh->ISA(ScDocShell) )
1807 : {
1808 0 : ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument(); // any document
1809 0 : SvtScriptType nScript = rDoc.GetStringScriptType( aString );
1810 0 : if ( nScript & SvtScriptType::COMPLEX )
1811 0 : Invalidate();
1812 : }
1813 : }
1814 :
1815 0 : SC_MOD()->SetInputMode( SC_INPUT_TOP );
1816 :
1817 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1818 0 : if (pViewFrm)
1819 0 : pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1820 : }
1821 :
1822 469 : IMPL_LINK_NOARG(ScTextWnd, NotifyHdl)
1823 : {
1824 469 : if (pEditView && !bInputMode)
1825 : {
1826 0 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1827 :
1828 : // Use the InputHandler's InOwnChange flag to prevent calling InputChanged
1829 : // while an InputHandler method is modifying the EditEngine content
1830 :
1831 0 : if ( pHdl && !pHdl->IsInOwnChange() )
1832 0 : pHdl->InputChanged( pEditView, true ); // #i20282# InputChanged must know if called from modify handler
1833 : }
1834 :
1835 469 : return 0;
1836 : }
1837 :
1838 191 : void ScTextWnd::StopEditEngine( bool bAll )
1839 : {
1840 191 : if (pEditView)
1841 : {
1842 80 : if (!maAccTextDatas.empty())
1843 0 : maAccTextDatas.back()->EndEdit();
1844 :
1845 80 : ScModule* pScMod = SC_MOD();
1846 :
1847 80 : if (!bAll)
1848 0 : pScMod->InputSelection( pEditView );
1849 80 : aString = pEditEngine->GetText();
1850 80 : bIsInsertMode = pEditView->IsInsertMode();
1851 80 : bool bSelection = pEditView->HasSelection();
1852 80 : pEditEngine->SetModifyHdl(Link<>());
1853 80 : DELETEZ(pEditView);
1854 80 : DELETEZ(pEditEngine);
1855 :
1856 80 : if ( pScMod->IsEditMode() && !bAll )
1857 0 : pScMod->SetInputMode(SC_INPUT_TABLE);
1858 :
1859 80 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1860 80 : if (pViewFrm)
1861 80 : pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERT );
1862 :
1863 80 : if (bSelection)
1864 0 : Invalidate(); // So that the Selection is not left there
1865 : }
1866 191 : }
1867 :
1868 256 : static sal_Int32 findFirstNonMatchingChar(const OUString& rStr1, const OUString& rStr2)
1869 : {
1870 : // Search the string for unmatching chars
1871 256 : const sal_Unicode* pStr1 = rStr1.getStr();
1872 256 : const sal_Unicode* pStr2 = rStr2.getStr();
1873 256 : sal_Int32 i = 0;
1874 574 : while ( i < rStr1.getLength() )
1875 : {
1876 : // Abort on the first unmatching char
1877 318 : if ( *pStr1 != *pStr2 )
1878 256 : return i;
1879 : ++pStr1,
1880 : ++pStr2,
1881 62 : ++i;
1882 : }
1883 :
1884 0 : return i;
1885 : }
1886 :
1887 1074 : void ScTextWnd::SetTextString( const OUString& rNewString )
1888 : {
1889 1074 : if ( rNewString != aString )
1890 : {
1891 421 : bInputMode = true;
1892 :
1893 : // Find position of the change, only paint the rest
1894 421 : if (!pEditEngine)
1895 : {
1896 : bool bPaintAll;
1897 256 : if ( bIsRTL )
1898 0 : bPaintAll = true;
1899 : else
1900 : {
1901 : // test if CTL script type is involved
1902 256 : SvtScriptType nOldScript = SvtScriptType::NONE;
1903 256 : SvtScriptType nNewScript = SvtScriptType::NONE;
1904 256 : SfxObjectShell* pObjSh = SfxObjectShell::Current();
1905 256 : if ( pObjSh && pObjSh->ISA(ScDocShell) )
1906 : {
1907 : // any document can be used (used only for its break iterator)
1908 222 : ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument();
1909 222 : nOldScript = rDoc.GetStringScriptType( aString );
1910 222 : nNewScript = rDoc.GetStringScriptType( rNewString );
1911 : }
1912 256 : bPaintAll = ( nOldScript & SvtScriptType::COMPLEX ) || ( nNewScript & SvtScriptType::COMPLEX );
1913 : }
1914 :
1915 256 : if ( bPaintAll )
1916 : {
1917 : // if CTL is involved, the whole text has to be redrawn
1918 0 : Invalidate();
1919 : }
1920 : else
1921 : {
1922 256 : long nTextSize = 0;
1923 : sal_Int32 nDifPos;
1924 256 : if (rNewString.getLength() > aString.getLength())
1925 96 : nDifPos = findFirstNonMatchingChar(rNewString, aString);
1926 : else
1927 160 : nDifPos = findFirstNonMatchingChar(aString, rNewString);
1928 :
1929 256 : long nSize1 = GetTextWidth(aString);
1930 256 : long nSize2 = GetTextWidth(rNewString);
1931 256 : if ( nSize1>0 && nSize2>0 )
1932 43 : nTextSize = std::max( nSize1, nSize2 );
1933 : else
1934 213 : nTextSize = GetOutputSize().Width(); // Overflow
1935 :
1936 256 : Point aLogicStart = PixelToLogic(Point(0,0));
1937 256 : long nStartPos = aLogicStart.X();
1938 256 : long nInvPos = nStartPos;
1939 256 : if (nDifPos)
1940 4 : nInvPos += GetTextWidth(aString,0,nDifPos);
1941 :
1942 256 : InvalidateFlags nFlags = InvalidateFlags::NONE;
1943 256 : if ( nDifPos == aString.getLength() ) // only new characters appended
1944 95 : nFlags = InvalidateFlags::NoErase; // then background is already clear
1945 :
1946 256 : Invalidate( Rectangle( nInvPos, 0, nStartPos+nTextSize, GetOutputSize().Height()-1 ), nFlags );
1947 : }
1948 : }
1949 : else
1950 : {
1951 165 : pEditEngine->SetText(rNewString);
1952 : }
1953 :
1954 421 : aString = rNewString;
1955 :
1956 421 : if (!maAccTextDatas.empty())
1957 0 : maAccTextDatas.back()->TextChanged();
1958 :
1959 421 : bInputMode = false;
1960 : }
1961 1074 : }
1962 :
1963 0 : const OUString& ScTextWnd::GetTextString() const
1964 : {
1965 0 : return aString;
1966 : }
1967 :
1968 1958 : bool ScTextWnd::IsInputActive()
1969 : {
1970 1958 : return HasFocus();
1971 : }
1972 :
1973 0 : EditView* ScTextWnd::GetEditView()
1974 : {
1975 0 : return pEditView;
1976 : }
1977 :
1978 0 : void ScTextWnd::MakeDialogEditView()
1979 : {
1980 0 : if ( pEditView ) return;
1981 :
1982 : ScFieldEditEngine* pNew;
1983 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1984 0 : if ( pViewSh )
1985 : {
1986 0 : ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
1987 0 : pNew = new ScFieldEditEngine(pDoc, pDoc->GetEnginePool(), pDoc->GetEditPool());
1988 : }
1989 : else
1990 0 : pNew = new ScFieldEditEngine(NULL, EditEngine::CreatePool(), NULL, true);
1991 0 : pNew->SetExecuteURL( false );
1992 0 : pEditEngine = pNew;
1993 :
1994 0 : pEditEngine->SetUpdateMode( false );
1995 0 : pEditEngine->SetWordDelimiters( pEditEngine->GetWordDelimiters() + "=" );
1996 0 : pEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX : THESIZE, 300 ) );
1997 :
1998 0 : SfxItemSet* pSet = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1999 0 : EditEngine::SetFontInfoInItemSet( *pSet, aTextFont );
2000 0 : lcl_ExtendEditFontAttribs( *pSet );
2001 0 : if ( bIsRTL )
2002 0 : lcl_ModifyRTLDefaults( *pSet );
2003 0 : pEditEngine->SetDefaults( pSet );
2004 0 : pEditEngine->SetUpdateMode( true );
2005 :
2006 0 : pEditView = new EditView( pEditEngine, this );
2007 0 : pEditEngine->InsertView( pEditView, EE_APPEND );
2008 :
2009 0 : Resize();
2010 :
2011 0 : if ( bIsRTL )
2012 0 : lcl_ModifyRTLVisArea( pEditView );
2013 :
2014 0 : if (!maAccTextDatas.empty())
2015 0 : maAccTextDatas.back()->StartEdit();
2016 : }
2017 :
2018 0 : void ScTextWnd::ImplInitSettings()
2019 : {
2020 0 : bIsRTL = AllSettings::GetLayoutRTL();
2021 :
2022 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2023 :
2024 0 : Color aBgColor= rStyleSettings.GetWindowColor();
2025 0 : Color aTxtColor= rStyleSettings.GetWindowTextColor();
2026 :
2027 0 : aTextFont.SetFillColor ( aBgColor );
2028 0 : aTextFont.SetColor (aTxtColor);
2029 0 : SetBackground ( aBgColor );
2030 0 : Invalidate();
2031 0 : }
2032 :
2033 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ScTextWnd::CreateAccessible()
2034 : {
2035 : return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), NULL, this,
2036 : OUString(ScResId(STR_ACC_EDITLINE_NAME)),
2037 0 : OUString(ScResId(STR_ACC_EDITLINE_DESCR)), ScAccessibleEditObject::EditLine);
2038 : }
2039 :
2040 0 : void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2041 : {
2042 : OSL_ENSURE( ::std::find( maAccTextDatas.begin(), maAccTextDatas.end(), &rTextData ) == maAccTextDatas.end(),
2043 : "ScTextWnd::InsertAccessibleTextData - passed object already registered" );
2044 0 : maAccTextDatas.push_back( &rTextData );
2045 0 : }
2046 :
2047 0 : void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData )
2048 : {
2049 0 : AccTextDataVector::iterator aEnd = maAccTextDatas.end();
2050 0 : AccTextDataVector::iterator aIt = ::std::find( maAccTextDatas.begin(), aEnd, &rTextData );
2051 : OSL_ENSURE( aIt != aEnd, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" );
2052 0 : if( aIt != aEnd )
2053 0 : maAccTextDatas.erase( aIt );
2054 0 : }
2055 :
2056 0 : void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt )
2057 : {
2058 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2059 0 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
2060 : {
2061 0 : ImplInitSettings();
2062 0 : Invalidate();
2063 : }
2064 : else
2065 0 : Window::DataChanged( rDCEvt );
2066 0 : }
2067 :
2068 0 : void ScTextWnd::TextGrabFocus()
2069 : {
2070 0 : GrabFocus();
2071 0 : }
2072 :
2073 : // Position window
2074 :
2075 338 : ScPosWnd::ScPosWnd( vcl::Window* pParent ) :
2076 : ComboBox ( pParent, WinBits(WB_HIDE | WB_DROPDOWN) ),
2077 : pAccel ( NULL ),
2078 : nTipVisible ( 0 ),
2079 338 : bFormulaMode( false )
2080 : {
2081 : Size aSize( GetTextWidth( OUString("GW99999:GW99999") ),
2082 338 : GetTextHeight() );
2083 338 : aSize.Width() += 25; // FIXME: ??
2084 338 : aSize.Height() = CalcWindowSizePixel(11); // Functions: 10 MRU + "others..."
2085 338 : SetSizePixel( aSize );
2086 :
2087 338 : FillRangeNames();
2088 :
2089 338 : StartListening( *SfxGetpApp() ); // For Navigator rangename updates
2090 338 : }
2091 :
2092 1008 : ScPosWnd::~ScPosWnd()
2093 : {
2094 336 : disposeOnce();
2095 672 : }
2096 :
2097 336 : void ScPosWnd::dispose()
2098 : {
2099 336 : EndListening( *SfxGetpApp() );
2100 :
2101 336 : HideTip();
2102 :
2103 336 : delete pAccel;
2104 336 : ComboBox::dispose();
2105 336 : }
2106 :
2107 0 : void ScPosWnd::SetFormulaMode( bool bSet )
2108 : {
2109 0 : if ( bSet != bFormulaMode )
2110 : {
2111 0 : bFormulaMode = bSet;
2112 :
2113 0 : if ( bSet )
2114 0 : FillFunctions();
2115 : else
2116 0 : FillRangeNames();
2117 :
2118 0 : HideTip();
2119 : }
2120 0 : }
2121 :
2122 1316 : void ScPosWnd::SetPos( const OUString& rPosStr )
2123 : {
2124 1316 : if ( aPosStr != rPosStr )
2125 : {
2126 839 : aPosStr = rPosStr;
2127 839 : SetText(aPosStr);
2128 : }
2129 1316 : }
2130 :
2131 : namespace {
2132 :
2133 10 : OUString createLocalRangeName(const OUString& rName, const OUString& rTableName)
2134 : {
2135 10 : OUStringBuffer aString (rName);
2136 10 : aString.append(" (");
2137 10 : aString.append(rTableName);
2138 10 : aString.append(")");
2139 10 : return aString.makeStringAndClear();
2140 : }
2141 :
2142 : }
2143 :
2144 1066 : void ScPosWnd::FillRangeNames()
2145 : {
2146 1066 : Clear();
2147 :
2148 1066 : SfxObjectShell* pObjSh = SfxObjectShell::Current();
2149 1066 : if ( pObjSh && pObjSh->ISA(ScDocShell) )
2150 : {
2151 737 : ScDocument& rDoc = static_cast<ScDocShell*>(pObjSh)->GetDocument();
2152 :
2153 737 : InsertEntry(ScGlobal::GetRscString( STR_MANAGE_NAMES ));
2154 737 : SetSeparatorPos(0);
2155 :
2156 737 : ScRange aDummy;
2157 737 : std::set<OUString> aSet;
2158 737 : ScRangeName* pRangeNames = rDoc.GetRangeName();
2159 737 : if (!pRangeNames->empty())
2160 : {
2161 59 : ScRangeName::const_iterator itrBeg = pRangeNames->begin(), itrEnd = pRangeNames->end();
2162 332 : for (ScRangeName::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
2163 : {
2164 273 : if (itr->second->IsValidReference(aDummy))
2165 261 : aSet.insert(itr->second->GetName());
2166 : }
2167 : }
2168 1844 : for (SCTAB i = 0; i < rDoc.GetTableCount(); ++i)
2169 : {
2170 1107 : ScRangeName* pLocalRangeName = rDoc.GetRangeName(i);
2171 1107 : if (pLocalRangeName && !pLocalRangeName->empty())
2172 : {
2173 16 : OUString aTableName;
2174 16 : rDoc.GetName(i, aTableName);
2175 32 : for (ScRangeName::const_iterator itr = pLocalRangeName->begin(); itr != pLocalRangeName->end(); ++itr)
2176 : {
2177 16 : if (itr->second->IsValidReference(aDummy))
2178 10 : aSet.insert(createLocalRangeName(itr->second->GetName(), aTableName));
2179 16 : }
2180 : }
2181 : }
2182 :
2183 737 : if (!aSet.empty())
2184 : {
2185 1020 : for (std::set<OUString>::iterator itr = aSet.begin();
2186 680 : itr != aSet.end(); ++itr)
2187 : {
2188 271 : InsertEntry(*itr);
2189 : }
2190 737 : }
2191 : }
2192 1066 : SetText(aPosStr);
2193 1066 : }
2194 :
2195 0 : void ScPosWnd::FillFunctions()
2196 : {
2197 0 : Clear();
2198 :
2199 0 : OUString aFirstName;
2200 0 : const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
2201 0 : sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount();
2202 0 : const sal_uInt16* pMRUList = rOpt.GetLRUFuncList();
2203 0 : if (pMRUList)
2204 : {
2205 0 : const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
2206 0 : sal_uLong nListCount = pFuncList->GetCount();
2207 0 : for (sal_uInt16 i=0; i<nMRUCount; i++)
2208 : {
2209 0 : sal_uInt16 nId = pMRUList[i];
2210 0 : for (sal_uLong j=0; j<nListCount; j++)
2211 : {
2212 0 : const ScFuncDesc* pDesc = pFuncList->GetFunction( j );
2213 0 : if ( pDesc->nFIndex == nId && pDesc->pFuncName )
2214 : {
2215 0 : InsertEntry( *pDesc->pFuncName );
2216 0 : if (aFirstName.isEmpty())
2217 0 : aFirstName = *pDesc->pFuncName;
2218 0 : break; // Stop searching
2219 : }
2220 : }
2221 : }
2222 : }
2223 :
2224 : //! Re-add entry "Other..." for Function AutoPilot if it can work with text that
2225 : // has been entered so far
2226 :
2227 : // InsertEntry( ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) );
2228 :
2229 0 : SetText(aFirstName);
2230 0 : }
2231 :
2232 12805 : void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint )
2233 : {
2234 12805 : if ( !bFormulaMode )
2235 : {
2236 : // Does the list of range names need updating?
2237 12805 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
2238 12805 : if ( pSimpleHint )
2239 : {
2240 10826 : sal_uLong nHintId = pSimpleHint->GetId();
2241 10826 : if ( nHintId == SC_HINT_AREAS_CHANGED || nHintId == SC_HINT_NAVIGATOR_UPDATEALL)
2242 381 : FillRangeNames();
2243 : }
2244 1979 : else if ( dynamic_cast<const SfxEventHint*>(&rHint) )
2245 : {
2246 1979 : sal_uLong nEventId = static_cast<const SfxEventHint*>(&rHint)->GetEventId();
2247 1979 : if ( nEventId == SFX_EVENT_ACTIVATEDOC )
2248 347 : FillRangeNames();
2249 : }
2250 : }
2251 12805 : }
2252 :
2253 336 : void ScPosWnd::HideTip()
2254 : {
2255 336 : if ( nTipVisible )
2256 : {
2257 0 : Help::HideTip( nTipVisible );
2258 0 : nTipVisible = 0;
2259 : }
2260 336 : }
2261 :
2262 0 : static ScNameInputType lcl_GetInputType( const OUString& rText )
2263 : {
2264 0 : ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error
2265 :
2266 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2267 0 : if ( pViewSh )
2268 : {
2269 0 : ScViewData& rViewData = pViewSh->GetViewData();
2270 0 : ScDocument* pDoc = rViewData.GetDocument();
2271 0 : SCTAB nTab = rViewData.GetTabNo();
2272 0 : formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
2273 :
2274 : // test in same order as in SID_CURRENTCELL execute
2275 :
2276 0 : ScRange aRange;
2277 0 : ScAddress aAddress;
2278 0 : ScRangeUtil aRangeUtil;
2279 : SCTAB nNameTab;
2280 : sal_Int32 nNumeric;
2281 :
2282 0 : if (rText == ScGlobal::GetRscString(STR_MANAGE_NAMES))
2283 0 : eRet = SC_MANAGE_NAMES;
2284 0 : else if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID )
2285 0 : eRet = SC_NAME_INPUT_RANGE;
2286 0 : else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID )
2287 0 : eRet = SC_NAME_INPUT_CELL;
2288 0 : else if ( ScRangeUtil::MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) )
2289 0 : eRet = SC_NAME_INPUT_NAMEDRANGE;
2290 0 : else if ( ScRangeUtil::MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_DBASE, eConv ) )
2291 0 : eRet = SC_NAME_INPUT_DATABASE;
2292 0 : else if ( comphelper::string::isdigitAsciiString( rText ) &&
2293 0 : ( nNumeric = rText.toInt32() ) > 0 && nNumeric <= MAXROW+1 )
2294 0 : eRet = SC_NAME_INPUT_ROW;
2295 0 : else if ( pDoc->GetTable( rText, nNameTab ) )
2296 0 : eRet = SC_NAME_INPUT_SHEET;
2297 0 : else if ( ScRangeData::IsNameValid( rText, pDoc ) ) // nothing found, create new range?
2298 : {
2299 0 : if ( rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
2300 0 : eRet = SC_NAME_INPUT_DEFINE;
2301 : else
2302 0 : eRet = SC_NAME_INPUT_BAD_SELECTION;
2303 : }
2304 : else
2305 0 : eRet = SC_NAME_INPUT_BAD_NAME;
2306 : }
2307 :
2308 0 : return eRet;
2309 : }
2310 :
2311 0 : void ScPosWnd::Modify()
2312 : {
2313 0 : ComboBox::Modify();
2314 :
2315 0 : HideTip();
2316 :
2317 0 : if ( !IsTravelSelect() && !bFormulaMode )
2318 : {
2319 : // determine the action that would be taken for the current input
2320 :
2321 0 : ScNameInputType eType = lcl_GetInputType( GetText() ); // uses current view
2322 0 : sal_uInt16 nStrId = 0;
2323 0 : switch ( eType )
2324 : {
2325 : case SC_NAME_INPUT_CELL:
2326 0 : nStrId = STR_NAME_INPUT_CELL;
2327 0 : break;
2328 : case SC_NAME_INPUT_RANGE:
2329 : case SC_NAME_INPUT_NAMEDRANGE:
2330 0 : nStrId = STR_NAME_INPUT_RANGE; // named range or range reference
2331 0 : break;
2332 : case SC_NAME_INPUT_DATABASE:
2333 0 : nStrId = STR_NAME_INPUT_DBRANGE;
2334 0 : break;
2335 : case SC_NAME_INPUT_ROW:
2336 0 : nStrId = STR_NAME_INPUT_ROW;
2337 0 : break;
2338 : case SC_NAME_INPUT_SHEET:
2339 0 : nStrId = STR_NAME_INPUT_SHEET;
2340 0 : break;
2341 : case SC_NAME_INPUT_DEFINE:
2342 0 : nStrId = STR_NAME_INPUT_DEFINE;
2343 0 : break;
2344 : default:
2345 : // other cases (error): no tip help
2346 0 : break;
2347 : }
2348 :
2349 0 : if ( nStrId )
2350 : {
2351 : // show the help tip at the text cursor position
2352 :
2353 0 : vcl::Window* pWin = GetSubEdit();
2354 0 : if (!pWin)
2355 0 : pWin = this;
2356 0 : Point aPos;
2357 0 : vcl::Cursor* pCur = pWin->GetCursor();
2358 0 : if (pCur)
2359 0 : aPos = pWin->LogicToPixel( pCur->GetPos() );
2360 0 : aPos = pWin->OutputToScreenPixel( aPos );
2361 0 : Rectangle aRect( aPos, aPos );
2362 :
2363 0 : OUString aText = ScGlobal::GetRscString( nStrId );
2364 0 : QuickHelpFlags nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom;
2365 0 : nTipVisible = Help::ShowTip(pWin, aRect, aText, nAlign);
2366 : }
2367 : }
2368 0 : }
2369 :
2370 0 : void ScPosWnd::Select()
2371 : {
2372 0 : ComboBox::Select(); // In VCL GetText() only return the selected entry afterwards
2373 :
2374 0 : HideTip();
2375 :
2376 0 : if (!IsTravelSelect())
2377 0 : DoEnter();
2378 0 : }
2379 :
2380 0 : void ScPosWnd::DoEnter()
2381 : {
2382 0 : OUString aText = GetText();
2383 0 : if ( !aText.isEmpty() )
2384 : {
2385 0 : if ( bFormulaMode )
2386 : {
2387 0 : ScModule* pScMod = SC_MOD();
2388 0 : if ( aText == ScGlobal::GetRscString(STR_FUNCTIONLIST_MORE) )
2389 : {
2390 : // Function AutoPilot
2391 : //! Continue working with the text entered so far
2392 :
2393 : //! new method at ScModule to query if function autopilot is open
2394 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
2395 0 : if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
2396 : pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
2397 0 : SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
2398 : }
2399 : else
2400 : {
2401 0 : ScTabViewShell* pViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
2402 0 : ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
2403 0 : if (pHdl)
2404 0 : pHdl->InsertFunction( aText );
2405 : }
2406 : }
2407 : else
2408 : {
2409 : // depending on the input, select something or create a new named range
2410 :
2411 0 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2412 0 : if ( pViewSh )
2413 : {
2414 0 : ScViewData& rViewData = pViewSh->GetViewData();
2415 0 : ScDocShell* pDocShell = rViewData.GetDocShell();
2416 0 : ScDocument& rDoc = pDocShell->GetDocument();
2417 :
2418 0 : ScNameInputType eType = lcl_GetInputType( aText );
2419 0 : if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION )
2420 : {
2421 0 : sal_uInt16 nId = ( eType == SC_NAME_INPUT_BAD_NAME ) ? STR_NAME_ERROR_NAME : STR_NAME_ERROR_SELECTION;
2422 0 : pViewSh->ErrorMessage( nId );
2423 : }
2424 0 : else if ( eType == SC_NAME_INPUT_DEFINE )
2425 : {
2426 0 : ScRangeName* pNames = rDoc.GetRangeName();
2427 0 : ScRange aSelection;
2428 0 : if ( pNames && !pNames->findByUpperName(ScGlobal::pCharClass->uppercase(aText)) &&
2429 0 : (rViewData.GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) )
2430 : {
2431 0 : ScRangeName aNewRanges( *pNames );
2432 0 : ScAddress aCursor( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() );
2433 0 : OUString aContent(aSelection.Format(SCR_ABS_3D, &rDoc, rDoc.GetAddressConvention()));
2434 0 : ScRangeData* pNew = new ScRangeData( &rDoc, aText, aContent, aCursor );
2435 0 : if ( aNewRanges.insert(pNew) )
2436 : {
2437 0 : pDocShell->GetDocFunc().ModifyRangeNames( aNewRanges );
2438 0 : pViewSh->UpdateInputHandler(true);
2439 0 : }
2440 : }
2441 : }
2442 0 : else if (eType == SC_MANAGE_NAMES)
2443 : {
2444 0 : sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId();
2445 0 : SfxViewFrame* pViewFrm = pViewSh->GetViewFrame();
2446 0 : SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
2447 :
2448 0 : SC_MOD()->SetRefDialog( nId, pWnd == nullptr );
2449 : }
2450 : else
2451 : {
2452 : // for all selection types, execute the SID_CURRENTCELL slot.
2453 0 : if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
2454 : {
2455 : // Note that SID_CURRENTCELL always expects address to
2456 : // be in Calc A1 format. Convert the text.
2457 0 : ScRange aRange(0,0, rViewData.GetTabNo());
2458 0 : aRange.ParseAny(aText, &rDoc, rDoc.GetAddressConvention());
2459 0 : aText = aRange.Format(SCR_ABS_3D, &rDoc, ::formula::FormulaGrammar::CONV_OOO);
2460 : }
2461 :
2462 0 : SfxStringItem aPosItem( SID_CURRENTCELL, aText );
2463 0 : SfxBoolItem aUnmarkItem( FN_PARAM_1, true ); // remove existing selection
2464 :
2465 0 : pViewSh->GetViewData().GetDispatcher().Execute( SID_CURRENTCELL,
2466 : SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
2467 0 : &aPosItem, &aUnmarkItem, 0L );
2468 : }
2469 : }
2470 : }
2471 : }
2472 : else
2473 0 : SetText( aPosStr );
2474 :
2475 0 : ReleaseFocus_Impl();
2476 0 : }
2477 :
2478 753 : bool ScPosWnd::Notify( NotifyEvent& rNEvt )
2479 : {
2480 753 : bool bHandled = true;
2481 :
2482 753 : switch (rNEvt.GetType())
2483 : {
2484 : case MouseNotifyEvent::KEYINPUT:
2485 : {
2486 0 : const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2487 :
2488 0 : switch ( pKEvt->GetKeyCode().GetCode() )
2489 : {
2490 : case KEY_RETURN:
2491 0 : DoEnter();
2492 0 : break;
2493 :
2494 : case KEY_ESCAPE:
2495 0 : if (nTipVisible)
2496 : {
2497 : // escape when the tip help is shown: only hide the tip
2498 0 : HideTip();
2499 : }
2500 : else
2501 : {
2502 0 : if (!bFormulaMode)
2503 0 : SetText( aPosStr );
2504 0 : ReleaseFocus_Impl();
2505 : }
2506 0 : break;
2507 : }
2508 : }
2509 0 : break;
2510 : case MouseNotifyEvent::GETFOCUS:
2511 : {
2512 : // Select the whole text upon focus.
2513 0 : OUString aStr = GetText();
2514 0 : SetSelection(Selection(0, aStr.getLength()));
2515 : }
2516 0 : break;
2517 : case MouseNotifyEvent::LOSEFOCUS:
2518 0 : HideTip();
2519 0 : bHandled = false;
2520 0 : break;
2521 : default:
2522 753 : bHandled = false;
2523 : }
2524 :
2525 753 : if (!bHandled)
2526 753 : bHandled = ComboBox::Notify(rNEvt);
2527 :
2528 753 : return bHandled;
2529 : }
2530 :
2531 0 : void ScPosWnd::ReleaseFocus_Impl()
2532 : {
2533 0 : HideTip();
2534 :
2535 0 : SfxViewShell* pCurSh = SfxViewShell::Current();
2536 0 : ScInputHandler* pHdl = SC_MOD()->GetInputHdl( PTR_CAST( ScTabViewShell, pCurSh ) );
2537 0 : if ( pHdl && pHdl->IsTopMode() )
2538 : {
2539 : // Focus back in input row?
2540 0 : ScInputWindow* pInputWin = pHdl->GetInputWindow();
2541 0 : if (pInputWin)
2542 : {
2543 0 : pInputWin->TextGrabFocus();
2544 0 : return;
2545 : }
2546 : }
2547 :
2548 : // Set focus to active View
2549 0 : if ( pCurSh )
2550 : {
2551 0 : vcl::Window* pShellWnd = pCurSh->GetWindow();
2552 :
2553 0 : if ( pShellWnd )
2554 0 : pShellWnd->GrabFocus();
2555 : }
2556 156 : }
2557 :
2558 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|