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