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 <sal/config.h>
21
22 #include "breakpoint.hxx"
23 #include "brkdlg.hxx"
24 #include <basobj.hxx>
25
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/sfxsids.hrc>
28
29 namespace basctl
30 {
31 // FIXME Why does BreakPointDialog allow only sal_uInt16 for break-point line
32 // numbers, whereas BreakPoint supports sal_uLong?
33
34 namespace
35 {
lcl_ParseText(OUString const & rText,size_t & rLineNr)36 bool lcl_ParseText(OUString const& rText, size_t& rLineNr)
37 {
38 // aText should look like "# n" where
39 // n > 0 && n < std::numeric_limits< sal_uInt16 >::max().
40 // All spaces are ignored, so there can even be spaces within the
41 // number n. (Maybe it would be better to ignore all whitespace instead
42 // of just spaces.)
43 OUString aText(rText.replaceAll(" ", ""));
44 if (aText.isEmpty())
45 return false;
46 sal_Unicode cFirst = aText[0];
47 if (cFirst != '#' && (cFirst < '0' || cFirst > '9'))
48 return false;
49 if (cFirst == '#')
50 aText = aText.copy(1);
51 // XXX Assumes that sal_uInt16 is contained within sal_Int32:
52 sal_Int32 n = aText.toInt32();
53 if (n <= 0)
54 return false;
55 rLineNr = static_cast<size_t>(n);
56 return true;
57 }
58
59 } // namespace
60
BreakPointDialog(weld::Window * pParent,BreakPointList & rBrkPntList)61 BreakPointDialog::BreakPointDialog(weld::Window* pParent, BreakPointList& rBrkPntList)
62 : GenericDialogController(pParent, "modules/BasicIDE/ui/managebreakpoints.ui",
63 "ManageBreakpointsDialog")
64 , m_rOriginalBreakPointList(rBrkPntList)
65 , m_aModifiedBreakPointList(rBrkPntList)
66 , m_xComboBox(m_xBuilder->weld_entry_tree_view("entriesgrid", "entries", "entrieslist"))
67 , m_xOKButton(m_xBuilder->weld_button("ok"))
68 , m_xNewButton(m_xBuilder->weld_button("new"))
69 , m_xDelButton(m_xBuilder->weld_button("delete"))
70 , m_xCheckBox(m_xBuilder->weld_check_button("active"))
71 , m_xNumericField(m_xBuilder->weld_spin_button("pass"))
72 {
73 m_xComboBox->set_size_request(m_xComboBox->get_approximate_digit_width() * 20, -1);
74 m_xComboBox->set_height_request_by_rows(12);
75
76 m_xComboBox->freeze();
77 for (size_t i = 0, n = m_aModifiedBreakPointList.size(); i < n; ++i)
78 {
79 BreakPoint& rBrk = m_aModifiedBreakPointList.at(i);
80 OUString aEntryStr("# " + OUString::number(rBrk.nLine));
81 m_xComboBox->append_text(aEntryStr);
82 }
83 m_xComboBox->thaw();
84
85 m_xOKButton->connect_clicked(LINK(this, BreakPointDialog, ButtonHdl));
86 m_xNewButton->connect_clicked(LINK(this, BreakPointDialog, ButtonHdl));
87 m_xDelButton->connect_clicked(LINK(this, BreakPointDialog, ButtonHdl));
88
89 m_xCheckBox->connect_toggled(LINK(this, BreakPointDialog, CheckBoxHdl));
90 m_xComboBox->connect_changed(LINK(this, BreakPointDialog, EditModifyHdl));
91 m_xComboBox->connect_row_activated(LINK(this, BreakPointDialog, TreeModifyHdl));
92 m_xComboBox->grab_focus();
93
94 m_xNumericField->set_range(0, 0x7FFFFFFF);
95 m_xNumericField->set_increments(1, 10);
96 m_xNumericField->connect_value_changed(LINK(this, BreakPointDialog, FieldModifyHdl));
97
98 if (m_xComboBox->get_count())
99 m_xComboBox->set_active(0);
100
101 if (m_aModifiedBreakPointList.size())
102 UpdateFields(m_aModifiedBreakPointList.at(0));
103
104 CheckButtons();
105 }
106
~BreakPointDialog()107 BreakPointDialog::~BreakPointDialog() {}
108
SetCurrentBreakPoint(BreakPoint const & rBrk)109 void BreakPointDialog::SetCurrentBreakPoint(BreakPoint const& rBrk)
110 {
111 OUString aStr("# " + OUString::number(rBrk.nLine));
112 m_xComboBox->set_entry_text(aStr);
113 UpdateFields(rBrk);
114 }
115
CheckButtons()116 void BreakPointDialog::CheckButtons()
117 {
118 // "New" button is enabled if the combo box edit contains a valid line
119 // number that is not already present in the combo box list; otherwise
120 // "OK" and "Delete" buttons are enabled:
121 size_t nLine;
122 if (lcl_ParseText(m_xComboBox->get_active_text(), nLine)
123 && m_aModifiedBreakPointList.FindBreakPoint(nLine) == nullptr)
124 {
125 m_xNewButton->set_sensitive(true);
126 m_xOKButton->set_sensitive(false);
127 m_xDelButton->set_sensitive(false);
128 m_xDelButton->set_has_default(false);
129 m_xNewButton->set_has_default(true);
130 }
131 else
132 {
133 m_xNewButton->set_sensitive(false);
134 m_xOKButton->set_sensitive(true);
135 m_xDelButton->set_sensitive(true);
136 m_xNewButton->set_has_default(false);
137 m_xDelButton->set_has_default(true);
138 }
139 }
140
IMPL_LINK(BreakPointDialog,CheckBoxHdl,weld::Toggleable &,rButton,void)141 IMPL_LINK(BreakPointDialog, CheckBoxHdl, weld::Toggleable&, rButton, void)
142 {
143 BreakPoint* pBrk = GetSelectedBreakPoint();
144 if (pBrk)
145 pBrk->bEnabled = rButton.get_active();
146 }
147
IMPL_LINK(BreakPointDialog,EditModifyHdl,weld::ComboBox &,rBox,void)148 IMPL_LINK(BreakPointDialog, EditModifyHdl, weld::ComboBox&, rBox, void)
149 {
150 CheckButtons();
151
152 int nEntry = rBox.find_text(rBox.get_active_text());
153 if (nEntry == -1)
154 return;
155 BreakPoint& rBrk = m_aModifiedBreakPointList.at(nEntry);
156 UpdateFields(rBrk);
157 }
158
IMPL_LINK(BreakPointDialog,FieldModifyHdl,weld::SpinButton &,rEdit,void)159 IMPL_LINK(BreakPointDialog, FieldModifyHdl, weld::SpinButton&, rEdit, void)
160 {
161 BreakPoint* pBrk = GetSelectedBreakPoint();
162 if (pBrk)
163 pBrk->nStopAfter = rEdit.get_value();
164 }
165
IMPL_LINK_NOARG(BreakPointDialog,TreeModifyHdl,weld::TreeView &,bool)166 IMPL_LINK_NOARG(BreakPointDialog, TreeModifyHdl, weld::TreeView&, bool)
167 {
168 if (m_xDelButton->get_sensitive())
169 ButtonHdl(*m_xDelButton);
170 return true;
171 }
172
IMPL_LINK(BreakPointDialog,ButtonHdl,weld::Button &,rButton,void)173 IMPL_LINK(BreakPointDialog, ButtonHdl, weld::Button&, rButton, void)
174 {
175 if (&rButton == m_xOKButton.get())
176 {
177 m_rOriginalBreakPointList.transfer(m_aModifiedBreakPointList);
178 m_xDialog->response(RET_OK);
179 }
180 else if (&rButton == m_xNewButton.get())
181 {
182 // keep checkbox in mind!
183 OUString aText(m_xComboBox->get_active_text());
184 size_t nLine;
185 bool bValid = lcl_ParseText(aText, nLine);
186 if (bValid)
187 {
188 BreakPoint aBrk(nLine);
189 aBrk.bEnabled = m_xCheckBox->get_active();
190 aBrk.nStopAfter = static_cast<size_t>(m_xNumericField->get_value());
191 m_aModifiedBreakPointList.InsertSorted(aBrk);
192 OUString aEntryStr("# " + OUString::number(aBrk.nLine));
193 m_xComboBox->append_text(aEntryStr);
194 if (SfxDispatcher* pDispatcher = GetDispatcher())
195 pDispatcher->Execute(SID_BASICIDE_BRKPNTSCHANGED);
196 }
197 else
198 {
199 m_xComboBox->set_active_text(aText);
200 m_xComboBox->grab_focus();
201 }
202 CheckButtons();
203 }
204 else if (&rButton == m_xDelButton.get())
205 {
206 int nEntry = m_xComboBox->find_text(m_xComboBox->get_active_text());
207 if (nEntry != -1)
208 {
209 m_aModifiedBreakPointList.remove(nEntry);
210 m_xComboBox->remove(nEntry);
211 if (nEntry && nEntry >= m_xComboBox->get_count())
212 nEntry--;
213 m_xComboBox->set_active_text(m_xComboBox->get_text(nEntry));
214 if (SfxDispatcher* pDispatcher = GetDispatcher())
215 pDispatcher->Execute(SID_BASICIDE_BRKPNTSCHANGED);
216 CheckButtons();
217 }
218 }
219 }
220
UpdateFields(BreakPoint const & rBrk)221 void BreakPointDialog::UpdateFields(BreakPoint const& rBrk)
222 {
223 m_xCheckBox->set_active(rBrk.bEnabled);
224 m_xNumericField->set_value(rBrk.nStopAfter);
225 }
226
GetSelectedBreakPoint()227 BreakPoint* BreakPointDialog::GetSelectedBreakPoint()
228 {
229 int nEntry = m_xComboBox->find_text(m_xComboBox->get_active_text());
230 if (nEntry == -1)
231 return nullptr;
232 return &m_aModifiedBreakPointList.at(nEntry);
233 }
234
235 } // namespace basctl
236
237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
238