Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/miscdlgs/crnrdlg.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 <reffact.hxx>
21
#include <document.hxx>
22
#include <globstr.hrc>
23
#include <scresid.hxx>
24
#include <docsh.hxx>
25
#include <crnrdlg.hxx>
26
#include <vcl/svapp.hxx>
27
#include <vcl/weld/Dialog.hxx>
28
#include <vcl/weld/MessageDialog.hxx>
29
#include <o3tl/string_view.hxx>
30
#include <memory>
31
32
namespace
33
{
34
    void ERRORBOX(weld::Window* pParent, const OUString& rString)
35
0
    {
36
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
37
0
                                                  VclMessageType::Warning, VclButtonsType::Ok,
38
0
                                                  rString));
39
0
        xBox->run();
40
0
    }
41
42
    int QUERYBOX(weld::Window* pParent, const OUString& rString)
43
0
    {
44
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
45
0
                                                  VclMessageType::Question, VclButtonsType::YesNo,
46
0
                                                  rString));
47
0
        xBox->set_default_response(RET_YES);
48
0
        return xBox->run();
49
0
    }
50
51
}
52
53
const sal_uLong nEntryDataCol = 0;
54
const sal_uLong nEntryDataRow = 1;
55
const sal_uLong nEntryDataDelim = 2;
56
57
58
// note: some of the initialisation is done in Init
59
ScColRowNameRangesDlg::ScColRowNameRangesDlg( SfxBindings* pB,
60
                                SfxChildWindow* pCW,
61
                                weld::Window* pParent,
62
                                ScViewData& rViewData )
63
64
0
    : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/namerangesdialog.ui"_ustr, u"NameRangesDialog"_ustr)
65
0
    , m_rViewData(rViewData)
66
0
    , rDoc(rViewData.GetDocument())
67
0
    , bDlgLostFocus(false)
68
0
    , m_pEdActive(nullptr)
69
0
    , m_xLbRange(m_xBuilder->weld_tree_view(u"range"_ustr))
70
0
    , m_xEdAssign(new formula::RefEdit(m_xBuilder->weld_entry(u"edassign"_ustr)))
71
0
    , m_xRbAssign(new formula::RefButton(m_xBuilder->weld_button(u"rbassign"_ustr)))
72
0
    , m_xBtnColHead(m_xBuilder->weld_radio_button(u"colhead"_ustr))
73
0
    , m_xBtnRowHead(m_xBuilder->weld_radio_button(u"rowhead"_ustr))
74
0
    , m_xEdAssign2(new formula::RefEdit(m_xBuilder->weld_entry(u"edassign2"_ustr)))
75
0
    , m_xRbAssign2(new formula::RefButton(m_xBuilder->weld_button(u"rbassign2"_ustr)))
76
0
    , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
77
0
    , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
78
0
    , m_xBtnAdd(m_xBuilder->weld_button(u"add"_ustr))
79
0
    , m_xBtnRemove(m_xBuilder->weld_button(u"delete"_ustr))
80
0
    , m_xRangeFrame(m_xBuilder->weld_frame(u"rangeframe"_ustr))
81
0
    , m_xDataFT(m_xBuilder->weld_label(u"datarange"_ustr))
82
0
{
83
0
    m_xRbAssign->SetReferences(this, m_xEdAssign.get());
84
0
    m_xEdAssign->SetReferences(this, m_xRangeFrame.get());
85
0
    m_xRbAssign2->SetReferences(this, m_xEdAssign2.get());
86
0
    m_xEdAssign2->SetReferences(this, m_xDataFT.get());
87
88
0
    xColNameRanges = rDoc.GetColNameRanges()->Clone();
89
0
    xRowNameRanges = rDoc.GetRowNameRanges()->Clone();
90
0
    Init();
91
0
}
92
93
ScColRowNameRangesDlg::~ScColRowNameRangesDlg()
94
0
{
95
0
}
96
97
// initialises event handlers and start parameters in the dialog
98
void ScColRowNameRangesDlg::Init()
99
0
{
100
0
    m_xBtnOk->connect_clicked      ( LINK( this, ScColRowNameRangesDlg, OkBtnHdl ) );
101
0
    m_xBtnCancel->connect_clicked  ( LINK( this, ScColRowNameRangesDlg, CancelBtnHdl ) );
102
0
    m_xBtnAdd->connect_clicked     ( LINK( this, ScColRowNameRangesDlg, AddBtnHdl ) );
103
0
    m_xBtnRemove->connect_clicked  ( LINK( this, ScColRowNameRangesDlg, RemoveBtnHdl ) );
104
0
    m_xLbRange->connect_selection_changed(LINK(this, ScColRowNameRangesDlg, Range1SelectHdl));
105
0
    m_xEdAssign->SetModifyHdl  ( LINK( this, ScColRowNameRangesDlg, Range1DataModifyHdl ) );
106
0
    m_xBtnColHead->connect_toggled ( LINK( this, ScColRowNameRangesDlg, ColRowToggleHdl ) );
107
0
    m_xEdAssign2->SetModifyHdl ( LINK( this, ScColRowNameRangesDlg, Range2DataModifyHdl ) );
108
109
0
    Link<formula::RefEdit&,void> aEditLink = LINK( this, ScColRowNameRangesDlg, GetEditFocusHdl );
110
0
    m_xEdAssign->SetGetFocusHdl( aEditLink );
111
0
    m_xEdAssign2->SetGetFocusHdl( aEditLink );
112
113
0
    Link<formula::RefButton&,void> aButtonLink = LINK( this, ScColRowNameRangesDlg, GetButtonFocusHdl );
114
0
    m_xRbAssign->SetGetFocusHdl( aButtonLink );
115
0
    m_xRbAssign2->SetGetFocusHdl( aButtonLink );
116
117
0
    aEditLink = LINK( this, ScColRowNameRangesDlg, LoseEditFocusHdl );
118
0
    m_xEdAssign->SetLoseFocusHdl( aEditLink );
119
0
    m_xEdAssign2->SetLoseFocusHdl( aEditLink );
120
121
0
    aButtonLink = LINK( this, ScColRowNameRangesDlg, LoseButtonFocusHdl );
122
0
    m_xRbAssign2->SetLoseFocusHdl( aButtonLink );
123
0
    m_xRbAssign->SetLoseFocusHdl( aButtonLink );
124
125
0
    m_pEdActive = m_xEdAssign.get();
126
127
0
    UpdateNames();
128
129
0
    SCCOL nStartCol = 0;
130
0
    SCROW nStartRow = 0;
131
0
    SCTAB nStartTab = 0;
132
0
    SCCOL nEndCol   = 0;
133
0
    SCROW nEndRow   = 0;
134
0
    SCTAB nEndTab   = 0;
135
0
    m_rViewData.GetSimpleArea(nStartCol, nStartRow, nStartTab,
136
0
                              nEndCol,   nEndRow,  nEndTab );
137
0
    SetColRowData( ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab));
138
139
0
    m_xBtnColHead->set_sensitive(true);
140
0
    m_xBtnRowHead->set_sensitive(true);
141
0
    m_xEdAssign->GetWidget()->set_sensitive(true);
142
0
    m_xEdAssign->GrabFocus();
143
0
    m_xRbAssign->GetWidget()->set_sensitive(true);
144
145
0
    Range1SelectHdl( *m_xLbRange );
146
0
}
147
148
// set data range of a labeled range to default values and set the
149
// form elements for the reference
150
void ScColRowNameRangesDlg::SetColRowData( const ScRange& rLabelRange, bool bRef)
151
0
{
152
0
    theCurData = theCurArea = rLabelRange;
153
0
    bool bValid = true;
154
0
    SCCOL nCol1 = theCurArea.aStart.Col();
155
0
    SCCOL nCol2 = theCurArea.aEnd.Col();
156
0
    SCROW nRow1 = theCurArea.aStart.Row();
157
0
    SCROW nRow2 = theCurArea.aEnd.Row();
158
0
    if ( (static_cast<SCCOLROW>(nCol2 - nCol1) >= nRow2 - nRow1) || (nCol1 == 0 && nCol2 == rDoc.MaxCol()) )
159
0
    {   // Column headers and the limiting case of the whole sheet
160
0
        m_xBtnColHead->set_active(true);
161
0
        m_xBtnRowHead->set_active(false);
162
0
        if ( nRow2 == rDoc.MaxRow()  )
163
0
        {
164
0
            if ( nRow1 == 0 )
165
0
                bValid = false;     // limiting case of the whole sheet
166
0
            else
167
0
            {   // Header at bottom, data above
168
0
                theCurData.aStart.SetRow( 0 );
169
0
                theCurData.aEnd.SetRow( nRow1 - 1 );
170
0
            }
171
0
        }
172
0
        else
173
0
        {   // Header at top, data below
174
0
            theCurData.aStart.SetRow( nRow2 + 1 );
175
0
            theCurData.aEnd.SetRow( rDoc.MaxRow() );
176
0
        }
177
0
    }
178
0
    else
179
0
    {   // Column headers
180
0
        m_xBtnRowHead->set_active(true);
181
0
        m_xBtnColHead->set_active(false);
182
0
        if ( nCol2 == rDoc.MaxCol() )
183
0
        {   // Header at the right, data to the left
184
0
            theCurData.aStart.SetCol( 0 );
185
0
            theCurData.aEnd.SetCol( nCol2 - 1 );
186
0
        }
187
0
        else
188
0
        {   // Header at the left, data to the right
189
0
            theCurData.aStart.SetCol( nCol2 + 1 );
190
0
            theCurData.aEnd.SetCol( rDoc.MaxCol() );
191
0
        }
192
0
    }
193
0
    if ( bValid )
194
0
    {
195
0
        const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
196
0
        OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv));
