Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/miscdlgs/anyrefdg.cxx
Line
Count
Source
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 <rangelst.hxx>
21
#include <comphelper/string.hxx>
22
#include <sfx2/app.hxx>
23
#include <sfx2/viewsh.hxx>
24
#include <sfx2/bindings.hxx>
25
#include <sfx2/dispatch.hxx>
26
#include <sfx2/viewfrm.hxx>
27
#include <osl/diagnose.h>
28
#include <o3tl/string_view.hxx>
29
30
#include <anyrefdg.hxx>
31
#include <sc.hrc>
32
#include <inputhdl.hxx>
33
#include <scmod.hxx>
34
#include <inputwin.hxx>
35
#include <tabvwsh.hxx>
36
#include <docsh.hxx>
37
#include <rfindlst.hxx>
38
#include <compiler.hxx>
39
#include <inputopt.hxx>
40
#include <rangeutl.hxx>
41
#include <tokenarray.hxx>
42
#include <comphelper/lok.hxx>
43
#include <output.hxx>
44
45
#include <memory>
46
47
ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg, SfxBindings* _pBindings,
48
                                                   weld::Dialog* pDialog)
49
0
    : m_pDlg(_pDlg)
50
0
    , m_pRefEdit(nullptr)
51
0
    , m_pRefBtn(nullptr)
52
0
    , m_pDialog(pDialog)
53
0
    , m_pBindings(_pBindings)
54
0
    , m_nRefTab(0)
55
0
    , m_bHighlightRef(false)
56
0
{
57
0
    ScInputOptions aInputOption = ScModule::get()->GetInputOptions();
58
0
    m_bEnableColorRef=aInputOption.GetRangeFinder();
59
0
}
60
61
ScFormulaReferenceHelper::~ScFormulaReferenceHelper()
62
0
{
63
0
    suppress_fun_call_w_exception(dispose());
64
0
}
65
66
void ScFormulaReferenceHelper::dispose()
67
0
{
68
    // common cleanup for ScAnyRefDlg and ScFormulaDlg is done here
69
0
    HideReference();
70
0
    enableInput( true );
71
72
0
    ScInputHandler* pInputHdl = ScModule::get()->GetInputHdl();
73
0
    if ( pInputHdl )
74
0
        pInputHdl->ResetDelayTimer();   // stop the timer for disabling the input line
75
76
0
    m_pDialog = nullptr;
77
0
}
78
79
void ScFormulaReferenceHelper::enableInput( bool bEnable )
80
0
{
81
0
    ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
82
0
    while( pDocShell )
83
0
    {
84
0
        SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
85
0
        while( pFrame )
86
0
        {
87
            //  enable everything except InPlace, including bean frames
88
0
            if ( !pFrame->GetFrame().IsInPlace() )
89
0
            {
90
0
                SfxViewShell* p = pFrame->GetViewShell();
91
0
                ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
92
0
                if(pViewSh!=nullptr)
93
0
                {
94
0
                    vcl::Window *pWin=pViewSh->GetWindow();
95
0
                    if(pWin)
96
0
                    {
97
0
                        vcl::Window *pParent=pWin->GetParent();
98
0
                        if(pParent)
99
0
                        {
100
0
                            pParent->EnableInput(bEnable);
101
0
                            pViewSh->EnableRefInput(bEnable);
102
0
                        }
103
0
                    }
104
0
                }
105
0
            }
106
0
            pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
107
0
        }
108
109
0
        pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
110
0
    }
111
0
}
112
113
void ScFormulaReferenceHelper::ShowSimpleReference(std::u16string_view rStr)
114
0
{
115
0
    if (!m_bEnableColorRef)
116
0
        return;
117
118
0
    m_bHighlightRef = true;
119
0
    ScViewData* pViewData=ScDocShell::GetViewData();
120
0
    if ( !pViewData )
121
0
        return;
122
123
0
    ScDocument& rDoc = pViewData->GetDocument();
124
0
    ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
125
126
0
    ScRangeList aRangeList;
127
128
0
    pTabViewShell->DoneRefMode();
129
0
    pTabViewShell->ClearHighlightRanges();
130
131
0
    if( ParseWithNames( aRangeList, rStr, rDoc ) )
132
0
    {
133
0
        for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
134
0
        {
135
0
            ScRange const & rRangeEntry = aRangeList[ i ];
136
0
            Color aColName = ScRangeFindList::GetColorName( i );
137
0
            pTabViewShell->AddHighlightRange( rRangeEntry, aColName );
138
0
        }
139
0
    }
140
0
}
141
142
bool ScFormulaReferenceHelper::ParseWithNames( ScRangeList& rRanges, std::u16string_view rStr, const ScDocument& rDoc )
143
0
{
144
0
    rRanges.RemoveAll();
145
146
0
    if (rStr.empty())
147
0
        return true;
148
149
0
    ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
150
151
0
    bool bError = false;
152
0
    sal_Int32 nIdx {0};
153
0
    do
154
0
    {
155
0
        ScRange aRange;
156
0
        OUString aRangeStr( o3tl::getToken(rStr, 0, ';', nIdx ) );
157
158
0
        ScRefFlags nFlags = aRange.ParseAny( aRangeStr, rDoc, aDetails );
159
0
        if ( nFlags & ScRefFlags::VALID )
160
0
        {
161
0
            if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO )
162
0
                aRange.aStart.SetTab( m_nRefTab );
163
0
            if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO )
164
0
                aRange.aEnd.SetTab( aRange.aStart.Tab() );
165
0
            rRanges.push_back( aRange );
166
0
        }
167
0
        else if ( ScRangeUtil::MakeRangeFromName( aRangeStr, rDoc, m_nRefTab, aRange, RUTL_NAMES, aDetails ) )
168
0
            rRanges.push_back( aRange );
169
0
        else
170
0
            bError = true;
171
0
    }
172
0
    while (nIdx>0);
173
174
0
    return !bError;
175
0
}
176
177
void ScFormulaReferenceHelper::ShowFormulaReference(const OUString& rStr)
178
0
{
179
0
    if( !m_bEnableColorRef)
180
0
        return;
181
182
0
    m_bHighlightRef=true;
183
0
    ScViewData* pViewData=ScDocShell::GetViewData();
184
0
    if ( !(pViewData && m_pRefComp) )
185
0
        return;
186
187
0
    ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
188
0
    SCCOL nCol = pViewData->GetCurX();
189
0
    SCROW nRow = pViewData->GetCurY();
190
0
    SCTAB nTab = pViewData->CurrentTabForData();
191
0
    ScAddress aPos( nCol, nRow, nTab );
192
193
0
    std::unique_ptr<ScTokenArray> pScTokA(m_pRefComp->CompileString(rStr));
194
195
0
    if (!(pTabViewShell && pScTokA))
196
0
        return;
197
198
0
    const ScViewData& rViewData = pTabViewShell->GetViewData();
199
0
    ScDocument& rDoc = rViewData.GetDocument();
200
0
    pTabViewShell->DoneRefMode();
201
0
    pTabViewShell->ClearHighlightRanges();
202
203
0
    formula::FormulaTokenArrayPlainIterator aIter(*pScTokA);
204
0
    const formula::FormulaToken* pToken = aIter.GetNextReference();
205
206
0
    sal_uInt16 nIndex=0;
207
208
0
    while(pToken!=nullptr)
209
0
    {
210
0
        bool bDoubleRef=(pToken->GetType()==formula::svDoubleRef);
211
212
0
        if(pToken->GetType()==formula::svSingleRef || bDoubleRef)
213
0
        {
214
0
            ScRange aRange;
215
0
            if(bDoubleRef)
216
0
            {
217
0
                ScComplexRefData aRef( *pToken->GetDoubleRef() );
218
0
                aRange = aRef.toAbs(rDoc, aPos);
219
0
            }
220
0
            else
221
0
            {
222
0
                ScSingleRefData aRef( *pToken->GetSingleRef() );
223
0
                aRange.aStart = aRef.toAbs(rDoc, aPos);
224
0
                aRange.aEnd = aRange.aStart;
225
0
            }
226
0
            Color aColName=ScRangeFindList::GetColorName(nIndex++);
227
0
            pTabViewShell->AddHighlightRange(aRange, aColName);
228
0
        }
229
230
0
        pToken = aIter.GetNextReference();
231
0
    }
232
0
}
233
234
void ScFormulaReferenceHelper::HideReference( bool bDoneRefMode )
235
0
{
236
0
    ScViewData* pViewData=ScDocShell::GetViewData();
237
238
0
    if( !(pViewData && m_bHighlightRef && m_bEnableColorRef))
239
0
        return;
240
241
0
    ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
242
243
0
    if(pTabViewShell!=nullptr)
244
0
    {
245
        //  bDoneRefMode is sal_False when called from before SetReference.
246
        //  In that case, RefMode was just started and must not be ended now.
247
248
0
        if ( bDoneRefMode )
249
0
            pTabViewShell->DoneRefMode();
250
0
        pTabViewShell->ClearHighlightRanges();
251
252
0
        if( comphelper::LibreOfficeKit::isActive() )
253
0
        {
254
            // Clear
255
0
            std::vector<ReferenceMark> aReferenceMarks;
256
0
            ScInputHandler::SendReferenceMarks( pTabViewShell, aReferenceMarks );
257
0
        }
258
0
    }
259
0
    m_bHighlightRef=false;
260
0
}
261
262
void ScFormulaReferenceHelper::ShowReference(const OUString& rStr)
263
0
{
264
0
    if( !m_bEnableColorRef )
265
0
        return;
266
267
    // Exclude ';' semicolon as it is the separator for ParseWithNames() used
268
    // in ShowSimpleReference(). Also sheet separator '.' dot is part of simple
269
    // reference (could be array col/row separator as well but then in '{' '}'
270
    // braces). Prefer '!' exclamation mark to be intersection operator rather
271
    // than Excel sheet separator.
272
0
    if (comphelper::string::indexOfAny( rStr, u"()+-*/^%&=<>~! #[]{},|\\@", 0) != -1)
273
0
    {
274
0
        ShowFormulaReference(rStr);
275
0
    }
276
0
    else
277
0
    {
278
0
        ShowSimpleReference(rStr);
279
0
    }
280
0
}
281
282
void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit )
283
0
{
284
0
    if( !m_pRefEdit && pEdit )
285
0
    {
286
0
        m_pDlg->RefInputStart( pEdit );
287
0
    }
288
289
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
290
0
    if( !pViewShell )
291
0
        return;
292
293
0
    pViewShell->ActiveGrabFocus();
294
0
    if( !m_pRefEdit )
295
0
        return;
296
297
0
    const ScViewData& rViewData = pViewShell->GetViewData();
298
0
    ScDocument& rDoc = rViewData.GetDocument();
299
0
    ScRangeList aRangeList;
300
0
    if( !ParseWithNames( aRangeList, m_pRefEdit->GetText(), rDoc ) )
301
0
        return;
302
303
0
    if ( !aRangeList.empty() )
304
0
    {
305
0
        const ScRange & rRange = aRangeList.front();
306
0
        pViewShell->SetTabNo( rRange.aStart.Tab() );
307
0
        pViewShell->MoveCursorAbs(  rRange.aStart.Col(),
308
0
            rRange.aStart.Row(), SC_FOLLOW_JUMP, false, false );
309
0
        pViewShell->MoveCursorAbs( rRange.aEnd.Col(),
310
0
            rRange.aEnd.Row(), SC_FOLLOW_JUMP, true, false );
311
0
        m_pDlg->SetReference( rRange, rDoc );
312
0
    }
313
0
}
314
315
void ScFormulaReferenceHelper::Init()
316
0
{
317
0
    ScViewData* pViewData=ScDocShell::GetViewData();    //! use pScViewShell?
318
0
    if ( !pViewData )
319
0
        return;
320
321
0
    ScDocument& rDoc = pViewData->GetDocument();
322
0
    SCCOL nCol = pViewData->GetCurX();
323
0
    SCROW nRow = pViewData->GetCurY();
324
0
    SCTAB nTab = pViewData->CurrentTabForData();
325
0
    ScAddress aCursorPos( nCol, nRow, nTab );
326
327
0
    m_pRefComp.reset( new ScCompiler( rDoc, aCursorPos, rDoc.GetGrammar()) );
328
0
    m_pRefComp->EnableJumpCommandReorder(false);
329
0
    m_pRefComp->EnableStopOnError(false);
330
331
0
    m_nRefTab = nTab;
332
0
}
333
334
IMPL_LINK_NOARG(ScFormulaReferenceHelper, ActivateHdl, weld::Widget&, bool)
335
0
{
336
0
    if (m_pRefEdit)
337
0
        m_pRefEdit->GrabFocus();
338
0
    m_pDlg->RefInputDone(true);
339
0
    return true;
340
0
}
341
342
void ScFormulaReferenceHelper::RefInputDone( bool bForced )
343
0
{
344
0
    if ( !CanInputDone( bForced ) )
345
0
        return;
346
347
0
    if (!m_pDialog)
348
0
        return;
349
350
    // Adjust window title
351
0
    m_pDialog->set_title(m_sOldDialogText);
352
353
0
    if (m_pRefEdit)
354
0
        m_pRefEdit->SetActivateHdl(Link<weld::Widget&, bool>());
355
356
    // set button image
357
0
    if (m_pRefBtn)
358
0
    {
359
0
        m_pRefBtn->SetActivateHdl(Link<weld::Widget&, bool>());
360
0
        m_pRefBtn->SetStartImage();
361
0
    }
362
363
0
    m_pDialog->undo_collapse();
364
365
0
    m_pRefEdit = nullptr;
366
0
    m_pRefBtn = nullptr;
367
0
}
368
369
void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
370
0
{
371
0
    if (m_pRefEdit)
372
0
        return;
373
374
0
    m_pRefEdit = pEdit;
375
0
    m_pRefBtn  = pButton;
376
377
    // Save and adjust window title
378
0
    m_sOldDialogText = m_pDialog->get_title();
379
0
    const OUString sLabel = m_pRefEdit->GetLabelTextForShrinkMode();
380
0
    if (!sLabel.isEmpty())
381
0
    {
382
0
        const OUString sNewDialogText = m_sOldDialogText + ": " + comphelper::string::stripEnd(sLabel, ':');
383
0
        m_pDialog->set_title(m_pDialog->strip_mnemonic(sNewDialogText));
384
0
    }
385
386
0
    assert(pEdit && pEdit->GetWidget());
387
0
    m_pDialog->collapse(*pEdit->GetWidget(), pButton ? pButton->GetWidget() : nullptr);
388
389
    // set button image
390
0
    if (pButton)
391
0
        pButton->SetEndImage();
392
393
0
    m_pRefEdit->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
394
0
    if (m_pRefBtn)
395
0
        m_pRefBtn->SetActivateHdl(LINK(this, ScFormulaReferenceHelper, ActivateHdl));
396
0
}
397
398
void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
399
0
{
400
0
    if( !pEdit )
401
0
        return;
402
403
0
    if( m_pRefEdit == pEdit )                 // is this the active ref edit field?
404
0
    {
405
0
        m_pRefEdit->GrabFocus();              // before RefInputDone()
406
0
        m_pDlg->RefInputDone( true );               // finish ref input
407
0
    }
408
0
    else
409
0
    {
410
0
        m_pDlg->RefInputDone( true );               // another active ref edit?
411
0
        m_pDlg->RefInputStart( pEdit, pButton );    // start ref input
412
        // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
413
0
        if( m_pRefEdit )
414
0
            m_pRefEdit->GrabFocus();
415
0
    }
416
0
}
417
418
void ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
419
0
{
420
0
    SfxApplication* pSfxApp = SfxGetpApp();
421
422
0
    SetDispatcherLock( false );         //! here and in dtor ?
423
424
0
    SfxViewFrame* pViewFrm = SfxViewFrame::Current();
425
0
    if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) )
426
0
    {
427
        //  The input row is disabled with ToolBox::Disable disabled, thus it must be
428
        //  reenabled with ToolBox::Enable (before the AppWindow is enabled)
429
        //  for the buttons to be drawn as enabled.
430
0
        SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS);
431
0
        if (pChild)
432
0
        {
433
0
            ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow());
434
0
            pWin->Enable();
435
0
        }
436
0
    }
437
438
    // find parent view frame to close dialog
439
0
    SfxViewFrame* pMyViewFrm = nullptr;
440
0
    if ( m_pBindings )
441
0
    {
442
0
        SfxDispatcher* pMyDisp = m_pBindings->GetDispatcher();
443
0
        if (pMyDisp)
444
0
            pMyViewFrm = pMyDisp->GetFrame();
445
0
    }
446
0
    ScModule::get()->SetRefDialog(nId, false, pMyViewFrm);
447
448
0
    pSfxApp->Broadcast( SfxHint( SfxHintId::ScKillEditView ) );
449
450
0
    ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
451
0
    if ( pScViewShell )
452
0
        pScViewShell->UpdateInputHandler(true);
453
0
}
454
455
void ScFormulaReferenceHelper::SetDispatcherLock( bool bLock )
456
0
{
457
0
    if (!comphelper::LibreOfficeKit::isActive())
458
0
    {
459
        // lock / unlock only the dispatchers of Calc documents
460
0
        ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
461
0
        while (pDocShell)
462
0
        {
463
0
            SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDocShell);
464
0
            while (pFrame)
465
0
            {
466
0
                SfxDispatcher* pDisp = pFrame->GetDispatcher();
467
0
                if (pDisp)
468
0
                    pDisp->Lock(bLock);
469
0
                pFrame = SfxViewFrame::GetNext(*pFrame, pDocShell);
470
0
            }
471
0
            pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
472
0
        }
473
0
        return;
474
        // if a new view is created while the dialog is open,
475
        // that view's dispatcher is locked when trying to create the dialog
476
        // for that view (ScTabViewShell::CreateRefDialog)
477
0
    }
478
479
    //  lock / unlock only the dispatcher of Calc document
480
0
    SfxDispatcher* pDisp = nullptr;
481
0
    if ( m_pBindings )
482
0
    {
483
0
        pDisp = m_pBindings->GetDispatcher();
484
0
    }
485
0
    else if(SfxViewFrame* pViewFrame = SfxViewFrame::Current())
486
0
    {
487
0
        if (dynamic_cast< ScTabViewShell* >(pViewFrame->GetViewShell()))
488
0
            pDisp = pViewFrame->GetDispatcher();
489
0
    }
490
491
0
    if (pDisp)
492
0
        pDisp->Lock(bLock);
493
0
}
494
495
void ScFormulaReferenceHelper::ViewShellChanged()
496
0
{
497
0
    enableInput( false );
498
499
0
    EnableSpreadsheets();
500
0
}
501
void ScFormulaReferenceHelper::EnableSpreadsheets(bool bFlag)
502
0
{
503
0
    ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
504
0
    while( pDocShell )
505
0
    {
506
0
        SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
507
0
        while( pFrame )
508
0
        {
509
            //  enable everything except InPlace, including bean frames
510
0
            if ( !pFrame->GetFrame().IsInPlace() )
511
0
            {
512
0
                SfxViewShell* p = pFrame->GetViewShell();
513
0
                ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
514
0
                if(pViewSh!=nullptr)
515
0
                {
516
0
                    vcl::Window *pWin=pViewSh->GetWindow();
517
0
                    if(pWin)
518
0
                    {
519
0
                        vcl::Window *pParent=pWin->GetParent();
520
0
                        if(pParent)
521
0
                        {
522
0
                            pParent->EnableInput(bFlag,false);
523
0
                            pViewSh->EnableRefInput(bFlag);
524
0
                        }
525
0
                    }
526
0
                }
527
0
            }
528
0
            pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
529
0
        }
530
531
0
        pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
532
0
    }
533
0
}
534
535
static void lcl_InvalidateWindows()
536
0
{
537
0
    ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<ScDocShell>));
538
0
    while( pDocShell )
539
0
    {
540
0
        SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
541
0
        while( pFrame )
542
0
        {
543
            //  enable everything except InPlace, including bean frames
544
0
            if ( !pFrame->GetFrame().IsInPlace() )
545
0
            {
546
0
                SfxViewShell* p = pFrame->GetViewShell();
547
0
                ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
548
0
                if(pViewSh!=nullptr)
549
0
                {
550
0
                    vcl::Window *pWin=pViewSh->GetWindow();
551
0
                    if(pWin)
552
0
                    {
553
0
                        vcl::Window *pParent=pWin->GetParent();
554
0
                        if(pParent)
555
0
                            pParent->Invalidate();
556
0
                    }
557
0
                }
558
0
            }
559
0
            pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
560
0
        }
561
562
0
        pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, checkSfxObjectShell<ScDocShell>));
563
0
    }
564
0
}
565
566
static void lcl_HideAllReferences()
567
0
{
568
0
    SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
569
0
    while ( pSh )
570
0
    {
571
0
        static_cast<ScTabViewShell*>(pSh)->ClearHighlightRanges();
572
0
        pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
573
0
    }
574
0
}
575
576
ScRefHandler::ScRefHandler(SfxDialogController& rController, SfxBindings* pB, bool bBindRef)
577
0
    : m_pController(&rController)
578
0
    , m_bInRefMode(false)
579
0
    , m_aHelper(this, pB, rController.getDialog())
580
0
    , m_pMyBindings(pB)
581
0
{
582
0
    if( bBindRef ) EnterRefMode();
583
0
}
584
585
bool ScRefHandler::EnterRefMode()
586
0
{
587
0
    if( m_bInRefMode ) return false;
588
589
0
    ScModule* mod = ScModule::get();
590
0
    mod->InputEnterHandler();
591
592
0
    ScTabViewShell* pScViewShell = nullptr;
593
594
    // title has to be from the view that opened the dialog,
595
    // even if it's not the current view
596
597
0
    SfxObjectShell* pParentDoc = nullptr;
598
0
    if ( m_pMyBindings )
599
0
    {
600
0
        SfxDispatcher* pMyDisp = m_pMyBindings->GetDispatcher();
601
0
        if (pMyDisp)
602
0
        {
603
0
            SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
604
0
            if (pMyViewFrm)
605
0
            {
606
0
                pScViewShell = dynamic_cast<ScTabViewShell*>( pMyViewFrm->GetViewShell()  );
607
0
                if( pScViewShell )
608
0
                    pScViewShell->UpdateInputHandler(true);
609
0
                pParentDoc = pMyViewFrm->GetObjectShell();
610
0
            }
611
0
        }
612
0
    }
613
0
    if ( !pParentDoc && pScViewShell )                  // use current only if above fails
614
0
        pParentDoc = pScViewShell->GetObjectShell();
615
0
    if ( pParentDoc )
616
0
        m_aDocName = pParentDoc->GetTitle();
617
618
0
    ScInputHandler* pInputHdl = mod->GetInputHdl(pScViewShell);
619
620
0
    OSL_ENSURE( pInputHdl, "Missing input handler :-/" );
621
622
0
    if ( pInputHdl )
623
0
        pInputHdl->NotifyChange( nullptr );
624
625
0
    ScFormulaReferenceHelper::enableInput( false );
626
627
0
    ScFormulaReferenceHelper::EnableSpreadsheets();
628
629
0
    m_aHelper.Init();
630
631
0
    m_aHelper.SetDispatcherLock( true );
632
633
0
    m_bInRefMode = true;
634
0
    return m_bInRefMode;
635
0
}
636
637
ScRefHandler::~ScRefHandler()
638
0
{
639
0
    suppress_fun_call_w_exception(disposeRefHandler());
640
0
}
641
642
void ScRefHandler::disposeRefHandler()
643
0
{
644
0
    m_pController = nullptr;
645
0
    LeaveRefMode();
646
0
    m_aHelper.dispose();
647
0
}
648
649
bool ScRefHandler::LeaveRefMode()
650
0
{
651
0
    if( !m_bInRefMode ) return false;
652
653
0
    lcl_HideAllReferences();
654
655
0
    SetDispatcherLock( false );         //! here and in DoClose ?
656
657
0
    ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
658
0
    if( pScViewShell )
659
0
        pScViewShell->UpdateInputHandler(true);
660
661
0
    lcl_InvalidateWindows();
662
663
0
    m_bInRefMode = false;
664
0
    return true;
665
0
}
666
667
void ScRefHandler::SwitchToDocument()
668
0
{
669
0
    ScTabViewShell* pCurrent = ScTabViewShell::GetActiveViewShell();
670
0
    if (pCurrent)
671
0
    {
672
0
        SfxObjectShell* pObjSh = pCurrent->GetObjectShell();
673
0
        if ( pObjSh && pObjSh->GetTitle() == m_aDocName )
674
0
        {
675
            //  right document already visible -> nothing to do
676
0
            return;
677
0
        }
678
0
    }
679
680
0
    SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
681
0
    while ( pSh )
682
0
    {
683
0
        SfxObjectShell* pObjSh = pSh->GetObjectShell();
684
0
        if ( pObjSh && pObjSh->GetTitle() == m_aDocName )
685
0
        {
686
            //  switch to first TabViewShell for document
687
0
            static_cast<ScTabViewShell*>(pSh)->SetActive();
688
0
            return;
689
0
        }
690
0
        pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
691
0
    }
692
0
}
693
694
bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const   // pDocSh may be 0
695
0
{
696
    //  if aDocName isn't initialized, allow
697
0
    if ( m_aDocName.isEmpty() )
698
0
        return true;
699
700
0
    if ( !pDocSh )
701
0
        return false;
702
703
    //  default: allow only same document (overridden in function dialog)
704
0
    return m_aDocName==pDocSh->GetTitle();
705
0
}
706
707
bool ScRefHandler::IsRefInputMode() const
708
0
{
709
0
    return m_pController->getDialog()->get_visible();
710
0
}
711
712
bool ScRefHandler::DoClose( sal_uInt16 nId )
713
0
{
714
0
    m_aHelper.DoClose(nId);
715
0
    return true;
716
0
}
717
718
void ScRefHandler::SetDispatcherLock( bool bLock )
719
0
{
720
0
    m_aHelper.SetDispatcherLock( bLock );
721
0
}
722
723
void ScRefHandler::ViewShellChanged()
724
0
{
725
0
    ScFormulaReferenceHelper::ViewShellChanged();
726
0
}
727
728
void ScRefHandler::AddRefEntry()
729
0
{
730
    // override this for multi-references
731
0
}
732
733
bool ScRefHandler::IsTableLocked() const
734
0
{
735
    // the default is that the sheet can be switched during while the reference is edited
736
737
0
    return false;
738
0
}
739
740
//  RefInputStart/Done: Zoom-In (AutoHide) on single field
741
//  (using button or movement)
742
743
void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
744
0
{
745
0
    m_aHelper.RefInputStart( pEdit, pButton );
746
0
}
747
748
void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
749
0
{
750
0
    m_aHelper.ToggleCollapsed( pEdit, pButton );
751
0
}
752
753
bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, std::u16string_view rStr, const ScDocument& rDoc )
754
0
{
755
0
    return m_aHelper.ParseWithNames( rRanges, rStr, rDoc );
756
0
}
757
758
void ScRefHandler::HideReference( bool bDoneRefMode )
759
0
{
760
0
    m_aHelper.HideReference( bDoneRefMode );
761
0
}
762
763
void ScRefHandler::ShowReference(const OUString& rStr)
764
0
{
765
0
    m_aHelper.ShowReference(rStr);
766
0
}
767
768
void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit )
769
0
{
770
0
    m_aHelper.ReleaseFocus( pEdit );
771
0
}
772
773
void ScRefHandler::RefInputDone( bool bForced )
774
0
{
775
0
    m_aHelper.RefInputDone( bForced );
776
0
}
777
778
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */