/src/libreoffice/sw/source/uibase/ribbar/inputwin.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 <sal/config.h> |
21 | | #include <sal/log.hxx> |
22 | | |
23 | | #include <osl/diagnose.h> |
24 | | #include <comphelper/string.hxx> |
25 | | #include <o3tl/safeint.hxx> |
26 | | #include <officecfg/Office/Common.hxx> |
27 | | #include <tools/gen.hxx> |
28 | | #include <sfx2/chalign.hxx> |
29 | | #include <sfx2/objface.hxx> |
30 | | #include <sfx2/viewfrm.hxx> |
31 | | #include <sfx2/dispatch.hxx> |
32 | | #include <svx/ruler.hxx> |
33 | | #include <svl/stritem.hxx> |
34 | | #include <vcl/event.hxx> |
35 | | #include <vcl/image.hxx> |
36 | | #include <vcl/svapp.hxx> |
37 | | #include <vcl/weld/Menu.hxx> |
38 | | #include <vcl/weld/Window.hxx> |
39 | | #include <vcl/weld/weldutils.hxx> |
40 | | |
41 | | #include <swtypes.hxx> |
42 | | #include <cmdid.h> |
43 | | #include <swmodule.hxx> |
44 | | #include <wrtsh.hxx> |
45 | | #include <view.hxx> |
46 | | #include <inputwin.hxx> |
47 | | #include <fldbas.hxx> |
48 | | #include <fldmgr.hxx> |
49 | | #include <frmfmt.hxx> |
50 | | #include <cellatr.hxx> |
51 | | #include <edtwin.hxx> |
52 | | #include <helpids.h> |
53 | | #include <strings.hrc> |
54 | | #include <bitmaps.hlst> |
55 | | |
56 | | // Only for the UpdateRange: Delete the box in which the stacked cursor is positioned. |
57 | | #include <pam.hxx> |
58 | | |
59 | | #include <swundo.hxx> |
60 | | |
61 | | #include <IDocumentContentOperations.hxx> |
62 | | |
63 | | constexpr ToolBoxItemId ED_POS(2); |
64 | | constexpr ToolBoxItemId ED_FORMULA(3); |
65 | | constexpr ToolBoxItemId FN_FORMULA_CALC(FN_FORMAT + 156); /* select formula */ |
66 | | constexpr ToolBoxItemId FN_FORMULA_CANCEL(FN_FORMAT + 157); /* don't apply formula */ |
67 | | constexpr ToolBoxItemId FN_FORMULA_APPLY(FN_FORMAT + 158); /* apply formula */ |
68 | | |
69 | | SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT ) |
70 | | |
71 | | IMPL_LINK(PosEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool) |
72 | 0 | { |
73 | 0 | return ChildKeyInput(rKEvt); |
74 | 0 | } |
75 | | |
76 | | SwInputWindow::SwInputWindow(vcl::Window* pParent, SfxDispatcher const * pDispatcher) |
77 | 0 | : ToolBox(pParent, WB_3DLOOK|WB_BORDER) |
78 | 0 | , mxPos(VclPtr<PosEdit>::Create(this)) |
79 | 0 | , mxEdit(VclPtr<InputEdit>::Create(this)) |
80 | 0 | , m_pWrtShell(nullptr) |
81 | 0 | , m_pView(nullptr) |
82 | 0 | , m_bDoesUndo(true) |
83 | 0 | , m_bResetUndo(false) |
84 | 0 | , m_bCallUndo(false) |
85 | 0 | { |
86 | 0 | m_bFirst = true; |
87 | 0 | m_bIsTable = m_bDelSel = false; |
88 | |
|
89 | 0 | InsertItem(FN_FORMULA_CALC, Image(StockImage::Yes, RID_BMP_FORMULA_CALC), |
90 | 0 | SwResId(STR_FORMULA_CALC)); |
91 | 0 | InsertItem(FN_FORMULA_CANCEL, Image(StockImage::Yes, RID_BMP_FORMULA_CANCEL), |
92 | 0 | SwResId(STR_FORMULA_CANCEL)); |
93 | 0 | InsertItem(FN_FORMULA_APPLY, Image(StockImage::Yes, RID_BMP_FORMULA_APPLY), |
94 | 0 | SwResId(STR_FORMULA_APPLY)); |
95 | |
|
96 | 0 | SetHelpId(FN_FORMULA_CALC, HID_TBX_FORMULA_CALC); |
97 | 0 | SetHelpId(FN_FORMULA_CANCEL, HID_TBX_FORMULA_CANCEL); |
98 | 0 | SetHelpId(FN_FORMULA_APPLY, HID_TBX_FORMULA_APPLY); |
99 | |
|
100 | 0 | SwView *pDispatcherView = dynamic_cast<SwView*>(pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr); |
101 | 0 | SwView* pActiveView = ::GetActiveView(); |
102 | 0 | if (pDispatcherView == pActiveView) |
103 | 0 | m_pView = pActiveView; |
104 | 0 | m_pWrtShell = m_pView ? m_pView->GetWrtShellPtr() : nullptr; |
105 | |
|
106 | 0 | InsertWindow(ED_POS, mxPos.get(), ToolBoxItemBits::NONE, 0); |
107 | 0 | SetItemText(ED_POS, SwResId(STR_ACCESS_FORMULA_TYPE)); |
108 | 0 | mxPos->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TYPE)); |
109 | 0 | SetAccessibleName(SwResId(STR_ACCESS_FORMULA_TOOLBAR)); |
110 | 0 | InsertSeparator ( 1 ); |
111 | 0 | InsertSeparator (); |
112 | 0 | InsertWindow(ED_FORMULA, mxEdit.get()); |
113 | 0 | SetItemText(ED_FORMULA, SwResId(STR_ACCESS_FORMULA_TEXT)); |
114 | 0 | mxEdit->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TEXT)); |
115 | 0 | SetHelpId(ED_FORMULA, HID_EDIT_FORMULA); |
116 | |
|
117 | 0 | SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | ToolBoxItemBits::DROPDOWNONLY ); |
118 | 0 | SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl )); |
119 | |
|
120 | 0 | Size aSizeTbx = CalcWindowSizePixel(); |
121 | 0 | Size aEditSize = mxEdit->GetSizePixel(); |
122 | 0 | tools::Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) ); |
123 | 0 | tools::Long nMaxHeight = std::max(aEditSize.Height(), aItemRect.GetHeight()); |
124 | 0 | if( nMaxHeight+2 > aSizeTbx.Height() ) |
125 | 0 | aSizeTbx.setHeight( nMaxHeight+2 ); |
126 | 0 | Size aSize = GetSizePixel(); |
127 | 0 | aSize.setHeight( aSizeTbx.Height() ); |
128 | 0 | SetSizePixel( aSize ); |
129 | | |
130 | | // align edit and item vcentered |
131 | 0 | Size aPosSize = mxPos->GetSizePixel(); |
132 | 0 | aPosSize.setHeight( nMaxHeight ); |
133 | 0 | aEditSize.setHeight( nMaxHeight ); |
134 | 0 | Point aPosPos = mxPos->GetPosPixel(); |
135 | 0 | Point aEditPos = mxEdit->GetPosPixel(); |
136 | 0 | aPosPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 ); |
137 | 0 | aEditPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 ); |
138 | 0 | mxPos->SetPosSizePixel( aPosPos, aPosSize ); |
139 | 0 | mxEdit->SetPosSizePixel( aEditPos, aEditSize ); |
140 | 0 | } Unexecuted instantiation: SwInputWindow::SwInputWindow(vcl::Window*, SfxDispatcher const*) Unexecuted instantiation: SwInputWindow::SwInputWindow(vcl::Window*, SfxDispatcher const*) |
141 | | |
142 | | SwInputWindow::~SwInputWindow() |
143 | 0 | { |
144 | 0 | disposeOnce(); |
145 | 0 | } |
146 | | |
147 | | void SwInputWindow::dispose() |
148 | 0 | { |
149 | | // wake rulers |
150 | 0 | if(m_pView) |
151 | 0 | { |
152 | 0 | m_pView->GetHRuler().SetActive(); |
153 | 0 | m_pView->GetVRuler().SetActive(); |
154 | 0 | } |
155 | 0 | m_pMgr.reset(); |
156 | 0 | if(m_pWrtShell) |
157 | 0 | m_pWrtShell->EndSelTableCells(); |
158 | |
|
159 | 0 | CleanupUglyHackWithUndo(); |
160 | |
|
161 | 0 | mxPos.disposeAndClear(); |
162 | 0 | mxEdit.disposeAndClear(); |
163 | 0 | ToolBox::dispose(); |
164 | 0 | } |
165 | | |
166 | | void SwInputWindow::CleanupUglyHackWithUndo() |
167 | 0 | { |
168 | 0 | if (!m_bResetUndo) |
169 | 0 | return; |
170 | | |
171 | 0 | if (m_pWrtShell) |
172 | 0 | { |
173 | 0 | DelBoxContent(); |
174 | 0 | m_pWrtShell->DoUndo(m_bDoesUndo); |
175 | 0 | if (m_bCallUndo) |
176 | 0 | { |
177 | 0 | m_pWrtShell->Undo(); |
178 | 0 | } |
179 | 0 | } |
180 | 0 | m_bResetUndo = false; // #i117122# once is enough :) |
181 | 0 | } |
182 | | |
183 | | void SwInputWindow::Resize() |
184 | 0 | { |
185 | 0 | ToolBox::Resize(); |
186 | |
|
187 | 0 | tools::Long nWidth = GetSizePixel().Width(); |
188 | 0 | tools::Long nLeft = mxEdit->GetPosPixel().X(); |
189 | 0 | Size aEditSize = mxEdit->GetSizePixel(); |
190 | |
|
191 | 0 | aEditSize.setWidth( std::max( static_cast<tools::Long>(nWidth - nLeft - 5), tools::Long(0) ) ); |
192 | 0 | mxEdit->SetSizePixel( aEditSize ); |
193 | 0 | } |
194 | | |
195 | | void SwInputWindow::ShowWin() |
196 | 0 | { |
197 | 0 | m_bIsTable = false; |
198 | | // stop rulers |
199 | 0 | if (m_pView && m_pWrtShell) |
200 | 0 | { |
201 | 0 | m_pView->GetHRuler().SetActive( false ); |
202 | 0 | m_pView->GetVRuler().SetActive( false ); |
203 | | |
204 | | // Cursor in table |
205 | 0 | m_bIsTable = m_pWrtShell->IsCursorInTable(); |
206 | |
|
207 | 0 | if( m_bFirst ) |
208 | 0 | m_pWrtShell->SelTableCells( LINK( this, SwInputWindow, |
209 | 0 | SelTableCellsNotify) ); |
210 | 0 | if( m_bIsTable ) |
211 | 0 | { |
212 | 0 | const OUString aPos = m_pWrtShell->GetBoxNms(); |
213 | 0 | sal_Int32 nPos = 0; |
214 | 0 | short nSrch = -1; |
215 | 0 | while( (nPos = aPos.indexOf( ':',nPos + 1 ) ) != -1 ) |
216 | 0 | nSrch = static_cast<short>(nPos); |
217 | 0 | mxPos->set_text( aPos.copy( ++nSrch ) ); |
218 | 0 | m_aCurrentTableName = m_pWrtShell->GetTableFormat()->GetName(); |
219 | 0 | } |
220 | 0 | else |
221 | 0 | mxPos->set_text(SwResId(STR_TBL_FORMULA)); |
222 | | |
223 | | // Edit current field |
224 | 0 | OSL_ENSURE(m_pMgr == nullptr, "FieldManager not deleted"); |
225 | 0 | m_pMgr.reset(new SwFieldMgr); |
226 | | |
227 | | // Form should always begin with "=" , so set here |
228 | 0 | OUString sEdit('='); |
229 | 0 | if( m_pMgr->GetCurField() && SwFieldTypesEnum::Formel == m_pMgr->GetCurTypeId() ) |
230 | 0 | { |
231 | 0 | sEdit += m_pMgr->GetCurFieldPar2(); |
232 | 0 | } |
233 | 0 | else if( m_bFirst && m_bIsTable ) |
234 | 0 | { |
235 | 0 | m_bResetUndo = true; |
236 | 0 | SAL_WARN_IF( |
237 | 0 | officecfg::Office::Common::Undo::Steps::get() <= 0, |
238 | 0 | "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0"); |
239 | | |
240 | 0 | m_bDoesUndo = m_pWrtShell->DoesUndo(); |
241 | 0 | if( !m_bDoesUndo ) |
242 | 0 | { |
243 | 0 | m_pWrtShell->DoUndo(); |
244 | 0 | } |
245 | |
|
246 | 0 | if( !m_pWrtShell->SwCursorShell::HasSelection() ) |
247 | 0 | { |
248 | 0 | m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); |
249 | 0 | m_pWrtShell->SetMark(); |
250 | 0 | m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); |
251 | 0 | } |
252 | 0 | if( m_pWrtShell->SwCursorShell::HasSelection() ) |
253 | 0 | { |
254 | 0 | m_pWrtShell->StartUndo( SwUndoId::DELETE ); |
255 | 0 | m_pWrtShell->Delete(false); |
256 | 0 | if( SwUndoId::EMPTY != m_pWrtShell->EndUndo( SwUndoId::DELETE )) |
257 | 0 | { |
258 | 0 | m_bCallUndo = true; |
259 | 0 | } |
260 | 0 | } |
261 | 0 | m_pWrtShell->DoUndo(false); |
262 | |
|
263 | 0 | SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA>( m_pWrtShell->GetAttrPool() )); |
264 | 0 | if( m_pWrtShell->GetTableBoxFormulaAttrs( aSet )) |
265 | 0 | { |
266 | 0 | SwTableBoxFormula& rFormula |
267 | 0 | = const_cast<SwTableBoxFormula&>(aSet.Get(RES_BOXATR_FORMULA)); |
268 | | // rFormula could be ANY of the table's formulas. |
269 | | // GetFormula returns the "current" formula - which is basically undefined, |
270 | | // so do something that encourages the current position's formula to become current. |
271 | 0 | if (m_pWrtShell->GetCursor()) |
272 | 0 | { |
273 | 0 | const SwNode* pNd = m_pWrtShell->GetCursor()->GetPointNode().FindTableNode(); |
274 | 0 | if (pNd) |
275 | 0 | { |
276 | 0 | const SwTable& rTable = static_cast<const SwTableNode*>(pNd)->GetTable(); |
277 | | // get cell's external formula (for UI) by waving the magic wand. |
278 | 0 | rFormula.PtrToBoxNm(&rTable); |
279 | 0 | } |
280 | 0 | } |
281 | |
|
282 | 0 | sEdit += rFormula.GetFormula(); |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | 0 | if( m_bFirst ) |
287 | 0 | { |
288 | | // Set WrtShell flags correctly |
289 | 0 | m_pWrtShell->SttSelect(); |
290 | 0 | m_pWrtShell->EndSelect(); |
291 | 0 | } |
292 | |
|
293 | 0 | m_bFirst = false; |
294 | |
|
295 | 0 | mxEdit->connect_changed( LINK( this, SwInputWindow, ModifyHdl )); |
296 | |
|
297 | 0 | mxEdit->set_text( sEdit ); |
298 | 0 | m_sOldFormula = sEdit; |
299 | | |
300 | | // For input cut the UserInterface |
301 | |
|
302 | 0 | m_pView->GetEditWin().LockKeyInput(true); |
303 | 0 | m_pView->GetViewFrame().GetDispatcher()->Lock(true); |
304 | 0 | m_pWrtShell->Push(); |
305 | 0 | } |
306 | | |
307 | 0 | ToolBox::Show(); |
308 | | |
309 | | // grab focus after ToolBox is shown so focus isn't potentially lost elsewhere |
310 | 0 | if (m_pView) |
311 | 0 | { |
312 | 0 | int nPos = mxEdit->get_text().getLength(); |
313 | 0 | mxEdit->select_region(nPos, nPos); |
314 | 0 | mxEdit->GrabFocus(); |
315 | 0 | } |
316 | 0 | } |
317 | | |
318 | | void SwInputWindow::MenuHdl(std::u16string_view command) |
319 | 0 | { |
320 | 0 | if (!command.empty()) |
321 | 0 | mxEdit->replace_selection(OUString::Concat(command) + " "); |
322 | 0 | } |
323 | | |
324 | | IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl, ToolBox *, void) |
325 | 0 | { |
326 | 0 | ToolBoxItemId nCurID = GetCurItemId(); |
327 | 0 | EndSelection(); // reset back CurItemId ! |
328 | 0 | if (nCurID == FN_FORMULA_CALC) |
329 | 0 | { |
330 | 0 | std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/inputwinmenu.ui"_ustr)); |
331 | 0 | std::unique_ptr<weld::Menu> xPopMenu(xBuilder->weld_menu(u"menu"_ustr)); |
332 | 0 | tools::Rectangle aRect(GetItemRect(FN_FORMULA_CALC)); |
333 | 0 | weld::Window* pParent = weld::GetPopupParent(*this, aRect); |
334 | 0 | MenuHdl(xPopMenu->popup_at_rect(pParent, aRect)); |
335 | 0 | } |
336 | 0 | } |
337 | | |
338 | | void SwInputWindow::Click( ) |
339 | 0 | { |
340 | 0 | ToolBoxItemId nCurID = GetCurItemId(); |
341 | 0 | EndSelection(); // reset back CurItemId ! |
342 | 0 | if ( nCurID == FN_FORMULA_CANCEL ) |
343 | 0 | { |
344 | 0 | CancelFormula(); |
345 | 0 | } |
346 | 0 | else if (nCurID == FN_FORMULA_APPLY) |
347 | 0 | { |
348 | 0 | ApplyFormula(); |
349 | 0 | } |
350 | 0 | } |
351 | | |
352 | | void SwInputWindow::ApplyFormula() |
353 | 0 | { |
354 | | // in case it was created while loading the document, the active view |
355 | | // wasn't initialised at that time, so ShowWin() didn't initialise anything |
356 | | // either - nothing to do |
357 | 0 | if (!m_pView || !m_pWrtShell) |
358 | 0 | { |
359 | | // presumably there must be an active view now since the event arrived |
360 | 0 | if (SwView* pView = GetActiveView()) |
361 | 0 | { |
362 | | // this just makes the input window go away, so that the next time it works |
363 | 0 | pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); |
364 | 0 | } |
365 | 0 | return; |
366 | 0 | } |
367 | | |
368 | 0 | m_pView->GetViewFrame().GetDispatcher()->Lock(false); |
369 | 0 | m_pView->GetEditWin().LockKeyInput(false); |
370 | 0 | CleanupUglyHackWithUndo(); |
371 | 0 | m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); |
372 | | |
373 | | // Form should always begin with "=", so remove it here again |
374 | 0 | OUString sEdit(comphelper::string::strip(mxEdit->get_text(), ' ')); |
375 | 0 | if( !sEdit.isEmpty() && '=' == sEdit[0] ) |
376 | 0 | sEdit = sEdit.copy( 1 ); |
377 | 0 | SfxStringItem aParam(FN_EDIT_FORMULA, sEdit); |
378 | |
|
379 | 0 | m_pWrtShell->EndSelTableCells(); |
380 | 0 | m_pView->GetEditWin().GrabFocus(); |
381 | 0 | const SfxPoolItem* aArgs[2]; |
382 | 0 | aArgs[0] = &aParam; |
383 | 0 | aArgs[1] = nullptr; |
384 | 0 | m_pView->GetViewFrame().GetBindings().Execute( FN_EDIT_FORMULA, aArgs, SfxCallMode::ASYNCHRON ); |
385 | 0 | } |
386 | | |
387 | | void SwInputWindow::CancelFormula() |
388 | 0 | { |
389 | | // in case it was created while loading the document, the active view |
390 | | // wasn't initialised at that time, so ShowWin() didn't initialise anything |
391 | | // either - nothing to do |
392 | 0 | if (!m_pView || !m_pWrtShell) |
393 | 0 | { |
394 | | // presumably there must be an active view now since the event arrived |
395 | 0 | if (SwView* pView = GetActiveView()) |
396 | 0 | { |
397 | | // this just makes the input window go away, so that the next time it works |
398 | 0 | pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); |
399 | 0 | } |
400 | 0 | return; |
401 | 0 | } |
402 | | |
403 | 0 | m_pView->GetViewFrame().GetDispatcher()->Lock( false ); |
404 | 0 | m_pView->GetEditWin().LockKeyInput(false); |
405 | 0 | CleanupUglyHackWithUndo(); |
406 | 0 | m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); |
407 | |
|
408 | 0 | if( m_bDelSel ) |
409 | 0 | m_pWrtShell->EnterStdMode(); |
410 | |
|
411 | 0 | m_pWrtShell->EndSelTableCells(); |
412 | |
|
413 | 0 | m_pView->GetEditWin().GrabFocus(); |
414 | |
|
415 | 0 | m_pView->GetViewFrame().GetDispatcher()->Execute( FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON); |
416 | 0 | } |
417 | | |
418 | | const sal_Unicode CH_LRE = 0x202a; |
419 | | const sal_Unicode CH_PDF = 0x202c; |
420 | | |
421 | | IMPL_LINK( SwInputWindow, SelTableCellsNotify, SwWrtShell&, rCaller, void ) |
422 | 0 | { |
423 | 0 | if(m_pWrtShell && m_bIsTable) |
424 | 0 | { |
425 | 0 | SwFrameFormat* pTableFormat = rCaller.GetTableFormat(); |
426 | 0 | OUString sBoxNms( rCaller.GetBoxNms() ); |
427 | 0 | UIName sTableNm; |
428 | 0 | if( pTableFormat && m_aCurrentTableName != pTableFormat->GetName() ) |
429 | 0 | sTableNm = pTableFormat->GetName(); |
430 | |
|
431 | 0 | mxEdit->UpdateRange( sBoxNms, sTableNm ); |
432 | |
|
433 | 0 | OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() |
434 | 0 | + OUStringChar(CH_PDF); |
435 | |
|
436 | 0 | if( sNew != m_sOldFormula ) |
437 | 0 | { |
438 | | // The WrtShell is in the table selection, |
439 | | // then cancel the table selection otherwise, the cursor is |
440 | | // positioned "in the forest" and the live update does not work! |
441 | 0 | m_pWrtShell->StartAllAction(); |
442 | |
|
443 | 0 | SwPaM aPam( *m_pWrtShell->GetStackCursor()->GetPoint() ); |
444 | 0 | aPam.Move( fnMoveBackward, GoInSection ); |
445 | 0 | aPam.SetMark(); |
446 | 0 | aPam.Move( fnMoveForward, GoInSection ); |
447 | |
|
448 | 0 | IDocumentContentOperations& rIDCO = m_pWrtShell->getIDocumentContentOperations(); |
449 | 0 | rIDCO.DeleteRange( aPam ); |
450 | 0 | rIDCO.InsertString( aPam, sNew ); |
451 | 0 | m_pWrtShell->EndAllAction(); |
452 | 0 | m_sOldFormula = sNew; |
453 | 0 | } |
454 | 0 | } |
455 | 0 | else |
456 | 0 | mxEdit->GrabFocus(); |
457 | 0 | } |
458 | | |
459 | | void SwInputWindow::SetFormula( const OUString& rFormula ) |
460 | 0 | { |
461 | 0 | OUString sEdit('='); |
462 | 0 | if( !rFormula.isEmpty() ) |
463 | 0 | { |
464 | 0 | if( '=' == rFormula[0] ) |
465 | 0 | sEdit = rFormula; |
466 | 0 | else |
467 | 0 | sEdit += rFormula; |
468 | 0 | } |
469 | 0 | mxEdit->set_text( sEdit ); |
470 | 0 | mxEdit->select_region(sEdit.getLength(), sEdit.getLength()); |
471 | 0 | m_bDelSel = true; |
472 | 0 | } |
473 | | |
474 | | IMPL_LINK_NOARG(SwInputWindow, ModifyHdl, weld::Entry&, void) |
475 | 0 | { |
476 | 0 | if (m_pWrtShell && m_bIsTable && m_bResetUndo) |
477 | 0 | { |
478 | 0 | m_pWrtShell->StartAllAction(); |
479 | 0 | DelBoxContent(); |
480 | 0 | OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() |
481 | 0 | + OUStringChar(CH_PDF); |
482 | 0 | m_pWrtShell->SwEditShell::Insert2( sNew ); |
483 | 0 | m_pWrtShell->EndAllAction(); |
484 | 0 | m_sOldFormula = sNew; |
485 | 0 | } |
486 | 0 | } |
487 | | |
488 | | void SwInputWindow::DelBoxContent() |
489 | 0 | { |
490 | 0 | if( m_pWrtShell && m_bIsTable ) |
491 | 0 | { |
492 | 0 | m_pWrtShell->StartAllAction(); |
493 | 0 | m_pWrtShell->ClearMark(); |
494 | 0 | m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); |
495 | 0 | m_pWrtShell->Push(); |
496 | 0 | m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); |
497 | 0 | m_pWrtShell->SetMark(); |
498 | 0 | m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); |
499 | 0 | m_pWrtShell->SwEditShell::Delete(false); |
500 | 0 | m_pWrtShell->EndAllAction(); |
501 | 0 | } |
502 | 0 | } |
503 | | |
504 | | IMPL_LINK(InputEdit, KeyInputHdl, const KeyEvent&, rEvent, bool) |
505 | 0 | { |
506 | 0 | bool bHandled = false; |
507 | 0 | const vcl::KeyCode aCode = rEvent.GetKeyCode(); |
508 | 0 | if (aCode == KEY_RETURN || aCode == KEY_F2) |
509 | 0 | { |
510 | 0 | bHandled = ActivateHdl(*m_xWidget); |
511 | 0 | } |
512 | 0 | else if(aCode == KEY_ESCAPE ) |
513 | 0 | { |
514 | 0 | static_cast<SwInputWindow*>(GetParent())->CancelFormula(); |
515 | 0 | bHandled = true; |
516 | 0 | } |
517 | 0 | return bHandled || ChildKeyInput(rEvent); |
518 | 0 | } |
519 | | |
520 | | IMPL_LINK_NOARG(InputEdit, ActivateHdl, weld::Entry&, bool) |
521 | 0 | { |
522 | 0 | static_cast<SwInputWindow*>(GetParent())->ApplyFormula(); |
523 | 0 | return true; |
524 | 0 | } |
525 | | |
526 | | void InputEdit::UpdateRange(std::u16string_view rBoxes, |
527 | | const UIName& rName ) |
528 | 0 | { |
529 | 0 | if( rBoxes.empty() ) |
530 | 0 | { |
531 | 0 | GrabFocus(); |
532 | 0 | return; |
533 | 0 | } |
534 | 0 | const sal_Unicode cOpen = '<', cClose = '>', |
535 | 0 | cOpenBracket = '('; |
536 | 0 | OUString aPrefix = rName.toString(); |
537 | 0 | if(!rName.isEmpty()) |
538 | 0 | aPrefix += "."; |
539 | 0 | OUString aBoxes = aPrefix + rBoxes; |
540 | |
|
541 | 0 | int nSelStartPos, nSelEndPos; |
542 | 0 | m_xWidget->get_selection_bounds(nSelStartPos, nSelEndPos); |
543 | |
|
544 | 0 | Selection aSelection(nSelStartPos, nSelEndPos); |
545 | 0 | sal_uInt16 nSel = o3tl::narrowing<sal_uInt16>(aSelection.Len()); |
546 | | // OS: The following expression ensures that in the overwrite mode, |
547 | | // the selected closing parenthesis will be not deleted. |
548 | 0 | if( nSel && ( nSel > 1 || |
549 | 0 | m_xWidget->get_text()[ o3tl::narrowing<sal_uInt16>(aSelection.Min()) ] != cClose )) |
550 | 0 | m_xWidget->cut_clipboard(); |
551 | 0 | else |
552 | 0 | aSelection.Max() = aSelection.Min(); |
553 | 0 | OUString aActText(m_xWidget->get_text()); |
554 | 0 | const sal_uInt16 nLen = aActText.getLength(); |
555 | 0 | if( !nLen ) |
556 | 0 | { |
557 | 0 | OUString aStr = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose); |
558 | 0 | m_xWidget->set_text(aStr); |
559 | 0 | sal_Int32 nPos = aStr.indexOf( cClose ); |
560 | 0 | OSL_ENSURE(nPos != -1, "delimiter not found"); |
561 | 0 | ++nPos; |
562 | 0 | m_xWidget->select_region(nPos, nPos); |
563 | 0 | } |
564 | 0 | else |
565 | 0 | { |
566 | 0 | bool bFound = false; |
567 | 0 | sal_Unicode cCh; |
568 | 0 | sal_uInt16 nPos, nEndPos = 0, nStartPos = o3tl::narrowing<sal_uInt16>(aSelection.Min()); |
569 | 0 | if( nStartPos-- ) |
570 | 0 | { |
571 | 0 | do { |
572 | 0 | if( cOpen == (cCh = aActText[ nStartPos ] ) || |
573 | 0 | cOpenBracket == cCh ) |
574 | 0 | { |
575 | 0 | bFound = cCh == cOpen; |
576 | 0 | break; |
577 | 0 | } |
578 | 0 | } while( nStartPos-- > 0 ); |
579 | 0 | } |
580 | 0 | if( bFound ) |
581 | 0 | { |
582 | 0 | bFound = false; |
583 | 0 | nEndPos = nStartPos; |
584 | 0 | while( nEndPos < nLen ) |
585 | 0 | { |
586 | 0 | if( cClose == aActText[ nEndPos ] ) |
587 | 0 | { |
588 | 0 | bFound = true; |
589 | 0 | break; |
590 | 0 | } |
591 | 0 | ++nEndPos; |
592 | 0 | } |
593 | | // Only if the current position lies in the range or right behind. |
594 | 0 | if( bFound && ( nStartPos >= o3tl::make_unsigned(aSelection.Max()) || |
595 | 0 | o3tl::narrowing<sal_uInt16>(aSelection.Max()) > nEndPos + 1 )) |
596 | 0 | bFound = false; |
597 | 0 | } |
598 | 0 | if( bFound ) |
599 | 0 | { |
600 | 0 | nPos = ++nStartPos + 1; // We want behind |
601 | 0 | aActText = aActText.replaceAt( nStartPos, nEndPos - nStartPos, aBoxes ); |
602 | 0 | nPos = nPos + aBoxes.getLength(); |
603 | 0 | } |
604 | 0 | else |
605 | 0 | { |
606 | 0 | OUString aTmp = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose); |
607 | 0 | nPos = o3tl::narrowing<sal_uInt16>(aSelection.Min()); |
608 | 0 | aActText = aActText.replaceAt( nPos, 0, aTmp ); |
609 | 0 | nPos = nPos + aTmp.getLength(); |
610 | 0 | } |
611 | 0 | if( m_xWidget->get_text() != aActText ) |
612 | 0 | { |
613 | 0 | m_xWidget->set_text(aActText); |
614 | 0 | m_xWidget->select_region(nPos, nPos); |
615 | 0 | } |
616 | 0 | } |
617 | 0 | GrabFocus(); |
618 | |
|
619 | 0 | } |
620 | | |
621 | | SwInputChild::SwInputChild(vcl::Window* _pParent, |
622 | | sal_uInt16 nId, |
623 | | SfxBindings const * pBindings, |
624 | | SfxChildWinInfo* ) : |
625 | 0 | SfxChildWindow( _pParent, nId ) |
626 | 0 | { |
627 | 0 | m_pDispatch = pBindings->GetDispatcher(); |
628 | 0 | SetWindow(VclPtr<SwInputWindow>::Create(_pParent, m_pDispatch)); |
629 | 0 | static_cast<SwInputWindow*>(GetWindow())->ShowWin(); |
630 | 0 | SetAlignment(SfxChildAlignment::LOWESTTOP); |
631 | 0 | } |
632 | | |
633 | | SwInputChild::~SwInputChild() |
634 | 0 | { |
635 | 0 | if(m_pDispatch) |
636 | 0 | m_pDispatch->Lock(false); |
637 | 0 | } |
638 | | |
639 | | SfxChildWinInfo SwInputChild::GetInfo() const |
640 | 0 | { |
641 | 0 | SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); |
642 | 0 | return aInfo; |
643 | 0 | } |
644 | | |
645 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |