Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/navipi/navipi.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 <sfx2/app.hxx>
21
#include <sfx2/bindings.hxx>
22
#include <sfx2/dispatch.hxx>
23
#include <sfx2/event.hxx>
24
#include <sfx2/navigat.hxx>
25
#include <svl/stritem.hxx>
26
#include <unotools/charclass.hxx>
27
28
#include <viewdata.hxx>
29
#include <tabvwsh.hxx>
30
#include <docsh.hxx>
31
#include <document.hxx>
32
#include <rangeutl.hxx>
33
#include <sc.hrc>
34
#include <strings.hrc>
35
#include <bitmaps.hlst>
36
#include <scresid.hxx>
37
#include <scmod.hxx>
38
#include <navicfg.hxx>
39
#include <navcitem.hxx>
40
#include <navipi.hxx>
41
#include <navsett.hxx>
42
#include <markdata.hxx>
43
44
#include <vcl/jsdialog/executor.hxx>
45
46
#include <com/sun/star/uno/Reference.hxx>
47
48
using namespace com::sun::star;
49
50
//  maximum values for UI
51
0
static SCCOL SCNAV_MAXCOL(const ScSheetLimits& rLimits) { return rLimits.GetMaxColCount(); }
52
static sal_Int32 SCNAV_COLDIGITS(const ScSheetLimits& rLimits)
53
0
{
54
0
    return static_cast<sal_Int32>( floor( log10( static_cast<double>(SCNAV_MAXCOL(rLimits)))) ) + 1;   // 1...256...18278
55
0
}
56
static sal_Int32 SCNAV_COLLETTERS(const ScSheetLimits& rLimits)
57
0
{
58
0
    return ::ScColToAlpha(SCNAV_MAXCOL(rLimits)).getLength();    // A...IV...ZZZ
59
0
}
60
61
static SCROW SCNAV_MAXROW(const ScSheetLimits& rSheetLimits)
62
0
{
63
0
    return rSheetLimits.GetMaxRowCount();
64
0
}
65
66
void ScNavigatorDlg::ReleaseFocus()
67
0
{
68
0
    SfxViewShell* pCurSh = SfxViewShell::Current();
69
70
0
    if ( pCurSh )
71
0
    {
72
0
        vcl::Window* pShellWnd = pCurSh->GetWindow();
73
0
        if ( pShellWnd )
74
0
            pShellWnd->GrabFocus();
75
0
    }
76
0
}
77
78
namespace
79
{
80
    SCCOL NumToAlpha(const ScSheetLimits& rSheetLimits, SCCOL nColNo)
81
0
    {
82
0
        if ( nColNo > SCNAV_MAXCOL(rSheetLimits) )
83
0
            nColNo = SCNAV_MAXCOL(rSheetLimits);
84
0
        else if ( nColNo < 1 )
85
0
            nColNo = 1;
86
87
0
        return nColNo;
88
0
    }
89
90
    SCCOL AlphaToNum(const ScDocument& rDoc, const OUString& rStr)
91
0
    {
92
0
        SCCOL  nColumn = 0;
93
94
0
        if ( CharClass::isAsciiAlpha( rStr) )
95
0
        {
96
0
            const OUString aUpperCaseStr = rStr.toAsciiUpperCase();
97
98
0
            if (::AlphaToCol( rDoc, nColumn, aUpperCaseStr))
99
0
                ++nColumn;
100
101
0
            if ( (aUpperCaseStr.getLength() > SCNAV_COLLETTERS(rDoc.GetSheetLimits())) ||
102
0
                 (nColumn > SCNAV_MAXCOL(rDoc.GetSheetLimits())) )
103
0
            {
104
0
                nColumn = SCNAV_MAXCOL(rDoc.GetSheetLimits());
105
0
            }
106
0
        }
107
108
0
        return nColumn;
109
0
    }
110
}
111
112
IMPL_STATIC_LINK(ScNavigatorDlg, ParseRowInputHdl, const OUString&, rStrCol, std::optional<int>)
113
0
{
114
0
    SCCOL nCol(0);
115
116
0
    if (!rStrCol.isEmpty())
117
0
    {
118
0
        if (ScViewData* pData = GetViewData())
119
0
        {
120
0
            ScDocument& rDoc = pData->GetDocument();
121
122
0
            if ( CharClass::isAsciiNumeric(rStrCol) )
123
0
                nCol = NumToAlpha(rDoc.GetSheetLimits(), static_cast<SCCOL>(rStrCol.toInt32()));
124
0
            else
125
0
                nCol = AlphaToNum( rDoc, rStrCol );
126
0
        }
127
0
    }
128
129
0
    return std::optional<int>(nCol);
130
0
}
131
132
IMPL_LINK_NOARG(ScNavigatorDlg, ExecuteColHdl, weld::Entry&, bool)
133
0
{
134
0
    ReleaseFocus();
135
136
0
    SCROW nRow = m_xEdRow->get_value();
137
0
    SCCOL nCol = m_xEdCol->get_value();
138
139
0
    if ( (nCol > 0) && (nRow > 0) )
140
0
        SetCurrentCell(nCol - 1, nRow - 1);
141
142
0
    return true;
143
0
}
144
145
IMPL_STATIC_LINK(ScNavigatorDlg, FormatRowOutputHdl, sal_Int64, nValue, OUString)
146
0
{
147
0
    return ::ScColToAlpha(nValue - 1);
148
0
}
149
150
IMPL_LINK_NOARG(ScNavigatorDlg, ExecuteRowHdl, weld::Entry&, bool)
151
0
{
152
0
    ReleaseFocus();
153
154
0
    SCCOL nCol = m_xEdCol->get_value();
155
0
    SCROW nRow = m_xEdRow->get_value();
156
157
0
    if ( (nCol > 0) && (nRow > 0) )
158
0
        SetCurrentCell(nCol - 1, nRow - 1);
159
160
0
    return true;
161
0
}
162
163
IMPL_LINK(ScNavigatorDlg, DocumentSelectHdl, weld::ComboBox&, rListBox, void)
164
0
{
165
0
    ScNavigatorDlg::ReleaseFocus();
166
167
0
    OUString aDocName = rListBox.get_active_text();
168
0
    m_xLbEntries->SelectDoc(aDocName);
169
0
}
170
171
IMPL_LINK(ScNavigatorDlg, ToolBoxSelectHdl, const OUString&, rSelId, void)
172
0
{
173
    //  Switch the mode?
174
0
    if (rSelId == "contents" || rSelId == "scenarios")
175
0
    {
176
0
        NavListMode eOldMode = eListMode;
177
0
        NavListMode eNewMode;
178
179
0
        if (rSelId == "scenarios")
180
0
        {
181
0
            if (eOldMode == NAV_LMODE_SCENARIOS)
182
0
                eNewMode = NAV_LMODE_AREAS;
183
0
            else
184
0
                eNewMode = NAV_LMODE_SCENARIOS;
185
0
        }
186
0
        else                                            // on/off
187
0
        {
188
0
            if (eOldMode == NAV_LMODE_NONE)
189
0
                eNewMode = NAV_LMODE_AREAS;
190
0
            else
191
0
                eNewMode = NAV_LMODE_NONE;
192
0
        }
193
0
        SetListMode(eNewMode);
194
0
        UpdateButtons();
195
0
    }
196
0
    else if (rSelId == "dragmode")
197
0
        m_xTbxCmd2->set_menu_item_active(u"dragmode"_ustr, !m_xTbxCmd2->get_menu_item_active(u"dragmode"_ustr));
198
0
    else
199
0
    {
200
0
        if (rSelId == "datarange")
201
0
            MarkDataArea();
202
0
        else if (rSelId == "start")
203
0
            StartOfDataArea();
204
0
        else if (rSelId == "end")
205
0
            EndOfDataArea();
206
0
        else if (rSelId == "toggle")
207
0
        {
208
0
            m_xLbEntries->ToggleRoot();
209
0
            UpdateButtons();
210
0
        }
211
0
    }
212
0
}
213
214
IMPL_LINK(ScNavigatorDlg, ToolBoxDropdownClickHdl, const OUString&, rCommand, void)
215
0
{
216
0
    if (!m_xTbxCmd2->get_menu_item_active(rCommand))
217
0
        return;
218
219
    // the popup menu of the drop mode has to be called in the
220
    // click (button down) and not in the select (button up)
221
0
    if (rCommand != "dragmode")
222
0
        return;
223
224
0
    switch (GetDropMode())
225
0
    {
226
0
        case 0:
227
0
            m_xDragModeMenu->set_active(u"hyperlink"_ustr, true);
228
0
            break;
229
0
        case 1:
230
0
            m_xDragModeMenu->set_active(u"link"_ustr, true);
231
0
            break;
232
0
        case 2:
233
0
            m_xDragModeMenu->set_active(u"copy"_ustr, true);
234
0
            break;
235
0
    }
236
0
}
237
238
IMPL_LINK(ScNavigatorDlg, MenuSelectHdl, const OUString&, rIdent, void)
239
0
{
240
0
    if (rIdent == u"hyperlink")
241
0
        SetDropMode(0);
242
0
    else if (rIdent == u"link")
243
0
        SetDropMode(1);
244
0
    else if (rIdent == u"copy")
245
0
        SetDropMode(2);
246
0
}
247
248
void ScNavigatorDlg::UpdateButtons()
249
0
{
250
0
    NavListMode eMode = eListMode;
251
0
    m_xTbxCmd2->set_item_active(u"scenarios"_ustr, eMode == NAV_LMODE_SCENARIOS);
252
0
    m_xTbxCmd1->set_item_active(u"contents"_ustr, eMode != NAV_LMODE_NONE);
253
254
    // the toggle button:
255
0
    if (eMode == NAV_LMODE_SCENARIOS || eMode == NAV_LMODE_NONE)
256
0
    {
257
0
        m_xTbxCmd2->set_item_sensitive(u"toggle"_ustr, false);
258
0
        m_xTbxCmd2->set_item_active(u"toggle"_ustr, false);
259
0
    }
260
0
    else
261
0
    {
262
0
        m_xTbxCmd2->set_item_sensitive(u"toggle"_ustr, true);
263
0
        bool bRootSet = m_xLbEntries->GetRootType() != ScContentId::ROOT;
264
0
        m_xTbxCmd2->set_item_active(u"toggle"_ustr, bRootSet);
265
0
    }
266
267
0
    OUString sImageId;
268
0
    switch (nDropMode)
269
0
    {
270
0
        case SC_DROPMODE_URL:
271
0
            sImageId = RID_BMP_DROP_URL;
272
0
            break;
273
0
        case SC_DROPMODE_LINK:
274
0
            sImageId = RID_BMP_DROP_LINK;
275
0
            break;
276
0
        case SC_DROPMODE_COPY:
277
0
            sImageId = RID_BMP_DROP_COPY;
278
0
            break;
279
0
    }
280
0
    m_xTbxCmd2->set_item_icon_name(u"dragmode"_ustr, sImageId);
281
0
}
282
283
ScNavigatorSettings::ScNavigatorSettings()
284
0
    : mnRootSelected(ScContentId::ROOT)
285
0
    , mnChildSelected(SC_CONTENT_NOCHILD)
286
0
{
287
0
    maExpandedVec.fill(false);
288
0
}
289
290
ScNavigatorWin::ScNavigatorWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr,
291
                               vcl::Window* _pParent, SfxChildWinInfo* pInfo)
292
0
    : SfxNavigator(_pBindings, _pMgr, _pParent, pInfo)
293
0
{
294
0
    m_xNavigator = std::make_unique<ScNavigatorDlg>(_pBindings, m_xContainer.get(), this);
295
0
    SetMinOutputSizePixel(GetOptimalSize());
296
0
}
Unexecuted instantiation: ScNavigatorWin::ScNavigatorWin(SfxBindings*, SfxChildWindow*, vcl::Window*, SfxChildWinInfo*)
Unexecuted instantiation: ScNavigatorWin::ScNavigatorWin(SfxBindings*, SfxChildWindow*, vcl::Window*, SfxChildWinInfo*)
297
298
ScNavigatorDlg::ScNavigatorDlg(SfxBindings* pB, weld::Widget* pParent, SfxNavigator* pNavigatorDlg)
299
0
    : PanelLayout(pParent, u"NavigatorPanel"_ustr, u"modules/scalc/ui/navigatorpanel.ui"_ustr)
300
0
    , rBindings(*pB)
301
0
    , m_xEdCol(m_xBuilder->weld_spin_button(u"column"_ustr))
302
0
    , m_xEdRow(m_xBuilder->weld_spin_button(u"row"_ustr))
303
0
    , m_xTbxCmd1(m_xBuilder->weld_toolbar(u"toolbox1"_ustr))
304
0
    , m_xTbxCmd2(m_xBuilder->weld_toolbar(u"toolbox2"_ustr))
305
0
    , m_xLbEntries(new ScContentTree(m_xBuilder->weld_tree_view(u"contentbox"_ustr), this))
306
0
    , m_xScenarioBox(m_xBuilder->weld_widget(u"scenariobox"_ustr))
307
0
    , m_xWndScenarios(new ScScenarioWindow(*m_xBuilder,
308
0
        ScResId(SCSTR_QHLP_SCEN_LISTBOX), ScResId(SCSTR_QHLP_SCEN_COMMENT)))
309
0
    , m_xLbDocuments(m_xBuilder->weld_combo_box(u"documents"_ustr))
310
0
    , m_xDragModeMenu(m_xBuilder->weld_menu(u"dragmodemenu"_ustr))
311
0
    , m_xNavigatorDlg(pNavigatorDlg)
312
0
    , aContentIdle("ScNavigatorDlg aContentIdle")
313
0
    , aStrActiveWin(ScResId(SCSTR_ACTIVEWIN))
314
0
    , eListMode(NAV_LMODE_NONE)
315
0
    , nDropMode(SC_DROPMODE_URL)
316
0
    , nCurCol(0)
317
0
    , nCurRow(0)
318
0
    , nCurTab(0)
319
0
{
320
321
0
    if (comphelper::LibreOfficeKit::isActive())
322
0
    {
323
0
        sal_uInt64 nShellId = reinterpret_cast<sal_uInt64>(SfxViewShell::Current());
324
0
        jsdialog::SendNavigatorForView(nShellId);
325
0
    }
326
327
0
    UpdateInitShow();
328
329
0
    UpdateSheetLimits();
330
0
    m_xEdRow->set_width_chars(5);
331
    //max rows is 1,000,000, which is too long for typical use
332
0
    m_xEdRow->connect_activate(LINK(this, ScNavigatorDlg, ExecuteRowHdl));
333
334
0
    m_xEdCol->connect_activate(LINK(this, ScNavigatorDlg, ExecuteColHdl));
335
0
    m_xEdCol->set_value_formatter(LINK(this, ScNavigatorDlg, FormatRowOutputHdl));
336
0
    m_xEdCol->set_text_parser(LINK(this, ScNavigatorDlg, ParseRowInputHdl));
337
338
0
    m_xTbxCmd1->connect_clicked(LINK(this, ScNavigatorDlg, ToolBoxSelectHdl));
339
0
    m_xTbxCmd2->connect_clicked(LINK(this, ScNavigatorDlg, ToolBoxSelectHdl));
340
341
0
    m_xTbxCmd2->set_item_menu(u"dragmode"_ustr, m_xDragModeMenu.get());
342
0
    m_xDragModeMenu->connect_activate(LINK(this, ScNavigatorDlg, MenuSelectHdl));
343
0
    m_xTbxCmd2->connect_menu_toggled(LINK(this, ScNavigatorDlg, ToolBoxDropdownClickHdl));
344
345
0
    ScNavipiCfg& rCfg = ScModule::get()->GetNavipiCfg();
346
0
    nDropMode = rCfg.GetDragMode();
347
348
0
    m_xLbDocuments->set_size_request(42, -1); // set a nominal width so it takes width of surroundings
349
0
    m_xLbDocuments->connect_changed(LINK(this, ScNavigatorDlg, DocumentSelectHdl));
350
0
    aStrActive    = " (" + ScResId(SCSTR_ACTIVE) + ")";     // " (active)"
351
0
    aStrNotActive = " (" + ScResId(SCSTR_NOTACTIVE) + ")";  // " (not active)"
352
353
0
    rBindings.ENTERREGISTRATIONS();
354
355
0
    mvBoundItems[0].reset(new ScNavigatorControllerItem(SID_CURRENTCELL,*this,rBindings));
356
0
    mvBoundItems[1].reset(new ScNavigatorControllerItem(SID_CURRENTTAB,*this,rBindings));
357
0
    mvBoundItems[2].reset(new ScNavigatorControllerItem(SID_CURRENTDOC,*this,rBindings));
358
0
    mvBoundItems[3].reset(new ScNavigatorControllerItem(SID_SELECT_SCENARIO,*this,rBindings));
359
360
0
    rBindings.LEAVEREGISTRATIONS();
361
362
0
    StartListening( *(SfxGetpApp()) );
363
0
    StartListening( rBindings );
364
365
    //  was a category chosen as root?
366
0
    ScContentId nLastRoot = rCfg.GetRootType();
367
0
    if ( nLastRoot != ScContentId::ROOT )
368
0
        m_xLbEntries->SetRootType( nLastRoot );
369
370
0
    GetDocNames(nullptr);
371
372
0
    UpdateButtons();
373
374
0
    UpdateColumn();
375
0
    UpdateRow();
376
0
    UpdateTable(nullptr);
377
0
    m_xLbEntries->hide();
378
0
    m_xScenarioBox->hide();
379
380
0
    aContentIdle.SetInvokeHandler( LINK( this, ScNavigatorDlg, TimeHdl ) );
381
0
    aContentIdle.SetPriority( TaskPriority::LOWEST );
382
383
0
    m_xLbEntries->SetNavigatorDlgFlag(true);
384
385
    // if scenario was active, switch on
386
0
    NavListMode eNavMode = static_cast<NavListMode>(rCfg.GetListMode());
387
0
    if (eNavMode == NAV_LMODE_SCENARIOS)
388
0
        m_xTbxCmd2->set_item_active(u"scenarios"_ustr, true);
389
0
    else
390
0
        eNavMode = NAV_LMODE_AREAS;
391
0
    SetListMode(eNavMode);
392
393
0
    if(comphelper::LibreOfficeKit::isActive())
394
0
    {
395
0
        m_xBuilder->weld_container(u"gridbuttons"_ustr)->hide();
396
0
        m_xLbDocuments->hide();
397
0
    }
398
0
}
399
400
weld::Window* ScNavigatorDlg::GetFrameWeld() const
401
0
{
402
0
    if (m_xNavigatorDlg)
403
0
        return m_xNavigatorDlg->GetFrameWeld();
404
0
    return PanelLayout::GetFrameWeld();
405
0
}
406
407
void ScNavigatorDlg::UpdateSheetLimits()
408
0
{
409
0
    if (ScViewData* pData = GetViewData())
410
0
    {
411
0
        ScDocument& rDoc = pData->GetDocument();
412
0
        m_xEdRow->set_range(1, SCNAV_MAXROW(rDoc.GetSheetLimits()));
413
0
        m_xEdCol->set_range(1, SCNAV_MAXCOL(rDoc.GetSheetLimits()));
414
0
        m_xEdCol->set_width_chars(SCNAV_COLDIGITS(rDoc.GetSheetLimits()));   // 1...256...18278 or A...IV...ZZZ
415
0
    }
416
0
}
417
418
void ScNavigatorDlg::UpdateInitShow()
419
0
{
420
    // When the navigator is displayed in the sidebar, or is otherwise
421
    // docked, it has the whole deck to fill. Therefore hide the button that
422
    // hides all controls below the top two rows of buttons.
423
0
    m_xTbxCmd1->set_item_visible(u"contents"_ustr, ParentIsFloatingWindow(m_xNavigatorDlg));
424
0
}
425
426
void ScNavigatorWin::StateChanged(StateChangedType nStateChange)
427
0
{
428
0
    SfxNavigator::StateChanged(nStateChange);
429
0
    if (nStateChange == StateChangedType::InitShow)
430
0
        m_xNavigator->UpdateInitShow();
431
0
}
432
433
ScNavigatorDlg::~ScNavigatorDlg()
434
0
{
435
0
    aContentIdle.Stop();
436
437
0
    for (auto & p : mvBoundItems)
438
0
        p.reset();
439
0
    moMarkArea.reset();
440
441
0
    EndListening( *(SfxGetpApp()) );
442
0
    EndListening( rBindings );
443
444
0
    m_xEdCol.reset();
445
0
    m_xEdRow.reset();
446
0
    m_xTbxCmd1.reset();
447
0
    m_xTbxCmd2.reset();
448
0
    m_xDragModeMenu.reset();
449
0
    m_xLbEntries.reset();
450
0
    m_xWndScenarios.reset();
451
0
    m_xScenarioBox.reset();
452
0
    m_xLbDocuments.reset();
453
0
}
454
455
void ScNavigatorDlg::Notify( SfxBroadcaster&, const SfxHint& rHint )
456
0
{
457
0
    if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
458
0
    {
459
        // This is for when the document might change and the navigator
460
        // wants to update for the new document, which isn't a scenario
461
        // that happens in online.
462
0
        if (comphelper::LibreOfficeKit::isActive())
463
0
            return;
464
0
        const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(rHint);
465
0
        if (rEventHint.GetEventId() == SfxEventHintId::ActivateDoc)
466
0
        {
467
0
            UpdateSheetLimits();
468
0
            bool bRefreshed = m_xLbEntries->ActiveDocChanged();
469
            // UpdateAll just possibly calls Refresh (and always
470
            // ContentUpdated) so if ActiveDocChanged already called Refresh
471
            // skip re-calling it
472
0
            if (bRefreshed)
473
0
                ContentUpdated();
474
0
            else
475
0
                UpdateAll();
476
0
        }
477
0
    }
478
0
    else
479
0
    {
480
0
        const SfxHintId nHintId = rHint.GetId();
481
482
0
        if (nHintId == SfxHintId::ScDocNameChanged)
483
0
        {
484
0
            m_xLbEntries->ActiveDocChanged();
485
0
        }
486
0
        else if (NAV_LMODE_NONE == eListMode)
487
0
        {
488
            //  Table not any more
489
0
        }
490
0
        else
491
0
        {
492
0
            switch ( nHintId )
493
0
            {
494
0
                case SfxHintId::ScTablesChanged:
495
0
                    m_xLbEntries->Refresh( ScContentId::TABLE );
496
0
                    break;
497
498
0
                case SfxHintId::ScDbAreasChanged:
499
0
                    m_xLbEntries->Refresh( ScContentId::DBAREA );
500
0
                    break;
501
502
0
                case SfxHintId::ScAreasChanged:
503
0
                    m_xLbEntries->Refresh( ScContentId::RANGENAME );
504
0
                    break;
505
506
0
                case SfxHintId::ScDrawChanged:
507
0
                    m_xLbEntries->Refresh( ScContentId::GRAPHIC );
508
0
                    m_xLbEntries->Refresh( ScContentId::OLEOBJECT );
509
0
                    m_xLbEntries->Refresh( ScContentId::DRAWING );
510
0
                    aContentIdle.Start();      // Do not search notes immediately
511
0
                    break;
512
513
0
                case SfxHintId::ScAreaLinksChanged:
514
0
                    m_xLbEntries->Refresh( ScContentId::AREALINK );
515
0
                    break;
516
517
                //  SfxHintId::DocChanged not only at document change
518
519
0
                case SfxHintId::ScNavigatorUpdateAll:
520
0
                    UpdateAll();
521
0
                    break;
522
523
0
                case SfxHintId::ScDataChanged:
524
0
                case SfxHintId::ScAnyDataChanged:
525
0
                    aContentIdle.Start();      // Do not search notes immediately
526
0
                    break;
527
0
                case SfxHintId::ScSelectionChanged:
528
0
                    UpdateSelection();
529
0
                    break;
530
0
                default:
531
0
                    break;
532
0
            }
533
0
        }
534
0
    }
535
0
}
536
537
IMPL_LINK( ScNavigatorDlg, TimeHdl, Timer*, pIdle, void )
538
0
{
539
0
    if ( pIdle != &aContentIdle )
540
0
        return;
541
542
0
    m_xLbEntries->Refresh( ScContentId::NOTE );
543
0
}
544
545
void ScNavigatorDlg::SetDropMode(sal_uInt16 nNew)
546
0
{
547
0
    nDropMode = nNew;
548
0
    UpdateButtons();
549
0
    ScNavipiCfg& rCfg = ScModule::get()->GetNavipiCfg();
550
0
    rCfg.SetDragMode(nDropMode);
551
0
}
552
553
void ScNavigatorDlg::SetCurrentCell( SCCOL nColNo, SCROW nRowNo )
554
0
{
555
0
    if ((nColNo+1 == nCurCol) && (nRowNo+1 == nCurRow))
556
0
        return;
557
558
    // SID_CURRENTCELL == Item #0 clear cache, so it's possible
559
    // setting the current cell even in combined areas
560
0
    mvBoundItems[0]->ClearCache();
561
562
0
    ScAddress aScAddress( nColNo, nRowNo, 0 );
563
0
    OUString aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS));
564
565
0
    bool bUnmark = false;
566
0
    if (ScViewData* pData = GetViewData())
567
0
        bUnmark = !pData->GetMarkData().IsCellMarked( nColNo, nRowNo );
568
569
0
    SfxStringItem   aPosItem( SID_CURRENTCELL, aAddr );
570
0
    SfxBoolItem     aUnmarkItem( FN_PARAM_1, bUnmark );     // cancel selection
571
572
0
    rBindings.GetDispatcher()->ExecuteList(SID_CURRENTCELL,
573
0
                              SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
574
0
                              { &aPosItem, &aUnmarkItem });
575
0
}
576
577
void ScNavigatorDlg::SetCurrentCellStr( const OUString& rName )
578
0
{
579
0
    mvBoundItems[0]->ClearCache();
580
0
    SfxStringItem   aNameItem( SID_CURRENTCELL, rName );
581
582
0
    rBindings.GetDispatcher()->ExecuteList(SID_CURRENTCELL,
583
0
                              SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
584
0
                              { &aNameItem });
585
0
}
586
587
void ScNavigatorDlg::SetCurrentTable( SCTAB nTabNo )
588
0
{
589
0
    if ( nTabNo != nCurTab )
590
0
    {
591
        // Table for basic is base-1
592
0
        SfxUInt16Item aTabItem( SID_CURRENTTAB, static_cast<sal_uInt16>(nTabNo) + 1 );
593
0
        rBindings.GetDispatcher()->ExecuteList(SID_CURRENTTAB,
594
0
                                  SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
595
0
                                  { &aTabItem });
596
0
    }
597
0
}
598
599
void ScNavigatorDlg::SetCurrentTableStr( std::u16string_view rName )
600
0
{
601
0
    ScViewData* pData = GetViewData();
602
0
    if(!pData)
603
0
        return;
604
605
0
    ScDocument& rDoc = pData->GetDocument();
606
0
    SCTAB nCount = rDoc.GetTableCount();
607
0
    OUString aTabName;
608
0
    SCTAB nLastSheet = 0;
609
610
0
    for (SCTAB i = 0; i<nCount; i++)
611
0
    {
612
0
        rDoc.GetName(i, aTabName);
613
0
        if (aTabName == rName)
614
0
        {
615
            // Check if this is a Scenario sheet and if so select the sheet
616
            // where it belongs to, which is the previous non-Scenario sheet.
617
0
            if (rDoc.IsScenario(i))
618
0
            {
619
0
                SetCurrentTable(nLastSheet);
620
0
                return;
621
0
            }
622
0
            else
623
0
            {
624
0
                SetCurrentTable(i);
625
0
                return;
626
0
            }
627
0
        }
628
0
        else
629
0
        {
630
0
            if (!rDoc.IsScenario(i))
631
0
                nLastSheet = i;
632
0
        }
633
0
    }
634
0
}
635
636
void ScNavigatorDlg::SetCurrentObject( const OUString& rName )
637
0
{
638
0
    SfxStringItem aNameItem( SID_CURRENTOBJECT, rName );
639
0
    rBindings.GetDispatcher()->ExecuteList( SID_CURRENTOBJECT,
640
0
                              SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
641
0
                              { &aNameItem });
642
0
}
643
644
void ScNavigatorDlg::SetCurrentDoc( const OUString& rDocName )        // activate
645
0
{
646
0
    SfxStringItem aDocItem( SID_CURRENTDOC, rDocName );
647
0
    rBindings.GetDispatcher()->ExecuteList( SID_CURRENTDOC,
648
0
                              SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
649
0
                              { &aDocItem });
650
0
}
651
652
void ScNavigatorDlg::UpdateSelection()
653
0
{
654
0
    ScTabViewShell* pViewSh = GetTabViewShell();
655
0
    if( !pViewSh )
656
0
        return;
657
658
0
    uno::Reference< drawing::XShapes > xShapes = pViewSh->getSelectedXShapes();
659
0
    if( !xShapes )
660
0
        return;
661
662
0
    uno::Reference< container::XIndexAccess > xIndexAccess(
663
0
            xShapes, uno::UNO_QUERY_THROW );
664
0
    if( xIndexAccess->getCount() > 1 )
665
0
        return;
666
0
    uno::Reference< drawing::XShape > xShape;
667
0
    if( xIndexAccess->getByIndex(0) >>= xShape )
668
0
    {
669
0
        uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY_THROW );
670
0
        OUString sName = xNamed->getName();
671
0
        if (!sName.isEmpty())
672
0
        {
673
0
            m_xLbEntries->SelectEntryByName( ScContentId::DRAWING, sName );
674
0
        }
675
0
    }
676
0
}
677
678
ScTabViewShell* ScNavigatorDlg::GetTabViewShell()
679
0
{
680
0
    return dynamic_cast<ScTabViewShell*>( SfxViewShell::Current()  );
681
0
}
682
683
ScNavigatorSettings* ScNavigatorDlg::GetNavigatorSettings()
684
0
{
685
    //  Don't store the settings pointer here, because the settings belong to
686
    //  the view, and the view may be closed while the navigator is open (reload).
687
    //  If the pointer is cached here again later for performance reasons, it has to
688
    //  be forgotten when the view is closed.
689
690
0
    ScTabViewShell* pViewSh = GetTabViewShell();
691
0
    return pViewSh ? pViewSh->GetNavigatorSettings() : nullptr;
692
0
}
693
694
ScViewData* ScNavigatorDlg::GetViewData()
695
0
{
696
0
    ScTabViewShell* pViewSh = GetTabViewShell();
697
0
    return pViewSh ? &pViewSh->GetViewData() : nullptr;
698
0
}
699
700
void ScNavigatorDlg::UpdateColumn( const SCCOL* pCol )
701
0
{
702
0
    if ( pCol )
703
0
        nCurCol = *pCol;
704
0
    else if ( ScViewData* pData = GetViewData() )
705
0
        nCurCol = pData->GetCurX() + 1;
706
707
0
    m_xEdCol->set_value(nCurCol);
708
0
}
709
710
void ScNavigatorDlg::UpdateRow( const SCROW* pRow )
711
0
{
712
0
    if ( pRow )
713
0
        nCurRow = *pRow;
714
0
    else if ( ScViewData* pData = GetViewData() )
715
0
        nCurRow = pData->GetCurY() + 1;
716
717
0
    m_xEdRow->set_value(nCurRow);
718
0
}
719
720
void ScNavigatorDlg::UpdateTable( const SCTAB* pTab )
721
0
{
722
0
    if ( pTab )
723
0
        nCurTab = *pTab;
724
0
    else if ( ScViewData* pData = GetViewData() )
725
0
        nCurTab = pData->CurrentTabForData();
726
0
}
727
728
void ScNavigatorDlg::UpdateAll()
729
0
{
730
0
    switch (eListMode)
731
0
    {
732
0
        case NAV_LMODE_AREAS:
733
0
            m_xLbEntries->Refresh();
734
0
            break;
735
0
        case NAV_LMODE_NONE:
736
            //! ???
737
0
            break;
738
0
        default:
739
0
            break;
740
0
    }
741
0
    ContentUpdated();       // not again
742
0
}
743
744
void ScNavigatorDlg::ContentUpdated()
745
0
{
746
0
    aContentIdle.Stop();
747
0
}
748
749
void ScNavigatorDlg::SetListMode(NavListMode eMode)
750
0
{
751
0
    if (eMode != eListMode)
752
0
    {
753
0
        bool bForceParentResize = ParentIsFloatingWindow(m_xNavigatorDlg) &&
754
0
                                  (eMode == NAV_LMODE_NONE || eListMode == NAV_LMODE_NONE);
755
0
        SfxNavigator* pNav = bForceParentResize ? m_xNavigatorDlg.get() : nullptr;
756
0
        if (pNav && eMode == NAV_LMODE_NONE) //save last normal size on minimizing
757
0
            aExpandedSize = pNav->GetSizePixel();
758
759
0
        eListMode = eMode;
760
761
0
        switch (eMode)
762
0
        {
763
0
            case NAV_LMODE_NONE:
764
0
                ShowList(false);
765
0
                break;
766
0
            case NAV_LMODE_AREAS:
767
0
                m_xLbEntries->Refresh();
768
0
                ShowList(true);
769
0
                break;
770
0
            case NAV_LMODE_SCENARIOS:
771
0
                ShowScenarios();
772
0
                break;
773
0
        }
774
775
0
        UpdateButtons();
776
777
0
        if (eMode != NAV_LMODE_NONE)
778
0
        {
779
0
            ScNavipiCfg& rCfg = ScModule::get()->GetNavipiCfg();
780
0
            rCfg.SetListMode( static_cast<sal_uInt16>(eMode) );
781
0
        }
782
783
0
        if (pNav)
784
0
        {
785
0
            pNav->InvalidateChildSizeCache();
786
0
            Size aOptimalSize(pNav->GetOptimalSize());
787
0
            Size aNewSize(pNav->GetOutputSizePixel());
788
0
            aNewSize.setHeight( eMode == NAV_LMODE_NONE ? aOptimalSize.Height() : aExpandedSize.Height() );
789
0
            pNav->SetMinOutputSizePixel(aOptimalSize);
790
0
            pNav->SetOutputSizePixel(aNewSize);
791
0
        }
792
0
    }
793
794
0
    if (moMarkArea)
795
0
        UnmarkDataArea();
796
0
}
797
798
void ScNavigatorDlg::ShowList(bool bShow)
799
0
{
800
0
    if (bShow)
801
0
    {
802
0
        m_xLbEntries->show();
803
0
        m_xLbDocuments->show();
804
0
    }
805
0
    else
806
0
    {
807
0
        m_xLbEntries->hide();
808
0
        m_xLbDocuments->hide();
809
0
    }
810
0
    m_xScenarioBox->hide();
811
0
}
812
813
void ScNavigatorDlg::ShowScenarios()
814
0
{
815
0
    rBindings.Invalidate( SID_SELECT_SCENARIO );
816
0
    rBindings.Update( SID_SELECT_SCENARIO );
817
818
0
    m_xScenarioBox->show();
819
0
    m_xLbDocuments->show();
820
0
    m_xLbEntries->hide();
821
0
}
822
823
//      documents for Dropdown-Listbox
824
void ScNavigatorDlg::GetDocNames( const OUString* pManualSel )
825
0
{
826
0
    m_xLbDocuments->clear();
827
0
    m_xLbDocuments->freeze();
828
829
0
    ScDocShell* pCurrentSh = dynamic_cast<ScDocShell*>( SfxObjectShell::Current()  );
830
831
0
    OUString aSelEntry;
832
0
    SfxObjectShell* pSh = SfxObjectShell::GetFirst();
833
0
    while ( pSh )
834
0
    {
835
0
        if ( dynamic_cast<const ScDocShell*>( pSh) !=  nullptr )
836
0
        {
837
0
            OUString aName = pSh->GetTitle();
838
0
            OUString aEntry = aName;
839
0
            if (pSh == pCurrentSh)
840
0
                aEntry += aStrActive;
841
0
            else
842
0
                aEntry += aStrNotActive;
843
0
            m_xLbDocuments->append_text(aEntry);
844
845
0
            if ( pManualSel ? ( aName == *pManualSel )
846
0
                            : ( pSh == pCurrentSh ) )
847
0
                aSelEntry = aEntry;                     // complete entry for selection
848
0
        }
849
850
0
        pSh = SfxObjectShell::GetNext( *pSh );
851
0
    }
852
853
0
    m_xLbDocuments->append_text(aStrActiveWin);
854
855
0
    m_xLbDocuments->thaw();
856
857
0
    m_xLbDocuments->set_active_text(aSelEntry);
858
0
}
859
860
void ScNavigatorDlg::MarkDataArea()
861
0
{
862
0
    ScTabViewShell* pViewSh = GetTabViewShell();
863
864
0
    if ( !pViewSh )
865
0
        return;
866
867
0
    if ( !moMarkArea )
868
0
        moMarkArea.emplace();
869
870
0
    pViewSh->MarkDataArea();
871
0
    const ScRange& aMarkRange = pViewSh->GetViewData().GetMarkData().GetMarkArea();
872
0
    moMarkArea->nColStart = aMarkRange.aStart.Col();
873
0
    moMarkArea->nRowStart = aMarkRange.aStart.Row();
874
0
    moMarkArea->nColEnd = aMarkRange.aEnd.Col();
875
0
    moMarkArea->nRowEnd = aMarkRange.aEnd.Row();
876
0
    moMarkArea->nTab = aMarkRange.aStart.Tab();
877
0
}
878
879
void ScNavigatorDlg::UnmarkDataArea()
880
0
{
881
0
    ScTabViewShell* pViewSh = GetTabViewShell();
882
883
0
    if ( pViewSh )
884
0
    {
885
0
        pViewSh->Unmark();
886
0
        moMarkArea.reset();
887
0
    }
888
0
}
889
890
void ScNavigatorDlg::StartOfDataArea()
891
0
{
892
    //  pMarkArea evaluate ???
893
894
0
    if (ScViewData* pData = GetViewData())
895
0
    {
896
0
        ScMarkData& rMark = pData->GetMarkData();
897
0
        const ScRange& aMarkRange = rMark.GetMarkArea();
898
899
0
        SCCOL nCol = aMarkRange.aStart.Col();
900
0
        SCROW nRow = aMarkRange.aStart.Row();
901
902
0
        if ( (nCol+1 != m_xEdCol->get_value()) || (nRow+1 != m_xEdRow->get_value()) )
903
0
            SetCurrentCell( nCol, nRow );
904
0
    }
905
0
}
906
907
void ScNavigatorDlg::EndOfDataArea()
908
0
{
909
    //  pMarkArea evaluate ???
910
911
0
    if (ScViewData* pData = GetViewData())
912
0
    {
913
0
        ScMarkData& rMark = pData->GetMarkData();
914
0
        const ScRange& aMarkRange = rMark.GetMarkArea();
915
916
0
        SCCOL nCol = aMarkRange.aEnd.Col();
917
0
        SCROW nRow = aMarkRange.aEnd.Row();
918
919
0
        if ( (nCol+1 != m_xEdCol->get_value()) || (nRow+1 != m_xEdRow->get_value()) )
920
0
            SetCurrentCell( nCol, nRow );
921
0
    }
922
0
}
923
924
SFX_IMPL_DOCKINGWINDOW(ScNavigatorWrapper, SID_NAVIGATOR);
925
926
ScNavigatorWrapper::ScNavigatorWrapper(vcl::Window *_pParent, sal_uInt16 nId,
927
                                       SfxBindings* pBindings, SfxChildWinInfo* pInfo)
928
0
    : SfxNavigatorWrapper(_pParent, nId)
929
0
{
930
0
    SetWindow(VclPtr<ScNavigatorWin>::Create(pBindings, this, _pParent, pInfo));
931
0
    Initialize();
932
0
}
933
934
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */