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