197
198
0
        if(bRef)
199
0
            m_xEdAssign->SetRefString( aStr );
200
0
        else
201
0
            m_xEdAssign->SetText( aStr );
202
203
0
        m_xEdAssign->SetCursorAtLast();
204
0
        aStr = theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);
205
206
0
        if(bRef)
207
0
            m_xEdAssign2->SetRefString( aStr );
208
0
        else
209
0
            m_xEdAssign2->SetText( aStr );
210
0
    }
211
0
    else
212
0
    {
213
0
        theCurData = theCurArea = ScRange();
214
215
0
        if(bRef)
216
0
        {
217
0
            m_xEdAssign->SetRefString( OUString() );
218
0
            m_xEdAssign2->SetRefString( OUString() );
219
0
        }
220
0
        else
221
0
        {
222
0
            m_xEdAssign->SetText( OUString() );
223
0
            m_xEdAssign2->SetText( OUString() );
224
0
        }
225
226
0
        m_xBtnColHead->set_sensitive(false);
227
0
        m_xBtnRowHead->set_sensitive(false);
228
0
        m_xEdAssign2->GetWidget()->set_sensitive(false);
229
0
        m_xRbAssign2->GetWidget()->set_sensitive(false);
230
0
    }
231
0
}
232
233
// adjust label range and set the data reference form element
234
void ScColRowNameRangesDlg::AdjustColRowData( const ScRange& rDataRange, bool bRef)
235
0
{
236
0
    theCurData = rDataRange;
237
0
    if ( m_xBtnColHead->get_active() )
238
0
    {   // Data range is the same columns as the header
239
0
        theCurData.aStart.SetCol( theCurArea.aStart.Col() );
240
0
        theCurData.aEnd.SetCol( theCurArea.aEnd.Col() );
241
0
        if ( theCurData.Intersects( theCurArea ) )
242
0
        {
243
0
            SCROW nRow1 = theCurArea.aStart.Row();
244
0
            SCROW nRow2 = theCurArea.aEnd.Row();
245
0
            if ( nRow1 > 0
246
0
              && (theCurData.aEnd.Row() < nRow2 || nRow2 == rDoc.MaxRow()) )
247
0
            {   // Data above header
248
0
                theCurData.aEnd.SetRow( nRow1 - 1 );
249
0
                if ( theCurData.aStart.Row() > theCurData.aEnd.Row() )
250
0
                    theCurData.aStart.SetRow( theCurData.aEnd.Row() );
251
0
            }
252
0
            else
253
0
            {   // Data below header
254
0
                theCurData.aStart.SetRow( nRow2 + 1 );
255
0
                if ( theCurData.aStart.Row() > theCurData.aEnd.Row() )
256
0
                    theCurData.aEnd.SetRow( theCurData.aStart.Row() );
257
0
            }
258
0
        }
259
0
    }
260
0
    else
261
0
    {   // Data range in the same rows as header
262
0
        theCurData.aStart.SetRow( theCurArea.aStart.Row() );
263
0
        theCurData.aEnd.SetRow( theCurArea.aEnd.Row() );
264
0
        if ( theCurData.Intersects( theCurArea ) )
265
0
        {
266
0
            SCCOL nCol1 = theCurArea.aStart.Col();
267
0
            SCCOL nCol2 = theCurArea.aEnd.Col();
268
0
            if ( nCol1 > 0
269
0
              && (theCurData.aEnd.Col() < nCol2 || nCol2 == rDoc.MaxCol()) )
270
0
            {   // Data left of header
271
0
                theCurData.aEnd.SetCol( nCol1 - 1 );
272
0
                if ( theCurData.aStart.Col() > theCurData.aEnd.Col() )
273
0
                    theCurData.aStart.SetCol( theCurData.aEnd.Col() );
274
0
            }
275
0
            else
276
0
            {   // Data right of header
277
0
                theCurData.aStart.SetCol( nCol2 + 1 );
278
0
                if ( theCurData.aStart.Col() > theCurData.aEnd.Col() )
279
0
                    theCurData.aEnd.SetCol( theCurData.aStart.Col() );
280
0
            }
281
0
        }
282
0
    }
283
0
    OUString aStr(theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
284
285
0
    if(bRef)
286
0
        m_xEdAssign2->SetRefString( aStr );
287
0
    else
288
0
        m_xEdAssign2->SetText( aStr );
289
290
0
    m_xEdAssign2->SetCursorAtLast();
291
0
}
292
293
// Set the reference to a cell range selected with the mouse and update
294
// the selection form element
295
void ScColRowNameRangesDlg::SetReference( const ScRange& rRef, ScDocument& /* rDoc */ )
296
0
{
297
0
    if ( !m_pEdActive )
298
0
        return;
299
300
0
    if ( rRef.aStart != rRef.aEnd )
301
0
        RefInputStart( m_pEdActive );
302
303
0
    if (m_pEdActive == m_xEdAssign.get())
304
0
        SetColRowData( rRef, true );
305
0
    else
306
0
        AdjustColRowData( rRef, true );
307
0
    m_xBtnColHead->set_sensitive(true);
308
0
    m_xBtnRowHead->set_sensitive(true);
309
0
    m_xBtnAdd->set_sensitive(true);
310
0
    m_xBtnRemove->set_sensitive(false);
311
0
}
312
313
void ScColRowNameRangesDlg::Close()
314
0
{
315
0
    DoClose( ScColRowNameRangesDlgWrapper::GetChildWindowId() );
316
0
}
317
318
void ScColRowNameRangesDlg::SetActive()
319
0
{
320
0
    if ( bDlgLostFocus )
321
0
    {
322
0
        bDlgLostFocus = false;
323
0
        if( m_pEdActive )
324
0
            m_pEdActive->GrabFocus();
325
0
    }
326
0
    else
327
0
        m_xDialog->grab_focus();
328
329
0
    if( m_pEdActive == m_xEdAssign.get() )
330
0
        Range1DataModifyHdl( *m_xEdAssign );
331
0
    else if( m_pEdActive == m_xEdAssign2.get() )
332
0
        Range2DataModifyHdl( *m_xEdAssign2 );
333
334
0
    RefInputDone();
335
0
}
336
337
void ScColRowNameRangesDlg::UpdateNames()
338
0
{
339
0
    m_xLbRange->freeze();
340
341
0
    m_xLbRange->clear();
342
0
    aRangeMap.clear();
343
0
    m_xEdAssign->SetText( OUString() );
344
345
0
    size_t nCount, j;
346
347
0
    SCCOL nCol1;
348
0
    SCROW nRow1;    //Extension for range names
349
0
    SCTAB nTab1;
350
0
    SCCOL nCol2;
351
0
    SCROW nRow2;
352
0
    SCTAB nTab2;
353
0
    OUString rString;
354
0
    const ScAddress::Details aDetails(rDoc.GetAddressConvention());
355
356
0
    OUString strDelim(u" --- "_ustr);
357
0
    OUString aString = strDelim + ScResId( STR_COLUMN ) + strDelim;
358
0
    m_xLbRange->append(OUString::number(nEntryDataDelim), aString);
359
0
    if ( xColNameRanges->size() > 0 )
360
0
    {
361
0
        std::vector<const ScRangePair*> aSortArray(xColNameRanges->CreateNameSortedArray(
362
0
               rDoc ));
363
0
        nCount = aSortArray.size();
364
0
        for ( j=0; j < nCount; j++ )
365
0
        {
366
0
            const ScRange aRange(aSortArray[j]->GetRange(0));
367
0
            aString = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aDetails);
368
369
            //@008 get range parameters from document
370
0
            aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1,
371
0
                                            nCol2, nRow2, nTab2 );
372
0
            SCCOL q=nCol1+3;
373
0
            if(q>nCol2) q=nCol2;
374
            //@008 construct string
375
0
            OUStringBuffer strShow = " [";
376
0
            rString = rDoc.GetString(nCol1, nRow1, nTab1);
377
0
            strShow.append(rString);
378
0
            for(SCCOL i=nCol1+1;i<=q;i++)
379
0
            {
380
0
                strShow.append(", ");
381
0
                rString = rDoc.GetString(i, nRow1, nTab1);
382
0
                strShow.append(rString);
383
0
            }
384
0
            if(q<nCol2) // Too long? Add ",..."
385
0
            {
386
0
                strShow.append(", ...");
387
0
            }
388
0
            strShow.append("]");
389
390
            //@008 Add string to listbox
391
0
            OUString aInsStr = aString + strShow;
392
0
            aRangeMap.emplace( aInsStr, aRange );
393
0
            m_xLbRange->append(OUString::number(nEntryDataCol), aInsStr);
394
0
        }
395
0
    }
396
0
    aString = strDelim + ScResId( STR_ROW ) + strDelim;
397
0
    m_xLbRange->append(OUString::number(nEntryDataDelim), aString);
398
0
    if ( xRowNameRanges->size() > 0 )
399
0
    {
400
0
        std::vector<const ScRangePair*> aSortArray(xRowNameRanges->CreateNameSortedArray(
401
0
               rDoc ));
402
0
        nCount = aSortArray.size();
403
0
        for ( j=0; j < nCount; j++ )
404
0
        {
405
0
            const ScRange aRange(aSortArray[j]->GetRange(0));
406
0
            aString = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, aDetails);
407
408
            //@008 Build string for rows below
409
0
            aSortArray[j]->GetRange(0).GetVars( nCol1, nRow1, nTab1,
410
0
                                            nCol2, nRow2, nTab2 );
411
0
            SCROW q=nRow1+3;
412
0
            if(q>nRow2) q=nRow2;
413
0
            OUStringBuffer strShow = " [";
414
0
            rString = rDoc.GetString(nCol1, nRow1, nTab1);
415
0
            strShow.append(rString);
416
0
            for(SCROW i=nRow1+1;i<=q;i++)
417
0
            {
418
0
                strShow.append(", ");
419
0
                rString = rDoc.GetString(nCol1, i, nTab1);
420
0
                strShow.append(rString);
421
0
            }
422
0
            if(q<nRow2)
423
0
            {
424
0
                strShow.append(", ...");
425
0
            }
426
0
            strShow.append("]");
427
428
0
            OUString aInsStr = aString + strShow;
429
0
            aRangeMap.emplace( aInsStr, aRange );
430
0
            m_xLbRange->append(OUString::number(nEntryDataRow), aInsStr);
431
0
        }
432
0
    }
433
434
0
    m_xLbRange->thaw();
435
0
}
436
437
void ScColRowNameRangesDlg::UpdateRangeData( const ScRange& rRange, bool bColName )
438
0
{
439
0
    ScRangePair* pPair = nullptr;
440
0
    bool bFound = false;
441
0
    if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr )
442
0
        bFound = true;
443
0
    else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr )
444
0
        bFound = true;
445
446
0
    if ( bFound )
447
0
    {
448
0
        const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
449
0
        theCurArea = rRange;
450
0
        OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv));
451
0
        m_xEdAssign->SetText( aStr );
452
0
        m_xBtnAdd->set_sensitive(false);
453
0
        m_xBtnRemove->set_sensitive(true);
454
0
        m_xBtnColHead->set_active(bColName);
455
0
        m_xBtnRowHead->set_active(!bColName);
456
0
        theCurData = pPair->GetRange(1);
457
0
        aStr = theCurData.Format(rDoc, ScRefFlags::RANGE_ABS_3D, eConv);
458
0
        m_xEdAssign2->SetText( aStr );
459
0
    }
460
0
    else
461
0
    {
462
0
        m_xBtnAdd->set_sensitive(true);
463
0
        m_xBtnRemove->set_sensitive(false);
464
0
    }
465
0
    m_xBtnColHead->set_sensitive(true);
466
0
    m_xBtnRowHead->set_sensitive(true);
467
0
    m_xEdAssign2->GetWidget()->set_sensitive(true);
468
0
    m_xRbAssign2->GetWidget()->set_sensitive(true);
469
0
}
470
471
bool ScColRowNameRangesDlg::IsRefInputMode() const
472
0
{
473
0
    return (m_pEdActive != nullptr);
474
0
}
475
476
// Handler:
477
478
// handler called when OK is clicked, calls the add button handler before
479
// passing the range lists to the document
480
IMPL_LINK_NOARG(ScColRowNameRangesDlg, OkBtnHdl, weld::Button&, void)
481
0
{
482
0
    AddBtnHdl(*m_xBtnAdd);
483
484
    // assign RangeLists to the references in the document
485
0
    rDoc.GetColNameRangesRef() = xColNameRanges;
486
0
    rDoc.GetRowNameRangesRef() = xRowNameRanges;
487
    // changed ranges need to take effect
488
0
    rDoc.CompileColRowNameFormula();
489
0
    ScDocShell* pDocShell = m_rViewData.GetDocShell();
490
0
    pDocShell->PostPaint(ScRange(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB), PaintPartFlags::Grid);
491
0
    pDocShell->SetDocumentModified();
492
493
0
    response(RET_OK);
494
0
}
495
496
IMPL_LINK_NOARG(ScColRowNameRangesDlg, CancelBtnHdl, weld::Button&, void)
497
0
{
498
0
    response(RET_CANCEL);
499
0
}
500
501
// handler called when add button clicked: set ranges and add to listbox
502
IMPL_LINK_NOARG(ScColRowNameRangesDlg, AddBtnHdl, weld::Button&, void)
503
0
{
504
0
    OUString aNewArea( m_xEdAssign->GetText() );
505
0
    OUString aNewData( m_xEdAssign2->GetText() );
506
507
0
    if (aNewArea.isEmpty() || aNewData.isEmpty())
508
0
        return;
509
510
0
    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
511
0
    ScRange aRange1, aRange2;
512
0
    bool bOk1 = (aRange1.ParseAny( aNewArea, rDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID;
513
0
    if ( bOk1 && (aRange2.ParseAny( aNewData, rDoc, eConv ) & ScRefFlags::VALID) == ScRefFlags::VALID)
514
0
    {
515
0
        theCurArea = aRange1;
516
0
        AdjustColRowData( aRange2 );
517
0
        ScRangePair* pPair;
518
0
        if ( ( pPair = xColNameRanges->Find( theCurArea ) ) != nullptr )
519
0
        {
520
0
            xColNameRanges->Remove( *pPair );
521
0
        }
522
0
        if ( ( pPair = xRowNameRanges->Find( theCurArea ) ) != nullptr )
523
0
        {
524
0
            xRowNameRanges->Remove( *pPair );
525
0
        }
526
0
        if ( m_xBtnColHead->get_active() )
527
0
            xColNameRanges->Join( ScRangePair( theCurArea, theCurData ) );
528
0
        else
529
0
            xRowNameRanges->Join( ScRangePair( theCurArea, theCurData ) );
530
531
0
        UpdateNames();
532
533
0
        m_xEdAssign->GrabFocus();
534
0
        m_xBtnAdd->set_sensitive(false);
535
0
        m_xBtnRemove->set_sensitive(false);
536
0
        m_xEdAssign->SetText( OUString() );
537
0
        m_xBtnColHead->set_active(true);
538
0
        m_xBtnRowHead->set_active(false);
539
0
        m_xEdAssign2->SetText( OUString() );
540
0
        theCurArea = ScRange();
541
0
        theCurData = theCurArea;
542
0
        Range1SelectHdl( *m_xLbRange );
543
0
    }
544
0
    else
545
0
    {
546
0
        ERRORBOX(m_xDialog.get(), ScResId(STR_INVALIDTABNAME));
547
0
        if ( !bOk1 )
548
0
            m_xEdAssign->GrabFocus();
549
0
        else
550
0
            m_xEdAssign2->GrabFocus();
551
0
    }
552
0
}
553
554
IMPL_LINK_NOARG(ScColRowNameRangesDlg, RemoveBtnHdl, weld::Button&, void)
555
0
{
556
0
    OUString aRangeStr = m_xLbRange->get_selected_text();
557
0
    sal_Int32 nSelectPos = m_xLbRange->get_selected_index();
558
0
    bool bColName = nSelectPos != -1 && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol;
559
0
    NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr);
560
0
    if (itr == aRangeMap.end())
561
0
        return;
562
0
    const ScRange& rRange = itr->second;
563
564
0
    ScRangePair* pPair = nullptr;
565
0
    bool bFound = false;
566
0
    if ( bColName && (pPair = xColNameRanges->Find( rRange )) != nullptr )
567
0
        bFound = true;
568
0
    else if ( !bColName && (pPair = xRowNameRanges->Find( rRange )) != nullptr )
569
0
        bFound = true;
570
0
    if ( !bFound )
571
0
        return;
572
573
0
    OUString aStrDelMsg = ScResId( STR_QUERY_DELENTRY );
574
0
    OUString aMsg       = o3tl::getToken(aStrDelMsg, 0, '#' )
575
0
                        + aRangeStr
576
0
                        + o3tl::getToken(aStrDelMsg, 1, '#' );
577
578
0
    if (RET_YES != QUERYBOX(m_xDialog.get(), aMsg))
579
0
        return;
580
581
0
    if ( bColName )
582
0
        xColNameRanges->Remove( *pPair );
583
0
    else
584
0
        xRowNameRanges->Remove( *pPair );
585
586
0
    UpdateNames();
587
0
    const sal_Int32 nCnt = m_xLbRange->n_children();
588
0
    if ( nSelectPos >= nCnt )
589
0
    {
590
0
        if ( nCnt )
591
0
            nSelectPos = nCnt - 1;
592
0
        else
593
0
            nSelectPos = 0;
594
0
    }
595
0
    m_xLbRange->select(nSelectPos);
596
0
    if (nSelectPos && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim)
597
0
        m_xLbRange->select( --nSelectPos );    // ---Row---
598
599
0
    m_xLbRange->grab_focus();
600
0
    m_xBtnAdd->set_sensitive(false);
601
0
    m_xBtnRemove->set_sensitive(false);
602
0
    m_xEdAssign->SetText( OUString() );
603
0
    theCurArea = theCurData = ScRange();
604
0
    m_xBtnColHead->set_active(true);
605
0
    m_xBtnRowHead->set_active(false);
606
0
    m_xEdAssign2->SetText( OUString() );
607
0
    Range1SelectHdl( *m_xLbRange );
608
0
}
609
610
// handler called when a row in the listbox is selected, updates form input fields
611
IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1SelectHdl, weld::ItemView&, void)
612
0
{
613
0
    sal_Int32 nSelectPos = m_xLbRange->get_selected_index();
614
0
    const sal_Int32 nCnt = m_xLbRange->n_children();
615
0
    sal_uInt16 nMoves = 0;
616
0
    while (nSelectPos != -1 && nSelectPos < nCnt && m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataDelim)
617
0
    {   // skip Delimiter
618
0
        ++nMoves;
619
0
        ++nSelectPos;
620
0
    }
621
0
    OUString aRangeStr = m_xLbRange->get_selected_text();
622
0
    if ( nMoves )
623
0
    {
624
0
        if ( nSelectPos > 1 && nSelectPos >= nCnt )
625
0
        {   // if entries exist before the " --- Row --- " Delimiter then
626
            // do not stop at the delimiter
627
0
            nSelectPos = nCnt - 2;
628
0
            m_xLbRange->select(nSelectPos);
629
0
            aRangeStr = m_xLbRange->get_selected_text();
630
0
        }
631
0
        else if ( nSelectPos > 2 && nSelectPos < nCnt && !aRangeStr.isEmpty()
632
0
                  && aRangeStr == m_xEdAssign->GetText() )
633
0
        {   // move upwards instead of below to the previous position
634
0
            nSelectPos -= 2;
635
0
            m_xLbRange->select( nSelectPos );
636
0
            aRangeStr = m_xLbRange->get_selected_text();
637
0
        }
638
0
        else
639
0
            m_xLbRange->select(nSelectPos);
640
0
    }
641
0
    NameRangeMap::const_iterator itr = aRangeMap.find(aRangeStr);
642
0
    if ( itr != aRangeMap.end() )
643
0
    {
644
0
        bool bColName = m_xLbRange->get_id(nSelectPos).toInt32() == nEntryDataCol;
645
0
        UpdateRangeData( itr->second, bColName );
646
0
        m_xBtnAdd->set_sensitive(false);
647
0
        m_xBtnRemove->set_sensitive(true);
648
0
    }
649
0
    else
650
0
    {
651
0
        if ( !m_xEdAssign->GetText().isEmpty() )
652
0
        {
653
0
            if ( !m_xEdAssign2->GetText().isEmpty() )
654
0
                m_xBtnAdd->set_sensitive(true);
655
0
            else
656
0
                m_xBtnAdd->set_sensitive(false);
657
0
            m_xBtnColHead->set_sensitive(true);
658
0
            m_xBtnRowHead->set_sensitive(true);
659
0
            m_xEdAssign2->GetWidget()->set_sensitive(true);
660
0
            m_xRbAssign2->GetWidget()->set_sensitive(true);
661
0
        }
662
0
        else
663
0
        {
664
0
            m_xBtnAdd->set_sensitive(false);
665
0
            m_xBtnColHead->set_sensitive(false);
666
0
            m_xBtnRowHead->set_sensitive(false);
667
0
            m_xEdAssign2->GetWidget()->set_sensitive(false);
668
0
            m_xRbAssign2->GetWidget()->set_sensitive(false);
669
0
        }
670
0
        m_xBtnRemove->set_sensitive(false);
671
0
        m_xEdAssign->GrabFocus();
672
0
    }
673
674
0
    m_xEdAssign->GetWidget()->set_sensitive(true);
675
0
    m_xRbAssign->GetWidget()->set_sensitive(true);
676
0
}
677
678
// handler called when the label range has changed
679
IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range1DataModifyHdl, formula::RefEdit&, void)
680
0
{
681
0
    OUString aNewArea( m_xEdAssign->GetText() );
682
0
    bool bValid = false;
683
0
    if (!aNewArea.isEmpty())
684
0
    {
685
0
        ScRange aRange;
686
0
        if ( (aRange.ParseAny(aNewArea, rDoc, rDoc.GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID)
687
0
        {
688
0
            SetColRowData( aRange );
689
0
            bValid = true;
690
0
        }
691
0
    }
692
0
    if ( bValid )
693
0
    {
694
0
        m_xBtnAdd->set_sensitive(true);
695
0
        m_xBtnColHead->set_sensitive(true);
696
0
        m_xBtnRowHead->set_sensitive(true);
697
0
        m_xEdAssign2->GetWidget()->set_sensitive(true);
698
0
        m_xRbAssign2->GetWidget()->set_sensitive(true);
699
0
    }
700
0
    else
701
0
    {
702
0
        m_xBtnAdd->set_sensitive(false);
703
0
        m_xBtnColHead->set_sensitive(false);
704
0
        m_xBtnRowHead->set_sensitive(false);
705
0
        m_xEdAssign2->GetWidget()->set_sensitive(false);
706
0
        m_xRbAssign2->GetWidget()->set_sensitive(false);
707
0
    }
708
0
    m_xBtnRemove->set_sensitive(false);
709
0
}
710
711
// handler called when the data range has changed
712
IMPL_LINK_NOARG(ScColRowNameRangesDlg, Range2DataModifyHdl, formula::RefEdit&, void)
713
0
{
714
0
    OUString aNewData( m_xEdAssign2->GetText() );
715
0
    if ( !aNewData.isEmpty() )
716
0
    {
717
0
        ScRange aRange;
718
0
        if ( (aRange.ParseAny(aNewData, rDoc, rDoc.GetAddressConvention() ) & ScRefFlags::VALID) == ScRefFlags::VALID)
719
0
        {
720
0
            AdjustColRowData( aRange );
721
0
            m_xBtnAdd->set_sensitive(true);
722
0
        }
723
0
        else
724
0
            m_xBtnAdd->set_sensitive(false);
725
0
    }
726
0
    else
727
0
    {
728
0
        m_xBtnAdd->set_sensitive(false);
729
0
    }
730
0
}
731
732
IMPL_LINK_NOARG(ScColRowNameRangesDlg, ColRowToggleHdl, weld::Toggleable&, void)
733
0
{
734
0
    if (m_xBtnColHead->get_active())
735
0
    {
736
        // handler for the radio button for columns, adjust ranges
737
0
        if ( theCurArea.aStart.Row() == 0 && theCurArea.aEnd.Row() == rDoc.MaxRow() )
738
0
        {
739
0
            theCurArea.aEnd.SetRow( rDoc.MaxRow() - 1 );
740
0
            OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
741
0
            m_xEdAssign->SetText( aStr );
742
0
        }
743
0
        ScRange aRange( theCurData );
744
0
        aRange.aStart.SetRow( std::min( static_cast<tools::Long>(theCurArea.aEnd.Row()) + 1, static_cast<tools::Long>(rDoc.MaxRow()) ) );
745
0
        aRange.aEnd.SetRow( rDoc.MaxRow() );
746
0
        AdjustColRowData( aRange );
747
0
    }
748
0
    else if (m_xBtnRowHead->get_active())
749
0
    {
750
        // handler for the radio button for columns, adjust range
751
0
        if ( theCurArea.aStart.Col() == 0 && theCurArea.aEnd.Col() == rDoc.MaxCol() )
752
0
        {
753
0
            theCurArea.aEnd.SetCol( rDoc.MaxCol() - 1 );
754
0
            OUString aStr(theCurArea.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
755
0
            m_xEdAssign->SetText( aStr );
756
0
        }
757
0
        ScRange aRange( theCurData );
758
0
        aRange.aStart.SetCol( static_cast<SCCOL>(std::min( static_cast<tools::Long>(theCurArea.aEnd.Col()) + 1, static_cast<tools::Long>(rDoc.MaxCol()) )) );
759
0
        aRange.aEnd.SetCol( rDoc.MaxCol() );
760
0
        AdjustColRowData( aRange );
761
0
    }
762
0
}
763
764
IMPL_LINK( ScColRowNameRangesDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
765
0
{
766
0
    if (&rCtrl == m_xEdAssign.get())
767
0
        m_pEdActive = m_xEdAssign.get();
768
0
    else if (&rCtrl == m_xEdAssign2.get())
769
0
        m_pEdActive = m_xEdAssign2.get();
770
0
    else
771
0
        m_pEdActive = nullptr;
772
773
0
    if( m_pEdActive )
774
0
        m_pEdActive->SelectAll();
775
0
}
776
777
IMPL_LINK( ScColRowNameRangesDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
778
0
{
779
0
    if (&rCtrl == m_xRbAssign.get())
780
0
        m_pEdActive = m_xEdAssign.get();
781
0
    else if (&rCtrl == m_xRbAssign2.get())
782
0
        m_pEdActive = m_xEdAssign2.get();
783
0
    else
784
0
        m_pEdActive = nullptr;
785
786
0
    if( m_pEdActive )
787
0
        m_pEdActive->SelectAll();
788
0
}
789
790
IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseEditFocusHdl, formula::RefEdit&, void)
791
0
{
792
0
    bDlgLostFocus = !m_xDialog->has_toplevel_focus();
793
0
}
794
795
IMPL_LINK_NOARG(ScColRowNameRangesDlg, LoseButtonFocusHdl, formula::RefButton&, void)
796
0
{
797
0
    bDlgLostFocus = !m_xDialog->has_toplevel_focus();
798
0
}
799
800
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */