File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 192, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <memory> | |||
21 | #include <algorithm> | |||
22 | ||||
23 | #include <editeng/eeitem.hxx> | |||
24 | ||||
25 | #include <sfx2/app.hxx> | |||
26 | #include <editeng/adjustitem.hxx> | |||
27 | #include <editeng/editview.hxx> | |||
28 | #include <editeng/editstat.hxx> | |||
29 | #include <editeng/lspcitem.hxx> | |||
30 | #include <editeng/fhgtitem.hxx> | |||
31 | #include <editeng/wghtitem.hxx> | |||
32 | #include <editeng/postitem.hxx> | |||
33 | #include <editeng/langitem.hxx> | |||
34 | #include <sfx2/bindings.hxx> | |||
35 | #include <sfx2/lokhelper.hxx> | |||
36 | #include <sfx2/viewfrm.hxx> | |||
37 | #include <sfx2/dispatch.hxx> | |||
38 | #include <sfx2/event.hxx> | |||
39 | #include <editeng/scriptspaceitem.hxx> | |||
40 | #include <vcl/commandevent.hxx> | |||
41 | #include <vcl/cursor.hxx> | |||
42 | #include <vcl/help.hxx> | |||
43 | #include <vcl/settings.hxx> | |||
44 | #include <svl/stritem.hxx> | |||
45 | #include <vcl/svapp.hxx> | |||
46 | #include <vcl/weldutils.hxx> | |||
47 | #include <unotools/charclass.hxx> | |||
48 | ||||
49 | #include <inputwin.hxx> | |||
50 | #include <scmod.hxx> | |||
51 | #include <global.hxx> | |||
52 | #include <scresid.hxx> | |||
53 | #include <strings.hrc> | |||
54 | #include <globstr.hrc> | |||
55 | #include <bitmaps.hlst> | |||
56 | #include <reffact.hxx> | |||
57 | #include <editutil.hxx> | |||
58 | #include <inputhdl.hxx> | |||
59 | #include <tabvwsh.hxx> | |||
60 | #include <document.hxx> | |||
61 | #include <docsh.hxx> | |||
62 | #include <appoptio.hxx> | |||
63 | #include <rangenam.hxx> | |||
64 | #include <rangeutl.hxx> | |||
65 | #include <docfunc.hxx> | |||
66 | #include <funcdesc.hxx> | |||
67 | #include <editeng/fontitem.hxx> | |||
68 | #include <AccessibleEditObject.hxx> | |||
69 | #include <AccessibleText.hxx> | |||
70 | #include <comphelper/lok.hxx> | |||
71 | #include <comphelper/string.hxx> | |||
72 | #include <com/sun/star/frame/XLayoutManager.hpp> | |||
73 | #include <helpids.h> | |||
74 | #include <output.hxx> | |||
75 | ||||
76 | namespace com::sun::star::accessibility { class XAccessible; } | |||
77 | ||||
78 | const long THESIZE = 1000000; // Should be more than enough! | |||
79 | const long INPUTLINE_INSET_MARGIN = 2; // Space between border and interior widgets of input line | |||
80 | const long LEFT_OFFSET = 5; // Left offset of input line | |||
81 | const long BUTTON_OFFSET = 2; // Space between input line and button to expand/collapse | |||
82 | const long MULTILINE_BUTTON_WIDTH = 20; // Width of the button which opens multiline dropdown | |||
83 | const long INPUTWIN_MULTILINES = 6; // Initial number of lines within multiline dropdown | |||
84 | const long TOOLBOX_WINDOW_HEIGHT = 22; // Height of toolbox window in pixels - TODO: The same on all systems? | |||
85 | const long POSITION_COMBOBOX_WIDTH = 18; // Width of position combobox in characters | |||
86 | ||||
87 | using com::sun::star::uno::Reference; | |||
88 | using com::sun::star::uno::UNO_QUERY; | |||
89 | ||||
90 | using com::sun::star::frame::XLayoutManager; | |||
91 | using com::sun::star::beans::XPropertySet; | |||
92 | ||||
93 | namespace { | |||
94 | ||||
95 | enum ScNameInputType | |||
96 | { | |||
97 | SC_NAME_INPUT_CELL, | |||
98 | SC_NAME_INPUT_RANGE, | |||
99 | SC_NAME_INPUT_NAMEDRANGE, | |||
100 | SC_NAME_INPUT_DATABASE, | |||
101 | SC_NAME_INPUT_ROW, | |||
102 | SC_NAME_INPUT_SHEET, | |||
103 | SC_NAME_INPUT_DEFINE, | |||
104 | SC_NAME_INPUT_BAD_NAME, | |||
105 | SC_NAME_INPUT_BAD_SELECTION, | |||
106 | SC_MANAGE_NAMES | |||
107 | }; | |||
108 | ||||
109 | } | |||
110 | ||||
111 | ScTextWndBase::ScTextWndBase( vcl::Window* pParent, WinBits nStyle ) | |||
112 | : Window ( pParent, nStyle ) | |||
113 | { | |||
114 | if ( IsNativeControlSupported( ControlType::Editbox, ControlPart::Entire ) ) | |||
115 | { | |||
116 | SetType( WindowType::CALCINPUTLINE ); | |||
117 | SetBorderStyle( WindowBorderStyle::NWF ); | |||
118 | } | |||
119 | } | |||
120 | ||||
121 | ||||
122 | SFX_IMPL_CHILDWINDOW_WITHID(ScInputWindowWrapper,FID_INPUTLINE_STATUS)std::unique_ptr<SfxChildWindow> ScInputWindowWrapper::CreateImpl ( vcl::Window *pParent, sal_uInt16 nId, SfxBindings *pBindings , SfxChildWinInfo* pInfo ) { return std::make_unique<ScInputWindowWrapper >(pParent, nId, pBindings, pInfo); } void ScInputWindowWrapper ::RegisterChildWindow (bool bVis, SfxModule *pMod, SfxChildWindowFlags nFlags) { auto pFact = std::make_unique<SfxChildWinFactory >( ScInputWindowWrapper::CreateImpl, ((26000 + 100)), (32767 *2 +1) ); pFact->aInfo.nFlags |= nFlags; pFact->aInfo. bVisible = bVis; SfxChildWindow::RegisterChildWindow(pMod, std ::move(pFact)); } sal_uInt16 ScInputWindowWrapper::GetChildWindowId () { return ((26000 + 100)); } | |||
| ||||
123 | ||||
124 | ScInputWindowWrapper::ScInputWindowWrapper( vcl::Window* pParentP, | |||
125 | sal_uInt16 nId, | |||
126 | SfxBindings* pBindings, | |||
127 | SfxChildWinInfo* /* pInfo */ ) | |||
128 | : SfxChildWindow( pParentP, nId ) | |||
129 | { | |||
130 | VclPtr<ScInputWindow> pWin = VclPtr<ScInputWindow>::Create( pParentP, pBindings ); | |||
131 | SetWindow( pWin ); | |||
132 | ||||
133 | pWin->Show(); | |||
134 | ||||
135 | pWin->SetSizePixel( pWin->CalcWindowSizePixel() ); | |||
136 | ||||
137 | SetAlignment(SfxChildAlignment::LOWESTTOP); | |||
138 | pBindings->Invalidate( FID_TOGGLEINPUTLINE((((((26000 + 200) + 20)) + 20)) + 1) ); | |||
139 | } | |||
140 | ||||
141 | /** | |||
142 | * GetInfo is disposed of if there's a SFX_IMPL_TOOLBOX! | |||
143 | */ | |||
144 | SfxChildWinInfo ScInputWindowWrapper::GetInfo() const | |||
145 | { | |||
146 | SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); | |||
147 | return aInfo; | |||
148 | } | |||
149 | ||||
150 | ||||
151 | static VclPtr<ScInputBarGroup> lcl_chooseRuntimeImpl( vcl::Window* pParent, const SfxBindings* pBind ) | |||
152 | { | |||
153 | ScTabViewShell* pViewSh = nullptr; | |||
154 | SfxDispatcher* pDisp = pBind->GetDispatcher(); | |||
155 | if ( pDisp ) | |||
156 | { | |||
157 | SfxViewFrame* pViewFrm = pDisp->GetFrame(); | |||
158 | if ( pViewFrm ) | |||
159 | pViewSh = dynamic_cast<ScTabViewShell*>( pViewFrm->GetViewShell() ); | |||
160 | } | |||
161 | ||||
162 | return VclPtr<ScInputBarGroup>::Create( pParent, pViewSh ); | |||
163 | } | |||
164 | ||||
165 | ScInputWindow::ScInputWindow( vcl::Window* pParent, const SfxBindings* pBind ) : | |||
166 | // With WB_CLIPCHILDREN otherwise we get flickering | |||
167 | ToolBox ( pParent, WinBits(WB_CLIPCHILDREN | WB_BORDER | WB_NOSHADOW) ), | |||
168 | aWndPos ( VclPtr<ScPosWnd>::Create(this) ), | |||
169 | pRuntimeWindow ( lcl_chooseRuntimeImpl( this, pBind ) ), | |||
170 | aTextWindow ( *pRuntimeWindow ), | |||
171 | pInputHdl ( nullptr ), | |||
172 | mpViewShell ( nullptr ), | |||
173 | mnMaxY (0), | |||
174 | bIsOkCancelMode ( false ), | |||
175 | bInResize ( false ) | |||
176 | { | |||
177 | // #i73615# don't rely on SfxViewShell::Current while constructing the input line | |||
178 | // (also for GetInputHdl below) | |||
179 | ScTabViewShell* pViewSh = nullptr; | |||
180 | SfxDispatcher* pDisp = pBind->GetDispatcher(); | |||
181 | if ( pDisp ) | |||
182 | { | |||
183 | SfxViewFrame* pViewFrm = pDisp->GetFrame(); | |||
184 | if ( pViewFrm ) | |||
185 | pViewSh = dynamic_cast<ScTabViewShell*>( pViewFrm->GetViewShell() ); | |||
186 | } | |||
187 | OSL_ENSURE( pViewSh, "no view shell for input window" )do { if (true && (!(pViewSh))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "187" ": "), "%s", "no view shell for input window"); } } while (false); | |||
188 | ||||
189 | mpViewShell = pViewSh; | |||
190 | ||||
191 | // Position window, 3 buttons, input window | |||
192 | if (!comphelper::LibreOfficeKit::isActive()) | |||
193 | { | |||
194 | InsertWindow (1, aWndPos.get(), ToolBoxItemBits::NONE, 0); | |||
195 | InsertSeparator (1); | |||
196 | InsertItem (SID_INPUT_FUNCTION((26000) + 47), Image(StockImage::Yes, RID_BMP_INPUT_FUNCTION"sc/res/sc26047.png"), ToolBoxItemBits::NONE, 2); | |||
197 | } | |||
198 | ||||
199 | const bool bIsLOKMobilePhone = mpViewShell && mpViewShell->isLOKMobilePhone(); | |||
200 | ||||
201 | // sigma and equal buttons | |||
202 | if (!bIsLOKMobilePhone) | |||
203 | { | |||
204 | InsertItem (SID_INPUT_SUM((26000) + 48), Image(StockImage::Yes, RID_BMP_INPUT_SUM"sc/res/sc26048.png"), ToolBoxItemBits::DROPDOWNONLY, 3); | |||
205 | InsertItem (SID_INPUT_EQUAL((26000) + 49), Image(StockImage::Yes, RID_BMP_INPUT_EQUAL"sc/res/sc26049.png"), ToolBoxItemBits::NONE, 4); | |||
206 | InsertItem (SID_INPUT_CANCEL((26000) + 50), Image(StockImage::Yes, RID_BMP_INPUT_CANCEL"sc/res/sc26050.png"), ToolBoxItemBits::NONE, 5); | |||
207 | InsertItem (SID_INPUT_OK((26000) + 51), Image(StockImage::Yes, RID_BMP_INPUT_OK"sc/res/sc26051.png"), ToolBoxItemBits::NONE, 6); | |||
208 | } | |||
209 | ||||
210 | InsertWindow (7, &aTextWindow, ToolBoxItemBits::NONE, 7); | |||
211 | SetDropdownClickHdl( LINK( this, ScInputWindow, DropdownClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<ScInputWindow *>(this), &ScInputWindow::LinkStubDropdownClickHdl)); | |||
212 | ||||
213 | if (!comphelper::LibreOfficeKit::isActive()) | |||
214 | { | |||
215 | aWndPos ->SetQuickHelpText(ScResId(SCSTR_QHELP_POSWNDreinterpret_cast<char const *>("SCSTR_QHELP_POSWND" "\004" u8"Name Box"))); | |||
216 | aWndPos ->SetHelpId (HID_INSWIN_POS"SC_HID_INSWIN_POS"); | |||
217 | } | |||
218 | aTextWindow.SetQuickHelpText(ScResId(SCSTR_QHELP_INPUTWNDreinterpret_cast<char const *>("SCSTR_QHELP_INPUTWND" "\004" u8"Input line"))); | |||
219 | aTextWindow.SetHelpId (HID_INSWIN_INPUT"SC_HID_INSWIN_INPUT"); | |||
220 | ||||
221 | if (!comphelper::LibreOfficeKit::isActive()) | |||
222 | { | |||
223 | // No SetHelpText: the helptexts come from the Help | |||
224 | SetItemText (SID_INPUT_FUNCTION((26000) + 47), ScResId(SCSTR_QHELP_BTNCALCreinterpret_cast<char const *>("SCSTR_QHELP_BTNCALC" "\004" u8"Function Wizard"))); | |||
225 | SetHelpId (SID_INPUT_FUNCTION((26000) + 47), HID_INSWIN_CALC"SC_HID_INSWIN_CALC"); | |||
226 | } | |||
227 | ||||
228 | // sigma and equal buttons | |||
229 | if (!bIsLOKMobilePhone) | |||
230 | { | |||
231 | SetItemText (SID_INPUT_SUM((26000) + 48), ScResId( SCSTR_QHELP_BTNSUMreinterpret_cast<char const *>("SCSTR_QHELP_BTNSUM" "\004" u8"Select Function") ) ); | |||
232 | SetHelpId (SID_INPUT_SUM((26000) + 48), HID_INSWIN_SUMME"SC_HID_INSWIN_SUMME"); | |||
233 | ||||
234 | SetItemText (SID_INPUT_EQUAL((26000) + 49), ScResId( SCSTR_QHELP_BTNEQUALreinterpret_cast<char const *>("SCSTR_QHELP_BTNEQUAL" "\004" u8"Formula") ) ); | |||
235 | SetHelpId (SID_INPUT_EQUAL((26000) + 49), HID_INSWIN_FUNC"SC_HID_INSWIN_FUNC"); | |||
236 | ||||
237 | SetItemText ( SID_INPUT_CANCEL((26000) + 50), ScResId( SCSTR_QHELP_BTNCANCELreinterpret_cast<char const *>("SCSTR_QHELP_BTNCANCEL" "\004" u8"Cancel") ) ); | |||
238 | SetHelpId ( SID_INPUT_CANCEL((26000) + 50), HID_INSWIN_CANCEL"SC_HID_INSWIN_CANCEL" ); | |||
239 | ||||
240 | SetItemText ( SID_INPUT_OK((26000) + 51), ScResId( SCSTR_QHELP_BTNOKreinterpret_cast<char const *>("SCSTR_QHELP_BTNOK" "\004" u8"Accept") ) ); | |||
241 | SetHelpId ( SID_INPUT_OK((26000) + 51), HID_INSWIN_OK"SC_HID_INSWIN_OK" ); | |||
242 | ||||
243 | EnableItem( SID_INPUT_CANCEL((26000) + 50), false ); | |||
244 | EnableItem( SID_INPUT_OK((26000) + 51), false ); | |||
245 | ||||
246 | HideItem( SID_INPUT_CANCEL((26000) + 50) ); | |||
247 | HideItem( SID_INPUT_OK((26000) + 51) ); | |||
248 | } | |||
249 | ||||
250 | SetHelpId( HID_SC_INPUTWIN"SC_HID_SC_INPUTWIN" ); // For the whole input row | |||
251 | ||||
252 | if (!comphelper::LibreOfficeKit::isActive()) | |||
253 | aWndPos ->Show(); | |||
254 | aTextWindow.Show(); | |||
255 | ||||
256 | pInputHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl( pViewSh, false ); // use own handler even if ref-handler is set | |||
257 | if (pInputHdl) | |||
258 | pInputHdl->SetInputWindow( this ); | |||
259 | ||||
260 | if (pInputHdl && !pInputHdl->GetFormString().isEmpty()) | |||
261 | { | |||
262 | // Switch over while the Function AutoPilot is active | |||
263 | // -> show content of the Function AutoPilot again | |||
264 | // Also show selection (remember at the InputHdl) | |||
265 | aTextWindow.SetTextString( pInputHdl->GetFormString() ); | |||
266 | } | |||
267 | else if (pInputHdl && pInputHdl->IsInputMode()) | |||
268 | { | |||
269 | // If the input row was hidden while editing (e.g. when editing a formula | |||
270 | // and then switching to another document or the help), display the text | |||
271 | // we just edited from the InputHandler | |||
272 | aTextWindow.SetTextString( pInputHdl->GetEditString() ); // Display text | |||
273 | if ( pInputHdl->IsTopMode() ) | |||
274 | pInputHdl->SetMode( SC_INPUT_TABLE ); // Focus ends up at the bottom anyways | |||
275 | } | |||
276 | else if (pViewSh) | |||
277 | { | |||
278 | // Don't stop editing in LOK a remote user might be editing. | |||
279 | const bool bStopEditing = !comphelper::LibreOfficeKit::isActive(); | |||
280 | pViewSh->UpdateInputHandler(true, bStopEditing); // Absolutely necessary update | |||
281 | } | |||
282 | ||||
283 | SetToolbarLayoutMode( ToolBoxLayoutMode::Locked ); | |||
284 | ||||
285 | SetAccessibleName(ScResId(STR_ACC_TOOLBAR_FORMULAreinterpret_cast<char const *>("STR_ACC_TOOLBAR_FORMULA" "\004" u8"Formula Tool Bar"))); | |||
286 | } | |||
287 | ||||
288 | ScInputWindow::~ScInputWindow() | |||
289 | { | |||
290 | disposeOnce(); | |||
291 | } | |||
292 | ||||
293 | void ScInputWindow::dispose() | |||
294 | { | |||
295 | bool bDown = !ScGlobal::xSysLocale; // after Clear? | |||
296 | ||||
297 | // if any view's input handler has a pointer to this input window, reset it | |||
298 | // (may be several ones, #74522#) | |||
299 | // member pInputHdl is not used here | |||
300 | ||||
301 | if ( !bDown ) | |||
302 | { | |||
303 | SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> ); | |||
304 | while ( pSh ) | |||
305 | { | |||
306 | ScInputHandler* pHdl = static_cast<ScTabViewShell*>(pSh)->GetInputHandler(); | |||
307 | if ( pHdl && pHdl->GetInputWindow() == this ) | |||
308 | { | |||
309 | pHdl->SetInputWindow( nullptr ); | |||
310 | pHdl->StopInputWinEngine( false ); // reset pTopView pointer | |||
311 | } | |||
312 | pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> ); | |||
313 | } | |||
314 | } | |||
315 | ||||
316 | if (comphelper::LibreOfficeKit::isActive()) | |||
317 | { | |||
318 | if(const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier()) | |||
319 | { | |||
320 | pNotifier->notifyWindow(GetLOKWindowId(), "close"); | |||
321 | ReleaseLOKNotifier(); | |||
322 | } | |||
323 | } | |||
324 | ||||
325 | pRuntimeWindow.disposeAndClear(); | |||
326 | aWndPos.disposeAndClear(); | |||
327 | ||||
328 | ToolBox::dispose(); | |||
329 | } | |||
330 | ||||
331 | void ScInputWindow::SetInputHandler( ScInputHandler* pNew ) | |||
332 | { | |||
333 | // Is called in the Activate of the View ... | |||
334 | if ( pNew != pInputHdl ) | |||
335 | { | |||
336 | // On Reload (last version) the pInputHdl is the InputHandler of the old, deleted | |||
337 | // ViewShell: so don't touch it here! | |||
338 | pInputHdl = pNew; | |||
339 | if (pInputHdl) | |||
340 | pInputHdl->SetInputWindow( this ); | |||
341 | } | |||
342 | } | |||
343 | ||||
344 | void ScInputWindow::Select() | |||
345 | { | |||
346 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
347 | ToolBox::Select(); | |||
348 | ||||
349 | switch ( GetCurItemId() ) | |||
350 | { | |||
351 | case SID_INPUT_FUNCTION((26000) + 47): | |||
352 | { | |||
353 | //! new method at ScModule to query if function autopilot is open | |||
354 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
355 | if ( pViewFrm && ( comphelper::LibreOfficeKit::isActive() || !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION((26000 + 100) + 52) ) ) ) | |||
356 | { | |||
357 | pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION((26000 + 100) + 52), | |||
358 | SfxCallMode::SYNCHRON | SfxCallMode::RECORD ); | |||
359 | ||||
360 | // The Toolbox will be disabled anyways, so we don't need to switch here, | |||
361 | // regardless whether it succeeded or not! | |||
362 | // SetOkCancelMode(); | |||
363 | } | |||
364 | } | |||
365 | break; | |||
366 | ||||
367 | case SID_INPUT_CANCEL((26000) + 50): | |||
368 | pScMod->InputCancelHandler(); | |||
369 | SetSumAssignMode(); | |||
370 | break; | |||
371 | ||||
372 | case SID_INPUT_OK((26000) + 51): | |||
373 | pScMod->InputEnterHandler(); | |||
374 | SetSumAssignMode(); | |||
375 | aTextWindow.Invalidate(); // Or else the Selection remains | |||
376 | break; | |||
377 | ||||
378 | case SID_INPUT_EQUAL((26000) + 49): | |||
379 | { | |||
380 | aTextWindow.StartEditEngine(); | |||
381 | if ( pScMod->IsEditMode() ) // Isn't if e.g. protected | |||
382 | { | |||
383 | aTextWindow.StartEditEngine(); | |||
384 | ||||
385 | sal_Int32 nStartPos = 1; | |||
386 | sal_Int32 nEndPos = 1; | |||
387 | ||||
388 | ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); | |||
389 | if ( pViewSh ) | |||
390 | { | |||
391 | const OUString& rString = aTextWindow.GetTextString(); | |||
392 | const sal_Int32 nLen = rString.getLength(); | |||
393 | ||||
394 | ScDocument& rDoc = pViewSh->GetViewData().GetDocument(); | |||
395 | CellType eCellType = rDoc.GetCellType( pViewSh->GetViewData().GetCurPos() ); | |||
396 | switch ( eCellType ) | |||
397 | { | |||
398 | case CELLTYPE_VALUE: | |||
399 | { | |||
400 | nEndPos = nLen + 1; | |||
401 | aTextWindow.SetTextString("=" + rString); | |||
402 | break; | |||
403 | } | |||
404 | case CELLTYPE_STRING: | |||
405 | case CELLTYPE_EDIT: | |||
406 | nStartPos = 0; | |||
407 | nEndPos = nLen; | |||
408 | break; | |||
409 | case CELLTYPE_FORMULA: | |||
410 | nEndPos = nLen; | |||
411 | break; | |||
412 | default: | |||
413 | aTextWindow.SetTextString("="); | |||
414 | break; | |||
415 | } | |||
416 | } | |||
417 | ||||
418 | EditView* pView = aTextWindow.GetEditView(); | |||
419 | if (pView) | |||
420 | { | |||
421 | if (comphelper::LibreOfficeKit::isActive()) | |||
422 | TextGrabFocus(); | |||
423 | pView->SetSelection( ESelection(0, nStartPos, 0, nEndPos) ); | |||
424 | pScMod->InputChanged(pView); | |||
425 | SetOkCancelMode(); | |||
426 | pView->SetEditEngineUpdateMode(true); | |||
427 | } | |||
428 | } | |||
429 | break; | |||
430 | } | |||
431 | } | |||
432 | } | |||
433 | ||||
434 | void ScInputWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) | |||
435 | { | |||
436 | if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isDialogPainting()) | |||
437 | return; | |||
438 | ||||
439 | ToolBox::Paint(rRenderContext, rRect); | |||
440 | ||||
441 | if (!comphelper::LibreOfficeKit::isActive()) | |||
442 | { | |||
443 | // draw a line at the bottom to distinguish that from the grid | |||
444 | // const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | |||
445 | // rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); | |||
446 | // Size aSize = GetSizePixel(); | |||
447 | // rRenderContext.DrawLine(Point(0, aSize.Height() - 1), | |||
448 | // Point(aSize.Width() - 1, aSize.Height() - 1)); | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | void ScInputWindow::PixelInvalidate(const tools::Rectangle* pRectangle) | |||
453 | { | |||
454 | if (comphelper::LibreOfficeKit::isDialogPainting() || !comphelper::LibreOfficeKit::isActive()) | |||
455 | return; | |||
456 | ||||
457 | if (pRectangle) | |||
458 | { | |||
459 | const Point aPos(pRectangle->getX() - GetOutOffXPixel(), pRectangle->getY() - GetOutOffYPixel()); | |||
460 | const tools::Rectangle aRect(aPos, pRectangle->GetSize()); | |||
461 | Window::PixelInvalidate(&aRect); | |||
462 | } | |||
463 | else | |||
464 | { | |||
465 | Window::PixelInvalidate(nullptr); | |||
466 | } | |||
467 | } | |||
468 | ||||
469 | void ScInputWindow::SetSizePixel( const Size& rNewSize ) | |||
470 | { | |||
471 | const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier(); | |||
472 | if (pNotifier) | |||
473 | { | |||
474 | if (vcl::Window* pFrameWindowImpl = GetParent()) | |||
475 | { | |||
476 | if (vcl::Window* pWorkWindow = pFrameWindowImpl->GetParent()) | |||
477 | { | |||
478 | if (vcl::Window* pImplBorderWindow = pWorkWindow->GetParent()) | |||
479 | { | |||
480 | Size aSize = pImplBorderWindow->GetSizePixel(); | |||
481 | aSize.setWidth(rNewSize.getWidth()); | |||
482 | pImplBorderWindow->SetSizePixel(aSize); | |||
483 | } | |||
484 | } | |||
485 | } | |||
486 | } | |||
487 | ||||
488 | ToolBox::SetSizePixel(rNewSize); | |||
489 | } | |||
490 | ||||
491 | void ScInputWindow::Resize() | |||
492 | { | |||
493 | ToolBox::Resize(); | |||
494 | aTextWindow.Resize(); | |||
495 | Size aSize = GetSizePixel(); | |||
496 | aSize.setHeight(CalcWindowSizePixel().Height() + 1); | |||
497 | ScInputBarGroup* pGroupBar = pRuntimeWindow.get(); | |||
498 | if (pGroupBar) | |||
499 | { | |||
500 | // To ensure smooth display and prevent the items in the toolbar being | |||
501 | // repositioned (vertically) we lock the vertical positioning of the toolbox | |||
502 | // items when we are displaying > 1 line. | |||
503 | // So, we need to adjust the height of the toolbox accordingly. If we don't | |||
504 | // then the largest item (e.g. the GroupBar window) will actually be | |||
505 | // positioned such that the toolbar will cut off the bottom of that item | |||
506 | if (pGroupBar->GetNumLines() > 1) | |||
507 | { | |||
508 | Size aGroupBarSize = pGroupBar->GetSizePixel(); | |||
509 | aSize.setHeight(aGroupBarSize.Height() + 2 * (pGroupBar->GetVertOffset() + 1)); | |||
510 | } | |||
511 | } | |||
512 | SetSizePixel(aSize); | |||
513 | ||||
514 | if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier()) | |||
515 | { | |||
516 | std::vector<vcl::LOKPayloadItem> aItems; | |||
517 | aItems.emplace_back(std::make_pair("position", Point(GetOutOffXPixel(), GetOutOffYPixel()).toString())); | |||
518 | aItems.emplace_back("size", GetSizePixel().toString()); | |||
519 | aItems.emplace_back("lines", OString::number(aTextWindow.GetNumLines())); | |||
520 | pNotifier->notifyWindow(GetLOKWindowId(), "size_changed", aItems); | |||
521 | } | |||
522 | ||||
523 | Invalidate(); | |||
524 | } | |||
525 | ||||
526 | void ScInputWindow::NotifyLOKClient() | |||
527 | { | |||
528 | if (comphelper::LibreOfficeKit::isActive() && !GetLOKNotifier() && mpViewShell) | |||
529 | SetLOKNotifier(mpViewShell); | |||
530 | ||||
531 | const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier(); | |||
532 | if (!pNotifier) | |||
533 | return; | |||
534 | ||||
535 | Size aSize = GetSizePixel(); | |||
536 | if (!aSize.IsEmpty()) | |||
537 | { | |||
538 | std::vector<vcl::LOKPayloadItem> aItems; | |||
539 | aItems.emplace_back("type", "calc-input-win"); | |||
540 | aItems.emplace_back(std::make_pair("position", Point(GetOutOffXPixel(), GetOutOffYPixel()).toString())); | |||
541 | aItems.emplace_back(std::make_pair("size", aSize.toString())); | |||
542 | aItems.emplace_back("lines", OString::number(aTextWindow.GetNumLines())); | |||
543 | pNotifier->notifyWindow(GetLOKWindowId(), "created", aItems); | |||
544 | } | |||
545 | } | |||
546 | ||||
547 | void ScInputWindow::SetFuncString( const OUString& rString, bool bDoEdit ) | |||
548 | { | |||
549 | //! new method at ScModule to query if function autopilot is open | |||
550 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
551 | EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION((26000 + 100) + 52) ) ); | |||
552 | aTextWindow.StartEditEngine(); | |||
553 | ||||
554 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
555 | if ( !pScMod->IsEditMode() ) | |||
556 | return; | |||
557 | ||||
558 | if ( bDoEdit ) | |||
559 | aTextWindow.GrabFocus(); | |||
560 | aTextWindow.SetTextString( rString ); | |||
561 | EditView* pView = aTextWindow.GetEditView(); | |||
562 | if (!pView) | |||
563 | return; | |||
564 | ||||
565 | sal_Int32 nLen = rString.getLength(); | |||
566 | ||||
567 | if ( nLen > 0 ) | |||
568 | { | |||
569 | nLen--; | |||
570 | pView->SetSelection( ESelection( 0, nLen, 0, nLen ) ); | |||
571 | } | |||
572 | ||||
573 | pScMod->InputChanged(pView); | |||
574 | if ( bDoEdit ) | |||
575 | SetOkCancelMode(); // Not the case if immediately followed by Enter/Cancel | |||
576 | ||||
577 | pView->SetEditEngineUpdateMode(true); | |||
578 | } | |||
579 | ||||
580 | void ScInputWindow::SetPosString( const OUString& rStr ) | |||
581 | { | |||
582 | aWndPos->SetPos( rStr ); | |||
583 | } | |||
584 | ||||
585 | void ScInputWindow::SetTextString( const OUString& rString ) | |||
586 | { | |||
587 | if (rString.getLength() <= 32767) | |||
588 | aTextWindow.SetTextString(rString); | |||
589 | else | |||
590 | aTextWindow.SetTextString(rString.copy(0, 32767)); | |||
591 | } | |||
592 | ||||
593 | void ScInputWindow::SetOkCancelMode() | |||
594 | { | |||
595 | //! new method at ScModule to query if function autopilot is open | |||
596 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
597 | EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION((26000 + 100) + 52) ) ); | |||
598 | ||||
599 | if (bIsOkCancelMode) | |||
600 | return; | |||
601 | ||||
602 | EnableItem ( SID_INPUT_SUM((26000) + 48), false ); | |||
603 | EnableItem ( SID_INPUT_EQUAL((26000) + 49), false ); | |||
604 | HideItem ( SID_INPUT_SUM((26000) + 48) ); | |||
605 | HideItem ( SID_INPUT_EQUAL((26000) + 49) ); | |||
606 | ||||
607 | ShowItem ( SID_INPUT_CANCEL((26000) + 50), true ); | |||
608 | ShowItem ( SID_INPUT_OK((26000) + 51), true ); | |||
609 | EnableItem ( SID_INPUT_CANCEL((26000) + 50), true ); | |||
610 | EnableItem ( SID_INPUT_OK((26000) + 51), true ); | |||
611 | ||||
612 | bIsOkCancelMode = true; | |||
613 | } | |||
614 | ||||
615 | void ScInputWindow::SetSumAssignMode() | |||
616 | { | |||
617 | //! new method at ScModule to query if function autopilot is open | |||
618 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
619 | EnableButtons( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION((26000 + 100) + 52) ) ); | |||
620 | ||||
621 | if (!bIsOkCancelMode) | |||
622 | return; | |||
623 | ||||
624 | EnableItem ( SID_INPUT_CANCEL((26000) + 50), false ); | |||
625 | EnableItem ( SID_INPUT_OK((26000) + 51), false ); | |||
626 | HideItem ( SID_INPUT_CANCEL((26000) + 50) ); | |||
627 | HideItem ( SID_INPUT_OK((26000) + 51) ); | |||
628 | ||||
629 | ShowItem ( SID_INPUT_SUM((26000) + 48), true ); | |||
630 | ShowItem ( SID_INPUT_EQUAL((26000) + 49), true ); | |||
631 | EnableItem ( SID_INPUT_SUM((26000) + 48), true ); | |||
632 | EnableItem ( SID_INPUT_EQUAL((26000) + 49), true ); | |||
633 | ||||
634 | bIsOkCancelMode = false; | |||
635 | ||||
636 | SetFormulaMode(false); // No editing -> no formula | |||
637 | } | |||
638 | ||||
639 | void ScInputWindow::SetFormulaMode( bool bSet ) | |||
640 | { | |||
641 | aWndPos->SetFormulaMode(bSet); | |||
642 | aTextWindow.SetFormulaMode(bSet); | |||
643 | } | |||
644 | ||||
645 | bool ScInputWindow::IsInputActive() | |||
646 | { | |||
647 | return aTextWindow.IsInputActive(); | |||
648 | } | |||
649 | ||||
650 | EditView* ScInputWindow::GetEditView() | |||
651 | { | |||
652 | return aTextWindow.GetEditView(); | |||
653 | } | |||
654 | ||||
655 | void ScInputWindow::MakeDialogEditView() | |||
656 | { | |||
657 | aTextWindow.MakeDialogEditView(); | |||
658 | } | |||
659 | ||||
660 | void ScInputWindow::StopEditEngine( bool bAll ) | |||
661 | { | |||
662 | aTextWindow.StopEditEngine( bAll ); | |||
663 | } | |||
664 | ||||
665 | void ScInputWindow::TextGrabFocus() | |||
666 | { | |||
667 | aTextWindow.TextGrabFocus(); | |||
668 | } | |||
669 | ||||
670 | void ScInputWindow::TextInvalidate() | |||
671 | { | |||
672 | aTextWindow.Invalidate(); | |||
673 | } | |||
674 | ||||
675 | void ScInputWindow::SwitchToTextWin() | |||
676 | { | |||
677 | // used for shift-ctrl-F2 | |||
678 | ||||
679 | aTextWindow.StartEditEngine(); | |||
680 | if ( SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->IsEditMode() ) | |||
681 | { | |||
682 | aTextWindow.TextGrabFocus(); | |||
683 | EditView* pView = aTextWindow.GetEditView(); | |||
684 | if (pView) | |||
685 | { | |||
686 | sal_Int32 nPara = pView->GetEditEngine()->GetParagraphCount() ? ( pView->GetEditEngine()->GetParagraphCount() - 1 ) : 0; | |||
687 | sal_Int32 nLen = pView->GetEditEngine()->GetTextLen( nPara ); | |||
688 | ESelection aSel( nPara, nLen, nPara, nLen ); | |||
689 | pView->SetSelection( aSel ); // set cursor to end of text | |||
690 | } | |||
691 | } | |||
692 | } | |||
693 | ||||
694 | void ScInputWindow::PosGrabFocus() | |||
695 | { | |||
696 | aWndPos->GrabFocus(); | |||
697 | } | |||
698 | ||||
699 | void ScInputWindow::EnableButtons( bool bEnable ) | |||
700 | { | |||
701 | // when enabling buttons, always also enable the input window itself | |||
702 | if ( bEnable && !IsEnabled() ) | |||
703 | Enable(); | |||
704 | ||||
705 | EnableItem( SID_INPUT_FUNCTION((26000) + 47), bEnable ); | |||
706 | EnableItem( bIsOkCancelMode ? SID_INPUT_CANCEL((26000) + 50) : SID_INPUT_SUM((26000) + 48), bEnable ); | |||
707 | EnableItem( bIsOkCancelMode ? SID_INPUT_OK((26000) + 51) : SID_INPUT_EQUAL((26000) + 49), bEnable ); | |||
708 | // Invalidate(); | |||
709 | } | |||
710 | ||||
711 | void ScInputWindow::StateChanged( StateChangedType nType ) | |||
712 | { | |||
713 | ToolBox::StateChanged( nType ); | |||
714 | ||||
715 | if ( nType == StateChangedType::InitShow ) Resize(); | |||
716 | } | |||
717 | ||||
718 | void ScInputWindow::DataChanged( const DataChangedEvent& rDCEvt ) | |||
719 | { | |||
720 | if ( rDCEvt.GetType() == DataChangedEventType::SETTINGS && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) | |||
721 | { | |||
722 | // update item images | |||
723 | SetItemImage(SID_INPUT_FUNCTION((26000) + 47), Image(StockImage::Yes, RID_BMP_INPUT_FUNCTION"sc/res/sc26047.png")); | |||
724 | if ( bIsOkCancelMode ) | |||
725 | { | |||
726 | SetItemImage(SID_INPUT_CANCEL((26000) + 50), Image(StockImage::Yes, RID_BMP_INPUT_CANCEL"sc/res/sc26050.png")); | |||
727 | SetItemImage(SID_INPUT_OK((26000) + 51), Image(StockImage::Yes, RID_BMP_INPUT_OK"sc/res/sc26051.png")); | |||
728 | } | |||
729 | else | |||
730 | { | |||
731 | SetItemImage(SID_INPUT_SUM((26000) + 48), Image(StockImage::Yes, RID_BMP_INPUT_SUM"sc/res/sc26048.png")); | |||
732 | SetItemImage(SID_INPUT_EQUAL((26000) + 49), Image(StockImage::Yes, RID_BMP_INPUT_EQUAL"sc/res/sc26049.png")); | |||
733 | } | |||
734 | } | |||
735 | ||||
736 | ToolBox::DataChanged( rDCEvt ); | |||
737 | } | |||
738 | ||||
739 | bool ScInputWindow::IsPointerAtResizePos() | |||
740 | { | |||
741 | return GetOutputSizePixel().Height() - GetPointerPosPixel().Y() <= 4; | |||
742 | } | |||
743 | ||||
744 | void ScInputWindow::MouseMove( const MouseEvent& rMEvt ) | |||
745 | { | |||
746 | Point aPosPixel = GetPointerPosPixel(); | |||
747 | ||||
748 | ScInputBarGroup* pGroupBar = pRuntimeWindow.get(); | |||
749 | ||||
750 | if (bInResize || IsPointerAtResizePos()) | |||
751 | SetPointer(PointerStyle::WindowSSize); | |||
752 | else | |||
753 | SetPointer(PointerStyle::Arrow); | |||
754 | ||||
755 | if (bInResize) | |||
756 | { | |||
757 | // detect direction | |||
758 | long nResizeThreshold = long(TOOLBOX_WINDOW_HEIGHT * 0.7); | |||
759 | bool bResetPointerPos = false; | |||
760 | ||||
761 | // Detect attempt to expand toolbar too much | |||
762 | if (aPosPixel.Y() >= mnMaxY) | |||
763 | { | |||
764 | bResetPointerPos = true; | |||
765 | aPosPixel.setY( mnMaxY ); | |||
766 | } // or expanding down | |||
767 | else if (GetOutputSizePixel().Height() - aPosPixel.Y() < -nResizeThreshold) | |||
768 | { | |||
769 | pGroupBar->IncrementVerticalSize(); | |||
770 | bResetPointerPos = true; | |||
771 | } // or shrinking up | |||
772 | else if ((GetOutputSizePixel().Height() - aPosPixel.Y()) > nResizeThreshold) | |||
773 | { | |||
774 | bResetPointerPos = true; | |||
775 | pGroupBar->DecrementVerticalSize(); | |||
776 | } | |||
777 | ||||
778 | if (bResetPointerPos) | |||
779 | { | |||
780 | aPosPixel.setY( GetOutputSizePixel().Height() ); | |||
781 | SetPointerPosPixel(aPosPixel); | |||
782 | } | |||
783 | } | |||
784 | ||||
785 | ToolBox::MouseMove(rMEvt); | |||
786 | } | |||
787 | ||||
788 | void ScInputWindow::MouseButtonDown( const MouseEvent& rMEvt ) | |||
789 | { | |||
790 | if (rMEvt.IsLeft()) | |||
791 | { | |||
792 | if (IsPointerAtResizePos()) | |||
793 | { | |||
794 | // Don't leave the mouse pointer leave *this* window | |||
795 | CaptureMouse(); | |||
796 | bInResize = true; | |||
797 | ||||
798 | // find the height of the gridwin, we don't want to be | |||
799 | // able to expand the toolbar too far so we need to | |||
800 | // calculate an upper limit | |||
801 | // I'd prefer to leave at least a single column header and a | |||
802 | // row but I don't know how to get that value in pixels. | |||
803 | // Use TOOLBOX_WINDOW_HEIGHT for the moment | |||
804 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
805 | mnMaxY = GetOutputSizePixel().Height() + (pViewSh->GetGridHeight(SC_SPLIT_TOP) | |||
806 | + pViewSh->GetGridHeight(SC_SPLIT_BOTTOM)) - TOOLBOX_WINDOW_HEIGHT; | |||
807 | } | |||
808 | } | |||
809 | ||||
810 | ToolBox::MouseButtonDown( rMEvt ); | |||
811 | } | |||
812 | void ScInputWindow::MouseButtonUp( const MouseEvent& rMEvt ) | |||
813 | { | |||
814 | ReleaseMouse(); | |||
815 | if ( rMEvt.IsLeft() ) | |||
816 | { | |||
817 | bInResize = false; | |||
818 | mnMaxY = 0; | |||
819 | } | |||
820 | ||||
821 | ToolBox::MouseButtonUp( rMEvt ); | |||
822 | } | |||
823 | ||||
824 | void ScInputWindow::AutoSum( bool& bRangeFinder, bool& bSubTotal, OpCode eCode ) | |||
825 | { | |||
826 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
827 | ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); | |||
828 | if ( !pViewSh ) | |||
829 | return; | |||
830 | ||||
831 | const OUString aFormula = pViewSh->DoAutoSum(bRangeFinder, bSubTotal, eCode); | |||
832 | if ( aFormula.isEmpty() ) | |||
833 | return; | |||
834 | ||||
835 | SetFuncString( aFormula ); | |||
836 | const sal_Int32 aOpen = aFormula.indexOf('('); | |||
837 | const sal_Int32 aLen = aFormula.getLength(); | |||
838 | if (!(bRangeFinder && pScMod->IsEditMode())) | |||
839 | return; | |||
840 | ||||
841 | ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh ); | |||
842 | if ( !pHdl ) | |||
843 | return; | |||
844 | ||||
845 | pHdl->InitRangeFinder( aFormula ); | |||
846 | ||||
847 | //! SetSelection at the InputHandler? | |||
848 | //! Set bSelIsRef? | |||
849 | if ( aOpen != -1 && aLen > aOpen ) | |||
850 | { | |||
851 | ESelection aSel( 0, aOpen + (bSubTotal ? 3 : 1), 0, aLen-1 ); | |||
852 | EditView* pTableView = pHdl->GetTableView(); | |||
853 | if ( pTableView ) | |||
854 | pTableView->SetSelection( aSel ); | |||
855 | EditView* pTopView = pHdl->GetTopView(); | |||
856 | if ( pTopView ) | |||
857 | pTopView->SetSelection( aSel ); | |||
858 | } | |||
859 | } | |||
860 | ||||
861 | ScInputBarGroup::ScInputBarGroup(vcl::Window* pParent, ScTabViewShell* pViewSh) | |||
862 | : ScTextWndBase(pParent, WinBits(WB_HIDE | WB_TABSTOP)), | |||
863 | maTextWndGroup(VclPtr<ScTextWndGroup>::Create(this, pViewSh)), | |||
864 | maButton(VclPtr<PushButton>::Create(this, WB_TABSTOP | WB_FLATBUTTON | WB_SMALLSTYLE | WB_NOPOINTERFOCUS | WB_CENTER | WB_VCENTER)), | |||
865 | mnVertOffset(0) | |||
866 | { | |||
867 | maTextWndGroup->Show(); | |||
868 | Size aSize(MULTILINE_BUTTON_WIDTH, maTextWndGroup->GetPixelHeightForLines(1)); | |||
869 | maButton->SetClickHdl(LINK(this, ScInputBarGroup, ClickHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScInputBarGroup *>(this), &ScInputBarGroup::LinkStubClickHdl)); | |||
870 | maButton->SetSizePixel(aSize); | |||
871 | maButton->Enable(); | |||
872 | maButton->SetSymbol(SymbolType::SPIN_DOWN); | |||
873 | maButton->SetQuickHelpText(ScResId(SCSTR_QHELP_EXPAND_FORMULAreinterpret_cast<char const *>("SCSTR_QHELP_EXPAND_FORMULA" "\004" u8"Expand Formula Bar"))); | |||
874 | // disable the multiline toggle on the mobile phones | |||
875 | const SfxViewShell* pViewShell = SfxViewShell::Current(); | |||
876 | if (!comphelper::LibreOfficeKit::isActive() || !(pViewShell && pViewShell->isLOKMobilePhone())) | |||
877 | maButton->Show(); | |||
878 | } | |||
879 | ||||
880 | ScInputBarGroup::~ScInputBarGroup() | |||
881 | { | |||
882 | disposeOnce(); | |||
883 | } | |||
884 | ||||
885 | void ScInputBarGroup::dispose() | |||
886 | { | |||
887 | maTextWndGroup.disposeAndClear(); | |||
888 | maButton.disposeAndClear(); | |||
889 | ScTextWndBase::dispose(); | |||
890 | } | |||
891 | ||||
892 | void ScInputBarGroup::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData ) | |||
893 | { | |||
894 | maTextWndGroup->InsertAccessibleTextData(rTextData); | |||
895 | } | |||
896 | ||||
897 | void ScInputBarGroup::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData ) | |||
898 | { | |||
899 | maTextWndGroup->RemoveAccessibleTextData(rTextData); | |||
900 | } | |||
901 | ||||
902 | const OUString& ScInputBarGroup::GetTextString() const | |||
903 | { | |||
904 | return maTextWndGroup->GetTextString(); | |||
905 | } | |||
906 | ||||
907 | void ScInputBarGroup::SetTextString( const OUString& rString ) | |||
908 | { | |||
909 | maTextWndGroup->SetTextString(rString); | |||
910 | } | |||
911 | ||||
912 | void ScInputBarGroup::Resize() | |||
913 | { | |||
914 | vcl::Window* pWindow = GetParent(); | |||
915 | ScInputWindow *pParent; | |||
916 | pParent = dynamic_cast<ScInputWindow*>(pWindow); | |||
917 | if (pParent == nullptr) | |||
918 | { | |||
919 | OSL_FAIL("The parent window pointer pParent is null")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "919" ": "), "%s", "The parent window pointer pParent is null" ); } } while (false); | |||
920 | return; | |||
921 | } | |||
922 | Size aSize = GetSizePixel(); | |||
923 | //(-10) to allow margin between sidebar and formulabar | |||
924 | long margin = (comphelper::LibreOfficeKit::isActive()) ? 10 : 0; | |||
925 | aSize.setWidth(pParent->GetSizePixel().Width() - GetPosPixel().X() - LEFT_OFFSET - margin); | |||
926 | aSize.setHeight(maTextWndGroup->GetPixelHeightForLines(maTextWndGroup->GetNumLines())); | |||
927 | SetSizePixel(aSize); | |||
928 | ||||
929 | long nButtonWidth = maButton->IsVisible()? maButton->GetSizePixel().Width() + BUTTON_OFFSET: 0; | |||
930 | aSize.setWidth(aSize.Width() - nButtonWidth); | |||
931 | maTextWndGroup->SetSizePixel(aSize); | |||
932 | maTextWndGroup->Resize(); | |||
933 | ||||
934 | if (maTextWndGroup->GetNumLines() > 1) | |||
935 | { | |||
936 | maButton->SetSymbol( SymbolType::SPIN_UP ); | |||
937 | maButton->SetQuickHelpText(ScResId( SCSTR_QHELP_COLLAPSE_FORMULAreinterpret_cast<char const *>("SCSTR_QHELP_COLLAPSE_FORMULA" "\004" u8"Collapse Formula Bar"))); | |||
938 | } | |||
939 | else | |||
940 | { | |||
941 | maButton->SetSymbol( SymbolType::SPIN_DOWN ); | |||
942 | maButton->SetQuickHelpText(ScResId( SCSTR_QHELP_EXPAND_FORMULAreinterpret_cast<char const *>("SCSTR_QHELP_EXPAND_FORMULA" "\004" u8"Expand Formula Bar"))); | |||
943 | } | |||
944 | ||||
945 | maButton->SetPosPixel(Point(aSize.Width(), 0)); | |||
946 | Invalidate(); | |||
947 | } | |||
948 | ||||
949 | void ScInputBarGroup::StopEditEngine(bool bAll) | |||
950 | { | |||
951 | maTextWndGroup->StopEditEngine(bAll); | |||
952 | } | |||
953 | ||||
954 | void ScInputBarGroup::StartEditEngine() | |||
955 | { | |||
956 | maTextWndGroup->StartEditEngine(); | |||
957 | } | |||
958 | ||||
959 | void ScInputBarGroup::MakeDialogEditView() | |||
960 | { | |||
961 | maTextWndGroup->MakeDialogEditView(); | |||
962 | } | |||
963 | ||||
964 | EditView* ScInputBarGroup::GetEditView() | |||
965 | { | |||
966 | return maTextWndGroup->GetEditView(); | |||
967 | } | |||
968 | ||||
969 | bool ScInputBarGroup::HasEditView() const | |||
970 | { | |||
971 | return maTextWndGroup->HasEditView(); | |||
972 | } | |||
973 | ||||
974 | bool ScInputBarGroup::IsInputActive() | |||
975 | { | |||
976 | return maTextWndGroup->IsInputActive(); | |||
977 | } | |||
978 | ||||
979 | void ScInputBarGroup::SetFormulaMode(bool bSet) | |||
980 | { | |||
981 | maTextWndGroup->SetFormulaMode(bSet); | |||
982 | } | |||
983 | ||||
984 | void ScInputBarGroup::IncrementVerticalSize() | |||
985 | { | |||
986 | maTextWndGroup->SetNumLines(maTextWndGroup->GetNumLines() + 1); | |||
987 | TriggerToolboxLayout(); | |||
988 | } | |||
989 | ||||
990 | void ScInputBarGroup::DecrementVerticalSize() | |||
991 | { | |||
992 | if (maTextWndGroup->GetNumLines() > 1) | |||
993 | { | |||
994 | maTextWndGroup->SetNumLines(maTextWndGroup->GetNumLines() - 1); | |||
995 | TriggerToolboxLayout(); | |||
996 | } | |||
997 | } | |||
998 | ||||
999 | IMPL_LINK( ScInputWindow, MenuHdl, Menu *, pMenu, bool )bool ScInputWindow::LinkStubMenuHdl(void * instance, Menu * data ) { return static_cast<ScInputWindow *>(instance)->MenuHdl (data); } bool ScInputWindow::MenuHdl(Menu * pMenu) | |||
1000 | { | |||
1001 | OString aCommand = pMenu->GetCurItemIdent(); | |||
1002 | if (!aCommand.isEmpty()) | |||
1003 | { | |||
1004 | bool bSubTotal = false; | |||
1005 | bool bRangeFinder = false; | |||
1006 | OpCode eCode = ocSum; | |||
1007 | if ( aCommand == "sum" ) | |||
1008 | { | |||
1009 | eCode = ocSum; | |||
1010 | } | |||
1011 | else if ( aCommand == "average" ) | |||
1012 | { | |||
1013 | eCode = ocAverage; | |||
1014 | } | |||
1015 | else if ( aCommand == "max" ) | |||
1016 | { | |||
1017 | eCode = ocMax; | |||
1018 | } | |||
1019 | else if ( aCommand == "min" ) | |||
1020 | { | |||
1021 | eCode = ocMin; | |||
1022 | } | |||
1023 | else if ( aCommand == "count" ) | |||
1024 | { | |||
1025 | eCode = ocCount; | |||
1026 | } | |||
1027 | ||||
1028 | AutoSum( bRangeFinder, bSubTotal, eCode ); | |||
1029 | } | |||
1030 | return false; | |||
1031 | } | |||
1032 | ||||
1033 | IMPL_LINK_NOARG(ScInputWindow, DropdownClickHdl, ToolBox *, void)void ScInputWindow::LinkStubDropdownClickHdl(void * instance, ToolBox * data) { return static_cast<ScInputWindow *>( instance)->DropdownClickHdl(data); } void ScInputWindow::DropdownClickHdl (__attribute__ ((unused)) ToolBox *) | |||
1034 | { | |||
1035 | sal_uInt16 nCurID = GetCurItemId(); | |||
1036 | EndSelection(); | |||
1037 | if (nCurID == SID_INPUT_SUM((26000) + 48)) | |||
1038 | { | |||
1039 | VclBuilder aBuilder(nullptr, AllSettings::GetUIRootDir(), "modules/scalc/ui/autosum.ui", ""); | |||
1040 | VclPtr<PopupMenu> aPopMenu(aBuilder.get_menu("menu")); | |||
1041 | aPopMenu->SetSelectHdl(LINK(this, ScInputWindow, MenuHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScInputWindow *>(this), &ScInputWindow::LinkStubMenuHdl)); | |||
1042 | aPopMenu->Execute(this, GetItemRect(SID_INPUT_SUM((26000) + 48)), PopupMenuFlags::NoMouseUpClose); | |||
1043 | } | |||
1044 | } | |||
1045 | ||||
1046 | IMPL_LINK_NOARG(ScInputBarGroup, ClickHdl, Button*, void)void ScInputBarGroup::LinkStubClickHdl(void * instance, Button * data) { return static_cast<ScInputBarGroup *>(instance )->ClickHdl(data); } void ScInputBarGroup::ClickHdl(__attribute__ ((unused)) Button*) | |||
1047 | { | |||
1048 | vcl::Window* w = GetParent(); | |||
1049 | ScInputWindow* pParent; | |||
1050 | pParent = dynamic_cast<ScInputWindow*>(w); | |||
1051 | ||||
1052 | if (pParent == nullptr) | |||
1053 | { | |||
1054 | OSL_FAIL("The parent window pointer pParent is null")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "1054" ": "), "%s", "The parent window pointer pParent is null" ); } } while (false); | |||
1055 | return; | |||
1056 | } | |||
1057 | if (maTextWndGroup->GetNumLines() > 1) | |||
1058 | { | |||
1059 | maTextWndGroup->SetNumLines(1); | |||
1060 | } | |||
1061 | else | |||
1062 | { | |||
1063 | maTextWndGroup->SetNumLines(maTextWndGroup->GetLastNumExpandedLines()); | |||
1064 | } | |||
1065 | TriggerToolboxLayout(); | |||
1066 | ||||
1067 | // Restore focus to input line(s) if necessary | |||
1068 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(); | |||
1069 | if ( pHdl && pHdl->IsTopMode() ) | |||
1070 | maTextWndGroup->GrabFocus(); | |||
1071 | } | |||
1072 | ||||
1073 | void ScInputBarGroup::TriggerToolboxLayout() | |||
1074 | { | |||
1075 | vcl::Window *w=GetParent(); | |||
1076 | ScInputWindow &rParent = dynamic_cast<ScInputWindow&>(*w); | |||
1077 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
1078 | ||||
1079 | // Capture the vertical position of this window in the toolbar, when we increase | |||
1080 | // the size of the toolbar to accommodate expanded line input we need to take this | |||
1081 | // into account | |||
1082 | if ( !mnVertOffset ) | |||
1083 | mnVertOffset = rParent.GetItemPosRect( rParent.GetItemCount() - 1 ).Top(); | |||
1084 | ||||
1085 | if ( !pViewFrm ) | |||
1086 | return; | |||
1087 | ||||
1088 | Reference< css::beans::XPropertySet > xPropSet( pViewFrm->GetFrame().GetFrameInterface(), UNO_QUERY ); | |||
1089 | Reference< css::frame::XLayoutManager > xLayoutManager; | |||
1090 | ||||
1091 | if ( xPropSet.is() ) | |||
1092 | { | |||
1093 | css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager"); | |||
1094 | aValue >>= xLayoutManager; | |||
1095 | } | |||
1096 | ||||
1097 | if ( !xLayoutManager.is() ) | |||
1098 | return; | |||
1099 | ||||
1100 | xLayoutManager->lock(); | |||
1101 | DataChangedEvent aFakeUpdate( DataChangedEventType::SETTINGS, nullptr, AllSettingsFlags::STYLE ); | |||
1102 | ||||
1103 | // this basically will trigger the repositioning of the | |||
1104 | // items in the toolbar from ImplFormat ( which is controlled by | |||
1105 | // mnWinHeight ) which in turn is updated in ImplCalcItem which is | |||
1106 | // controlled by mbCalc. Additionally the ImplFormat above is | |||
1107 | // controlled via mbFormat. It seems the easiest way to get these | |||
1108 | // booleans set is to send in the fake event below. | |||
1109 | rParent.DataChanged( aFakeUpdate); | |||
1110 | ||||
1111 | // highest item in toolbar will have been calculated via the | |||
1112 | // event above. Call resize on InputBar to pick up the height | |||
1113 | // change | |||
1114 | rParent.Resize(); | |||
1115 | ||||
1116 | // unlock relayouts the toolbars in the 4 quadrants | |||
1117 | xLayoutManager->unlock(); | |||
1118 | } | |||
1119 | ||||
1120 | void ScInputBarGroup::TextGrabFocus() | |||
1121 | { | |||
1122 | maTextWndGroup->TextGrabFocus(); | |||
1123 | } | |||
1124 | ||||
1125 | constexpr long gnBorderWidth = INPUTLINE_INSET_MARGIN + 1; | |||
1126 | constexpr long gnBorderHeight = INPUTLINE_INSET_MARGIN + 1; | |||
1127 | ||||
1128 | ScTextWndGroup::ScTextWndGroup(vcl::Window* pParent, ScTabViewShell* pViewSh) | |||
1129 | : ScTextWndBase(pParent, WinBits(WB_TABSTOP)), | |||
1130 | maTextWnd(VclPtr<ScTextWnd>::Create(this, pViewSh)), | |||
1131 | maScrollBar(VclPtr<ScrollBar>::Create(this, WB_TABSTOP | WB_VERT | WB_DRAG)) | |||
1132 | { | |||
1133 | maTextWnd->SetPosPixel(Point(2 * gnBorderWidth, gnBorderHeight)); | |||
1134 | Size aSize = GetSizePixel(); | |||
1135 | maTextWnd->SetSizePixel(Size(aSize.Width() - 4 * gnBorderWidth, aSize.Height() - 2 * gnBorderHeight)); | |||
1136 | maTextWnd->Show(); | |||
1137 | maTextWnd->SetQuickHelpText(ScResId(SCSTR_QHELP_INPUTWNDreinterpret_cast<char const *>("SCSTR_QHELP_INPUTWND" "\004" u8"Input line"))); | |||
1138 | maTextWnd->SetHelpId(HID_INSWIN_INPUT"SC_HID_INSWIN_INPUT"); | |||
1139 | maScrollBar->SetScrollHdl(LINK(this, ScTextWndGroup, Impl_ScrollHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScTextWndGroup *>(this), &ScTextWndGroup::LinkStubImpl_ScrollHdl)); | |||
1140 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); | |||
1141 | Color aBackgroundColor = rStyleSettings.GetWindowColor(); | |||
1142 | SetBackground(aBackgroundColor); | |||
1143 | } | |||
1144 | ||||
1145 | ScTextWndGroup::~ScTextWndGroup() | |||
1146 | { | |||
1147 | disposeOnce(); | |||
1148 | } | |||
1149 | ||||
1150 | void ScTextWndGroup::dispose() | |||
1151 | { | |||
1152 | maTextWnd.disposeAndClear(); | |||
1153 | maScrollBar.disposeAndClear(); | |||
1154 | ScTextWndBase::dispose(); | |||
1155 | } | |||
1156 | ||||
1157 | void ScTextWndGroup::InsertAccessibleTextData(ScAccessibleEditLineTextData& rTextData) | |||
1158 | { | |||
1159 | maTextWnd->InsertAccessibleTextData(rTextData); | |||
1160 | } | |||
1161 | ||||
1162 | EditView* ScTextWndGroup::GetEditView() | |||
1163 | { | |||
1164 | return maTextWnd->GetEditView(); | |||
1165 | } | |||
1166 | ||||
1167 | long ScTextWndGroup::GetLastNumExpandedLines() const | |||
1168 | { | |||
1169 | return maTextWnd->GetLastNumExpandedLines(); | |||
1170 | } | |||
1171 | ||||
1172 | long ScTextWndGroup::GetNumLines() const | |||
1173 | { | |||
1174 | return maTextWnd->GetNumLines(); | |||
1175 | } | |||
1176 | ||||
1177 | long ScTextWndGroup::GetPixelHeightForLines(long nLines) | |||
1178 | { | |||
1179 | return maTextWnd->GetPixelHeightForLines(nLines) + 2 * gnBorderHeight; | |||
1180 | } | |||
1181 | ||||
1182 | ScrollBar& ScTextWndGroup::GetScrollBar() | |||
1183 | { | |||
1184 | return *maScrollBar; | |||
1185 | } | |||
1186 | ||||
1187 | const OUString& ScTextWndGroup::GetTextString() const | |||
1188 | { | |||
1189 | return maTextWnd->GetTextString(); | |||
1190 | } | |||
1191 | ||||
1192 | bool ScTextWndGroup::HasEditView() const | |||
1193 | { | |||
1194 | return maTextWnd->HasEditView(); | |||
1195 | } | |||
1196 | ||||
1197 | bool ScTextWndGroup::IsInputActive() | |||
1198 | { | |||
1199 | return maTextWnd->IsInputActive(); | |||
1200 | } | |||
1201 | ||||
1202 | void ScTextWndGroup::MakeDialogEditView() | |||
1203 | { | |||
1204 | maTextWnd->MakeDialogEditView(); | |||
1205 | } | |||
1206 | ||||
1207 | void ScTextWndGroup::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) | |||
1208 | { | |||
1209 | ScTextWndBase::Paint(rRenderContext, rRect); | |||
1210 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); | |||
1211 | rRenderContext.SetLineColor(rStyleSettings.GetShadowColor()); | |||
1212 | Size aSize = GetSizePixel(); | |||
1213 | rRenderContext.DrawLine(Point(0, 0), | |||
1214 | Point(aSize.Width() - 1, 0)); | |||
1215 | rRenderContext.DrawLine(Point(aSize.Width() - 1, 0), | |||
1216 | Point(aSize.Width() - 1, aSize.Height() - 1)); | |||
1217 | rRenderContext.DrawLine(Point(aSize.Width() - 1, aSize.Height() - 1), | |||
1218 | Point(0, aSize.Height() - 1)); | |||
1219 | rRenderContext.DrawLine(Point(0, aSize.Height() - 1), | |||
1220 | Point(0, 0)); | |||
1221 | } | |||
1222 | ||||
1223 | void ScTextWndGroup::RemoveAccessibleTextData(ScAccessibleEditLineTextData& rTextData) | |||
1224 | { | |||
1225 | maTextWnd->RemoveAccessibleTextData(rTextData); | |||
1226 | } | |||
1227 | ||||
1228 | void ScTextWndGroup::Resize() | |||
1229 | { | |||
1230 | Size aSize = GetSizePixel(); | |||
1231 | aSize.setHeight(GetPixelHeightForLines(GetNumLines())); | |||
1232 | SetSizePixel(aSize); | |||
1233 | if (maTextWnd->GetNumLines() > 1) | |||
1234 | { | |||
1235 | Size aScrollBarSize = maScrollBar->GetSizePixel(); | |||
1236 | aScrollBarSize.setHeight(aSize.Height() - 2); | |||
1237 | maScrollBar->SetPosPixel(Point(aSize.Width() - aScrollBarSize.Width() - 1, 1)); | |||
1238 | maScrollBar->SetSizePixel(aScrollBarSize); | |||
1239 | Size aOutputSize = maTextWnd->GetOutputSize(); | |||
1240 | maScrollBar->SetVisibleSize(aOutputSize.Height()); | |||
1241 | maScrollBar->SetPageSize(aOutputSize.Height()); | |||
1242 | maScrollBar->SetLineSize(maTextWnd->GetTextHeight()); | |||
1243 | maScrollBar->Resize(); | |||
1244 | maScrollBar->Show(); | |||
1245 | maTextWnd->SetSizePixel(Size(aSize.Width() - aScrollBarSize.Width() - 3 * gnBorderWidth - 1, | |||
1246 | aSize.Height() - 2 * gnBorderHeight)); | |||
1247 | } | |||
1248 | else | |||
1249 | { | |||
1250 | maScrollBar->Hide(); | |||
1251 | maTextWnd->SetSizePixel(Size(aSize.Width() - 4 * gnBorderWidth, aSize.Height() - 2 * gnBorderHeight)); | |||
1252 | } | |||
1253 | maTextWnd->Resize(); | |||
1254 | Invalidate(); | |||
1255 | } | |||
1256 | ||||
1257 | void ScTextWndGroup::SetNumLines(long nLines) | |||
1258 | { | |||
1259 | maTextWnd->SetNumLines(nLines); | |||
1260 | } | |||
1261 | ||||
1262 | void ScTextWndGroup::SetFormulaMode(bool bSet) | |||
1263 | { | |||
1264 | maTextWnd->SetFormulaMode(bSet); | |||
1265 | } | |||
1266 | ||||
1267 | void ScTextWndGroup::SetTextString(const OUString& rString) | |||
1268 | { | |||
1269 | maTextWnd->SetTextString(rString); | |||
1270 | } | |||
1271 | ||||
1272 | void ScTextWndGroup::StartEditEngine() | |||
1273 | { | |||
1274 | maTextWnd->StartEditEngine(); | |||
1275 | } | |||
1276 | ||||
1277 | void ScTextWndGroup::StopEditEngine(bool bAll) | |||
1278 | { | |||
1279 | maTextWnd->StopEditEngine( bAll ); | |||
1280 | } | |||
1281 | ||||
1282 | void ScTextWndGroup::TextGrabFocus() | |||
1283 | { | |||
1284 | maTextWnd->TextGrabFocus(); | |||
1285 | } | |||
1286 | ||||
1287 | IMPL_LINK_NOARG(ScTextWndGroup, Impl_ScrollHdl, ScrollBar*, void)void ScTextWndGroup::LinkStubImpl_ScrollHdl(void * instance, ScrollBar * data) { return static_cast<ScTextWndGroup *>(instance )->Impl_ScrollHdl(data); } void ScTextWndGroup::Impl_ScrollHdl (__attribute__ ((unused)) ScrollBar*) | |||
1288 | { | |||
1289 | maTextWnd->DoScroll(); | |||
1290 | } | |||
1291 | ||||
1292 | void ScTextWnd::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) | |||
1293 | { | |||
1294 | if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isDialogPainting()) | |||
1295 | return; | |||
1296 | ||||
1297 | tools::Rectangle aRect = comphelper::LibreOfficeKit::isActive() ? this->PixelToLogic(rRect) : rRect; | |||
1298 | EditView* pView = GetEditView(); | |||
1299 | if (pView) | |||
1300 | { | |||
1301 | if (mbInvalidate) | |||
1302 | { | |||
1303 | pView->Invalidate(); | |||
1304 | mbInvalidate = false; | |||
1305 | } | |||
1306 | mpEditView->Paint(aRect, &rRenderContext); | |||
1307 | } | |||
1308 | } | |||
1309 | ||||
1310 | EditView* ScTextWnd::GetEditView() | |||
1311 | { | |||
1312 | if ( !mpEditView ) | |||
1313 | InitEditEngine(); | |||
1314 | return mpEditView.get(); | |||
1315 | } | |||
1316 | ||||
1317 | bool ScTextWnd::HasEditView() const { return mpEditView != nullptr; } | |||
1318 | ||||
1319 | long ScTextWnd::GetPixelHeightForLines(long nLines) | |||
1320 | { | |||
1321 | // add padding (for the borders of the window) | |||
1322 | return LogicToPixel(Size(0, nLines * GetTextHeight())).Height() + 1; | |||
1323 | } | |||
1324 | ||||
1325 | void ScTextWnd::SetNumLines(long nLines) | |||
1326 | { | |||
1327 | mnLines = nLines; | |||
1328 | if ( nLines > 1 ) | |||
1329 | { | |||
1330 | mnLastExpandedLines = nLines; | |||
1331 | Resize(); | |||
1332 | } | |||
1333 | } | |||
1334 | ||||
1335 | void ScTextWnd::Resize() | |||
1336 | { | |||
1337 | // Only Height is recalculated here, Width is applied from | |||
1338 | // parent/container window | |||
1339 | Size aTextBoxSize = GetSizePixel(); | |||
1340 | ||||
1341 | aTextBoxSize.setHeight( GetPixelHeightForLines( mnLines ) ); | |||
1342 | SetSizePixel( aTextBoxSize ); | |||
1343 | ||||
1344 | if (mpEditView) | |||
1345 | { | |||
1346 | Size aOutputSize = GetOutputSizePixel(); | |||
1347 | tools::Rectangle aOutputArea = PixelToLogic( tools::Rectangle( Point(), aOutputSize )); | |||
1348 | mpEditView->SetOutputArea( aOutputArea ); | |||
1349 | ||||
1350 | // Don't leave an empty area at the bottom if we can move the text down. | |||
1351 | long nMaxVisAreaTop = mpEditEngine->GetTextHeight() - aOutputArea.GetHeight(); | |||
1352 | if (mpEditView->GetVisArea().Top() > nMaxVisAreaTop) | |||
1353 | { | |||
1354 | mpEditView->Scroll(0, mpEditView->GetVisArea().Top() - nMaxVisAreaTop); | |||
1355 | } | |||
1356 | ||||
1357 | mpEditEngine->SetPaperSize( PixelToLogic( Size( aOutputSize.Width(), 10000 ) ) ); | |||
1358 | } | |||
1359 | ||||
1360 | SetScrollBarRange(); | |||
1361 | } | |||
1362 | ||||
1363 | long ScTextWnd::GetEditEngTxtHeight() const | |||
1364 | { | |||
1365 | return mpEditView ? mpEditView->GetEditEngine()->GetTextHeight() : 0; | |||
1366 | } | |||
1367 | ||||
1368 | void ScTextWnd::SetScrollBarRange() | |||
1369 | { | |||
1370 | if ( mpEditView ) | |||
1371 | { | |||
1372 | ScrollBar& rVBar = mrGroupBar.GetScrollBar(); | |||
1373 | rVBar.SetRange( Range( 0, GetEditEngTxtHeight() ) ); | |||
1374 | long currentDocPos = mpEditView->GetVisArea().TopLeft().Y(); | |||
1375 | rVBar.SetThumbPos( currentDocPos ); | |||
1376 | } | |||
1377 | } | |||
1378 | ||||
1379 | void ScTextWnd::DoScroll() | |||
1380 | { | |||
1381 | if ( mpEditView ) | |||
1382 | { | |||
1383 | ScrollBar& rVBar = mrGroupBar.GetScrollBar(); | |||
1384 | long currentDocPos = mpEditView->GetVisArea().TopLeft().Y(); | |||
1385 | long nDiff = currentDocPos - rVBar.GetThumbPos(); | |||
1386 | mpEditView->Scroll( 0, nDiff ); | |||
1387 | currentDocPos = mpEditView->GetVisArea().TopLeft().Y(); | |||
1388 | rVBar.SetThumbPos( currentDocPos ); | |||
1389 | } | |||
1390 | } | |||
1391 | ||||
1392 | void ScTextWnd::StartEditEngine() | |||
1393 | { | |||
1394 | // Don't activate if we're a modal dialog ourselves (Doc-modal dialog) | |||
1395 | SfxObjectShell* pObjSh = SfxObjectShell::Current(); | |||
1396 | if ( pObjSh && pObjSh->IsInModalMode() ) | |||
1397 | return; | |||
1398 | ||||
1399 | if ( !mpEditView || !mpEditEngine ) | |||
1400 | { | |||
1401 | InitEditEngine(); | |||
1402 | } | |||
1403 | ||||
1404 | ScInputHandler* pHdl = mpViewShell->GetInputHandler(); | |||
1405 | if (pHdl) | |||
1406 | pHdl->SetMode(SC_INPUT_TOP, nullptr, mpEditEngine.get()); | |||
1407 | ||||
1408 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
1409 | if (pViewFrm) | |||
1410 | pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERTTypedWhichId<SfxBoolItem>( 10000 + 221 ) ); | |||
1411 | } | |||
1412 | ||||
1413 | static void lcl_ExtendEditFontAttribs( SfxItemSet& rSet ) | |||
1414 | { | |||
1415 | const SfxPoolItem& rFontItem = rSet.Get( EE_CHAR_FONTINFO ); | |||
1416 | std::unique_ptr<SfxPoolItem> pNewItem(rFontItem.Clone()); | |||
1417 | pNewItem->SetWhich(EE_CHAR_FONTINFO_CJK); | |||
1418 | rSet.Put( *pNewItem ); | |||
1419 | pNewItem->SetWhich(EE_CHAR_FONTINFO_CTL); | |||
1420 | rSet.Put( *pNewItem ); | |||
1421 | const SfxPoolItem& rHeightItem = rSet.Get( EE_CHAR_FONTHEIGHT ); | |||
1422 | pNewItem.reset(rHeightItem.Clone()); | |||
1423 | pNewItem->SetWhich(EE_CHAR_FONTHEIGHT_CJK); | |||
1424 | rSet.Put( *pNewItem ); | |||
1425 | pNewItem->SetWhich(EE_CHAR_FONTHEIGHT_CTL); | |||
1426 | rSet.Put( *pNewItem ); | |||
1427 | const SfxPoolItem& rWeightItem = rSet.Get( EE_CHAR_WEIGHT ); | |||
1428 | pNewItem.reset(rWeightItem.Clone()); | |||
1429 | pNewItem->SetWhich(EE_CHAR_WEIGHT_CJK); | |||
1430 | rSet.Put( *pNewItem ); | |||
1431 | pNewItem->SetWhich(EE_CHAR_WEIGHT_CTL); | |||
1432 | rSet.Put( *pNewItem ); | |||
1433 | const SfxPoolItem& rItalicItem = rSet.Get( EE_CHAR_ITALIC ); | |||
1434 | pNewItem.reset(rItalicItem.Clone()); | |||
1435 | pNewItem->SetWhich(EE_CHAR_ITALIC_CJK); | |||
1436 | rSet.Put( *pNewItem ); | |||
1437 | pNewItem->SetWhich(EE_CHAR_ITALIC_CTL); | |||
1438 | rSet.Put( *pNewItem ); | |||
1439 | const SfxPoolItem& rLangItem = rSet.Get( EE_CHAR_LANGUAGE ); | |||
1440 | pNewItem.reset(rLangItem.Clone()); | |||
1441 | pNewItem->SetWhich(EE_CHAR_LANGUAGE_CJK); | |||
1442 | rSet.Put( *pNewItem ); | |||
1443 | pNewItem->SetWhich(EE_CHAR_LANGUAGE_CTL); | |||
1444 | rSet.Put( *pNewItem ); | |||
1445 | } | |||
1446 | ||||
1447 | static void lcl_ModifyRTLDefaults( SfxItemSet& rSet ) | |||
1448 | { | |||
1449 | rSet.Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) ); | |||
1450 | ||||
1451 | // always using rtl writing direction would break formulas | |||
1452 | //rSet.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) ); | |||
1453 | ||||
1454 | // PaperSize width is limited to USHRT_MAX in RTL mode (because of EditEngine's | |||
1455 | // sal_uInt16 values in EditLine), so the text may be wrapped and line spacing must be | |||
1456 | // increased to not see the beginning of the next line. | |||
1457 | SvxLineSpacingItem aItem( LINE_SPACE_DEFAULT_HEIGHT200, EE_PARA_SBL ); | |||
1458 | aItem.SetPropLineSpace( 200 ); | |||
1459 | rSet.Put( aItem ); | |||
1460 | } | |||
1461 | ||||
1462 | static void lcl_ModifyRTLVisArea( EditView* pEditView ) | |||
1463 | { | |||
1464 | tools::Rectangle aVisArea = pEditView->GetVisArea(); | |||
1465 | Size aPaper = pEditView->GetEditEngine()->GetPaperSize(); | |||
1466 | long nDiff = aPaper.Width() - aVisArea.Right(); | |||
1467 | aVisArea.AdjustLeft(nDiff ); | |||
1468 | aVisArea.AdjustRight(nDiff ); | |||
1469 | pEditView->SetVisArea(aVisArea); | |||
1470 | } | |||
1471 | ||||
1472 | void ScTextWnd::InitEditEngine() | |||
1473 | { | |||
1474 | std::unique_ptr<ScFieldEditEngine> pNew; | |||
1475 | ScDocShell* pDocSh = nullptr; | |||
1476 | if ( mpViewShell ) | |||
1477 | { | |||
1478 | pDocSh = mpViewShell->GetViewData().GetDocShell(); | |||
1479 | ScDocument& rDoc = mpViewShell->GetViewData().GetDocument(); | |||
1480 | pNew = std::make_unique<ScFieldEditEngine>(&rDoc, rDoc.GetEnginePool(), rDoc.GetEditPool()); | |||
1481 | } | |||
1482 | else | |||
1483 | pNew = std::make_unique<ScFieldEditEngine>(nullptr, EditEngine::CreatePool(), nullptr, true); | |||
1484 | pNew->SetExecuteURL( false ); | |||
1485 | mpEditEngine = std::move(pNew); | |||
1486 | ||||
1487 | Size barSize=GetSizePixel(); | |||
1488 | mpEditEngine->SetUpdateMode( false ); | |||
1489 | mpEditEngine->SetPaperSize( PixelToLogic(Size(barSize.Width(),10000)) ); | |||
1490 | mpEditEngine->SetWordDelimiters( | |||
1491 | ScEditUtil::ModifyDelimiters( mpEditEngine->GetWordDelimiters() ) ); | |||
1492 | mpEditEngine->SetReplaceLeadingSingleQuotationMark( false ); | |||
1493 | ||||
1494 | UpdateAutoCorrFlag(); | |||
1495 | ||||
1496 | { | |||
1497 | auto pSet = std::make_unique<SfxItemSet>( mpEditEngine->GetEmptyItemSet() ); | |||
1498 | EditEngine::SetFontInfoInItemSet( *pSet, aTextFont ); | |||
1499 | lcl_ExtendEditFontAttribs( *pSet ); | |||
1500 | // turn off script spacing to match DrawText output | |||
1501 | pSet->Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) ); | |||
1502 | if ( bIsRTL ) | |||
1503 | lcl_ModifyRTLDefaults( *pSet ); | |||
1504 | mpEditEngine->SetDefaults( std::move(pSet) ); | |||
1505 | } | |||
1506 | ||||
1507 | // If the Cell contains URLFields, they need to be taken over into the entry row, | |||
1508 | // or else the position is not correct anymore | |||
1509 | bool bFilled = false; | |||
1510 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(); | |||
1511 | if ( pHdl ) //! Test if it's the right InputHdl? | |||
1512 | bFilled = pHdl->GetTextAndFields( *mpEditEngine ); | |||
1513 | ||||
1514 | mpEditEngine->SetUpdateMode( true ); | |||
1515 | ||||
1516 | // aString is the truth ... | |||
1517 | if (bFilled && mpEditEngine->GetText() == aString) | |||
1518 | Invalidate(); // Repaint for (filled) Field | |||
1519 | else | |||
1520 | mpEditEngine->SetTextCurrentDefaults(aString); // At least the right text then | |||
1521 | ||||
1522 | mpEditView = std::make_unique<EditView>(mpEditEngine.get(), this); | |||
1523 | mpEditView->SetInsertMode(bIsInsertMode); | |||
1524 | ||||
1525 | if (comphelper::LibreOfficeKit::isActive()) | |||
1526 | mpEditView->RegisterViewShell(mpViewShell); | |||
1527 | ||||
1528 | // Text from Clipboard is taken over as ASCII in a single row | |||
1529 | EVControlBits n = mpEditView->GetControlWord(); | |||
1530 | mpEditView->SetControlWord( n | EVControlBits::SINGLELINEPASTE ); | |||
1531 | ||||
1532 | mpEditEngine->InsertView( mpEditView.get(), EE_APPEND ); | |||
1533 | ||||
1534 | Resize(); | |||
1535 | ||||
1536 | if ( bIsRTL ) | |||
1537 | lcl_ModifyRTLVisArea( mpEditView.get() ); | |||
1538 | ||||
1539 | mpEditEngine->SetModifyHdl(LINK(this, ScTextWnd, ModifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScTextWnd *>(this), &ScTextWnd::LinkStubModifyHdl)); | |||
1540 | mpEditEngine->SetNotifyHdl(LINK(this, ScTextWnd, NotifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScTextWnd *>(this), &ScTextWnd::LinkStubNotifyHdl)); | |||
1541 | ||||
1542 | if (!maAccTextDatas.empty()) | |||
1543 | maAccTextDatas.back()->StartEdit(); | |||
1544 | ||||
1545 | // as long as EditEngine and DrawText sometimes differ for CTL text, | |||
1546 | // repaint now to have the EditEngine's version visible | |||
1547 | if (pDocSh) | |||
1548 | { | |||
1549 | ScDocument& rDoc = pDocSh->GetDocument(); // any document | |||
1550 | SvtScriptType nScript = rDoc.GetStringScriptType( aString ); | |||
1551 | if ( nScript & SvtScriptType::COMPLEX ) | |||
1552 | Invalidate(); | |||
1553 | } | |||
1554 | } | |||
1555 | ||||
1556 | ScTextWnd::ScTextWnd(ScTextWndGroup* pParent, ScTabViewShell* pViewSh) | |||
1557 | : ScTextWndBase(pParent, WinBits(WB_HIDE)), | |||
1558 | DragSourceHelper(this), | |||
1559 | bIsInsertMode(true), | |||
1560 | bFormulaMode (false), | |||
1561 | bInputMode (false), | |||
1562 | mpViewShell(pViewSh), | |||
1563 | mrGroupBar(*pParent), | |||
1564 | mnLines(1), | |||
1565 | mnLastExpandedLines(INPUTWIN_MULTILINES), | |||
1566 | mbInvalidate(false) | |||
1567 | { | |||
1568 | EnableRTL(false); // EditEngine can't be used with VCL EnableRTL | |||
1569 | ||||
1570 | bIsRTL = AllSettings::GetLayoutRTL(); | |||
1571 | ||||
1572 | // always use application font, so a font with cjk chars can be installed | |||
1573 | vcl::Font aAppFont = GetFont(); | |||
1574 | aTextFont = aAppFont; | |||
1575 | Size aFontSize = aAppFont.GetFontSize(); | |||
1576 | aTextFont.SetFontSize(PixelToLogic(aFontSize, MapMode(MapUnit::MapTwip))); | |||
1577 | ||||
1578 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); | |||
1579 | ||||
1580 | Color aBgColor = rStyleSettings.GetWindowColor(); | |||
1581 | Color aTxtColor = rStyleSettings.GetWindowTextColor(); | |||
1582 | ||||
1583 | aTextFont.SetTransparent(true); | |||
1584 | aTextFont.SetFillColor(aBgColor); | |||
1585 | aTextFont.SetColor(aTxtColor); | |||
1586 | aTextFont.SetWeight(WEIGHT_NORMAL); | |||
1587 | ||||
1588 | Size aSize(1, GetPixelHeightForLines(1)); | |||
1589 | auto nMinEditHeight = weld::GetMinimumEditHeight(); | |||
1590 | if (nMinEditHeight > aSize.Height()) | |||
1591 | aSize.setHeight(nMinEditHeight); | |||
1592 | ||||
1593 | SetSizePixel(aSize); | |||
1594 | SetBackground(aBgColor); | |||
1595 | SetLineColor(COL_BLACK); | |||
1596 | SetMapMode(MapMode(MapUnit::MapTwip)); | |||
1597 | SetPointer(PointerStyle::Text); | |||
1598 | SetFont(aTextFont); | |||
1599 | ||||
1600 | set_id("sc_input_window"); | |||
1601 | } | |||
1602 | ||||
1603 | ScTextWnd::~ScTextWnd() | |||
1604 | { | |||
1605 | disposeOnce(); | |||
1606 | } | |||
1607 | ||||
1608 | void ScTextWnd::dispose() | |||
1609 | { | |||
1610 | while (!maAccTextDatas.empty()) { | |||
1611 | maAccTextDatas.back()->Dispose(); | |||
1612 | } | |||
1613 | mpEditView.reset(); | |||
1614 | mpEditEngine.reset(); | |||
1615 | ||||
1616 | DragSourceHelper::dispose(); | |||
1617 | ScTextWndBase::dispose(); | |||
1618 | } | |||
1619 | ||||
1620 | void ScTextWnd::MouseMove( const MouseEvent& rMEvt ) | |||
1621 | { | |||
1622 | if (mpEditView) | |||
1623 | mpEditView->MouseMove( rMEvt ); | |||
1624 | } | |||
1625 | ||||
1626 | void ScTextWnd::MouseButtonDown( const MouseEvent& rMEvt ) | |||
1627 | { | |||
1628 | if (!HasFocus()) | |||
1629 | { | |||
1630 | StartEditEngine(); | |||
1631 | if ( SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->IsEditMode() ) | |||
1632 | GrabFocus(); | |||
1633 | } | |||
1634 | ||||
1635 | if (mpEditView) | |||
1636 | { | |||
1637 | mpEditView->SetEditEngineUpdateMode( true ); | |||
1638 | mpEditView->MouseButtonDown( rMEvt ); | |||
1639 | } | |||
1640 | } | |||
1641 | ||||
1642 | void ScTextWnd::MouseButtonUp( const MouseEvent& rMEvt ) | |||
1643 | { | |||
1644 | if (mpEditView) | |||
1645 | if (mpEditView->MouseButtonUp( rMEvt )) | |||
1646 | { | |||
1647 | if ( rMEvt.IsMiddle() && | |||
1648 | GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection ) | |||
1649 | { | |||
1650 | // EditView may have pasted from selection | |||
1651 | SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->InputChanged( mpEditView.get() ); | |||
1652 | } | |||
1653 | else | |||
1654 | SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->InputSelection( mpEditView.get() ); | |||
1655 | } | |||
1656 | } | |||
1657 | ||||
1658 | void ScTextWnd::Command( const CommandEvent& rCEvt ) | |||
1659 | { | |||
1660 | bInputMode = true; | |||
1661 | CommandEventId nCommand = rCEvt.GetCommand(); | |||
1662 | if ( mpEditView /* && nCommand == CommandEventId::StartDrag */ ) | |||
1663 | { | |||
1664 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
1665 | ScTabViewShell* pStartViewSh = ScTabViewShell::GetActiveViewShell(); | |||
1666 | ||||
1667 | // don't modify the font defaults here - the right defaults are | |||
1668 | // already set in StartEditEngine when the EditEngine is created | |||
1669 | ||||
1670 | // Prevent that the EditView is lost when switching between Views | |||
1671 | pScMod->SetInEditCommand( true ); | |||
1672 | mpEditView->Command( rCEvt ); | |||
1673 | pScMod->SetInEditCommand( false ); | |||
1674 | ||||
1675 | // CommandEventId::StartDrag does not mean by far that the content was actually changed, | |||
1676 | // so don't trigger an InputChanged. | |||
1677 | //! Detect if dragged with Move or forbid Drag&Move somehow | |||
1678 | ||||
1679 | if ( nCommand == CommandEventId::StartDrag ) | |||
1680 | { | |||
1681 | // Is dragged onto another View? | |||
1682 | ScTabViewShell* pEndViewSh = ScTabViewShell::GetActiveViewShell(); | |||
1683 | if ( pEndViewSh != pStartViewSh && pStartViewSh != nullptr ) | |||
1684 | { | |||
1685 | ScViewData& rViewData = pStartViewSh->GetViewData(); | |||
1686 | ScInputHandler* pHdl = pScMod->GetInputHdl( pStartViewSh ); | |||
1687 | if ( pHdl && rViewData.HasEditView( rViewData.GetActivePart() ) ) | |||
1688 | { | |||
1689 | pHdl->CancelHandler(); | |||
1690 | rViewData.GetView()->ShowCursor(); // Missing for KillEditView, due to being inactive | |||
1691 | } | |||
1692 | } | |||
1693 | } | |||
1694 | else if ( nCommand == CommandEventId::EndExtTextInput ) | |||
1695 | { | |||
1696 | if (bFormulaMode) | |||
1697 | { | |||
1698 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(); | |||
1699 | if (pHdl) | |||
1700 | pHdl->InputCommand(rCEvt); | |||
1701 | } | |||
1702 | } | |||
1703 | else if ( nCommand == CommandEventId::CursorPos ) | |||
1704 | { | |||
1705 | // don't call InputChanged for CommandEventId::CursorPos | |||
1706 | } | |||
1707 | else if ( nCommand == CommandEventId::InputLanguageChange ) | |||
1708 | { | |||
1709 | // #i55929# Font and font size state depends on input language if nothing is selected, | |||
1710 | // so the slots have to be invalidated when the input language is changed. | |||
1711 | ||||
1712 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
1713 | if (pViewFrm) | |||
1714 | { | |||
1715 | SfxBindings& rBindings = pViewFrm->GetBindings(); | |||
1716 | rBindings.Invalidate( SID_ATTR_CHAR_FONT( 10000 + 7 ) ); | |||
1717 | rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT( 10000 + 15 ) ); | |||
1718 | } | |||
1719 | } | |||
1720 | else if ( nCommand == CommandEventId::ContextMenu ) | |||
1721 | { | |||
1722 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
1723 | if (pViewFrm) | |||
1724 | { | |||
1725 | Point aPos = rCEvt.GetMousePosPixel(); | |||
1726 | if (!rCEvt.IsMouseEvent()) | |||
1727 | { | |||
1728 | Size aSize = GetOutputSizePixel(); | |||
1729 | aPos = Point(aSize.Width() / 2, aSize.Height() / 2); | |||
1730 | } | |||
1731 | pViewFrm->GetDispatcher()->ExecutePopup("formulabar", this, &aPos); | |||
1732 | } | |||
1733 | } | |||
1734 | else if ( nCommand == CommandEventId::Wheel ) | |||
1735 | { | |||
1736 | //don't call InputChanged for CommandEventId::Wheel | |||
1737 | } | |||
1738 | else if ( nCommand == CommandEventId::Swipe ) | |||
1739 | { | |||
1740 | //don't call InputChanged for CommandEventId::Swipe | |||
1741 | } | |||
1742 | else if ( nCommand == CommandEventId::LongPress ) | |||
1743 | { | |||
1744 | //don't call InputChanged for CommandEventId::LongPress | |||
1745 | } | |||
1746 | else if ( nCommand == CommandEventId::ModKeyChange ) | |||
1747 | { | |||
1748 | //pass alt press/release to parent impl | |||
1749 | Window::Command(rCEvt); | |||
1750 | } | |||
1751 | else | |||
1752 | SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->InputChanged( mpEditView.get() ); | |||
1753 | } | |||
1754 | else | |||
1755 | Window::Command(rCEvt); // Or else let the base class handle it... | |||
1756 | ||||
1757 | bInputMode = false; | |||
1758 | } | |||
1759 | ||||
1760 | void ScTextWnd::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel ) | |||
1761 | { | |||
1762 | if ( mpEditView ) | |||
1763 | { | |||
1764 | CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true ); | |||
1765 | mpEditView->Command( aDragEvent ); | |||
1766 | ||||
1767 | // handling of d&d to different view (CancelHandler) can't be done here, | |||
1768 | // because the call returns before d&d is complete. | |||
1769 | } | |||
1770 | } | |||
1771 | ||||
1772 | void ScTextWnd::KeyInput(const KeyEvent& rKEvt) | |||
1773 | { | |||
1774 | bInputMode = true; | |||
1775 | if (!SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->InputKeyEvent( rKEvt )) | |||
1776 | { | |||
1777 | bool bUsed = false; | |||
1778 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
1779 | if ( pViewSh ) | |||
1780 | bUsed = pViewSh->SfxKeyInput(rKEvt); // Only accelerators, no input | |||
1781 | if (!bUsed) | |||
1782 | Window::KeyInput( rKEvt ); | |||
1783 | } | |||
1784 | bInputMode = false; | |||
1785 | } | |||
1786 | ||||
1787 | void ScTextWnd::GetFocus() | |||
1788 | { | |||
1789 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
1790 | if ( pViewSh ) | |||
1791 | pViewSh->SetFormShellAtTop( false ); // focus in input line -> FormShell no longer on top | |||
1792 | } | |||
1793 | ||||
1794 | void ScTextWnd::LoseFocus() | |||
1795 | { | |||
1796 | } | |||
1797 | ||||
1798 | OUString ScTextWnd::GetText() const | |||
1799 | { | |||
1800 | // Override to get the text via the testtool | |||
1801 | if ( mpEditEngine ) | |||
1802 | return mpEditEngine->GetText(); | |||
1803 | else | |||
1804 | return GetTextString(); | |||
1805 | } | |||
1806 | ||||
1807 | void ScTextWnd::SetFormulaMode( bool bSet ) | |||
1808 | { | |||
1809 | if ( bSet != bFormulaMode ) | |||
1810 | { | |||
1811 | bFormulaMode = bSet; | |||
1812 | UpdateAutoCorrFlag(); | |||
1813 | } | |||
1814 | } | |||
1815 | ||||
1816 | void ScTextWnd::UpdateAutoCorrFlag() | |||
1817 | { | |||
1818 | if ( mpEditEngine ) | |||
1819 | { | |||
1820 | EEControlBits nControl = mpEditEngine->GetControlWord(); | |||
1821 | EEControlBits nOld = nControl; | |||
1822 | if ( bFormulaMode ) | |||
1823 | nControl &= ~EEControlBits::AUTOCORRECT; // No AutoCorrect in Formulas | |||
1824 | else | |||
1825 | nControl |= EEControlBits::AUTOCORRECT; // Else do enable it | |||
1826 | ||||
1827 | if ( nControl != nOld ) | |||
1828 | mpEditEngine->SetControlWord( nControl ); | |||
1829 | } | |||
1830 | } | |||
1831 | ||||
1832 | IMPL_LINK(ScTextWnd, NotifyHdl, EENotify&, rNotify, void)void ScTextWnd::LinkStubNotifyHdl(void * instance, EENotify& data) { return static_cast<ScTextWnd *>(instance)-> NotifyHdl(data); } void ScTextWnd::NotifyHdl(EENotify& rNotify ) | |||
1833 | { | |||
1834 | // need to process EE_NOTIFY_TEXTVIEWSCROLLED here | |||
1835 | // sometimes we don't seem to get EE_NOTIFY_TEXTVIEWSCROLLED e.g. when | |||
1836 | // we insert text at the beginning of the text so the cursor never moves | |||
1837 | // down to generate a scroll event | |||
1838 | ||||
1839 | if ( rNotify.eNotificationType == EE_NOTIFY_TEXTVIEWSCROLLED | |||
1840 | || rNotify.eNotificationType == EE_NOTIFY_TextHeightChanged ) | |||
1841 | SetScrollBarRange(); | |||
1842 | } | |||
1843 | ||||
1844 | IMPL_LINK_NOARG(ScTextWnd, ModifyHdl, LinkParamNone*, void)void ScTextWnd::LinkStubModifyHdl(void * instance, LinkParamNone * data) { return static_cast<ScTextWnd *>(instance)-> ModifyHdl(data); } void ScTextWnd::ModifyHdl(__attribute__ (( unused)) LinkParamNone*) | |||
1845 | { | |||
1846 | if (mpEditView && !bInputMode) | |||
1847 | { | |||
1848 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl(); | |||
1849 | ||||
1850 | // Use the InputHandler's InOwnChange flag to prevent calling InputChanged | |||
1851 | // while an InputHandler method is modifying the EditEngine content | |||
1852 | ||||
1853 | if ( pHdl && !pHdl->IsInOwnChange() ) | |||
1854 | pHdl->InputChanged( mpEditView.get(), true ); // #i20282# InputChanged must know if called from modify handler | |||
1855 | } | |||
1856 | } | |||
1857 | ||||
1858 | void ScTextWnd::StopEditEngine( bool bAll ) | |||
1859 | { | |||
1860 | if (!mpEditEngine) | |||
1861 | return; | |||
1862 | ||||
1863 | mpEditEngine->SetNotifyHdl(Link<EENotify&, void>()); | |||
1864 | ||||
1865 | if (mpEditView) | |||
1866 | { | |||
1867 | if (!maAccTextDatas.empty()) | |||
1868 | maAccTextDatas.back()->EndEdit(); | |||
1869 | ||||
1870 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
1871 | ||||
1872 | if (!bAll) | |||
1873 | pScMod->InputSelection( mpEditView.get() ); | |||
1874 | aString = mpEditEngine->GetText(); | |||
1875 | bIsInsertMode = mpEditView->IsInsertMode(); | |||
1876 | bool bSelection = mpEditView->HasSelection(); | |||
1877 | mpEditEngine->SetModifyHdl(Link<LinkParamNone*,void>()); | |||
1878 | mpEditView.reset(); | |||
1879 | mpEditEngine.reset(); | |||
1880 | ||||
1881 | ScInputHandler* pHdl = mpViewShell->GetInputHandler(); | |||
1882 | ||||
1883 | if (pHdl && pHdl->IsEditMode() && !bAll) | |||
1884 | pHdl->SetMode(SC_INPUT_TABLE); | |||
1885 | ||||
1886 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
1887 | if (pViewFrm) | |||
1888 | pViewFrm->GetBindings().Invalidate( SID_ATTR_INSERTTypedWhichId<SfxBoolItem>( 10000 + 221 ) ); | |||
1889 | ||||
1890 | if (bSelection) | |||
1891 | Invalidate(); // So that the Selection is not left there | |||
1892 | } | |||
1893 | ||||
1894 | if (comphelper::LibreOfficeKit::isActive()) | |||
1895 | { | |||
1896 | // Clear | |||
1897 | std::vector<ReferenceMark> aReferenceMarks; | |||
1898 | ScInputHandler::SendReferenceMarks( mpViewShell, aReferenceMarks ); | |||
1899 | } | |||
1900 | } | |||
1901 | ||||
1902 | static sal_Int32 findFirstNonMatchingChar(const OUString& rStr1, const OUString& rStr2) | |||
1903 | { | |||
1904 | // Search the string for unmatching chars | |||
1905 | const sal_Unicode* pStr1 = rStr1.getStr(); | |||
1906 | const sal_Unicode* pStr2 = rStr2.getStr(); | |||
1907 | sal_Int32 i = 0; | |||
1908 | while ( i < rStr1.getLength() ) | |||
1909 | { | |||
1910 | // Abort on the first unmatching char | |||
1911 | if ( *pStr1 != *pStr2 ) | |||
1912 | return i; | |||
1913 | ++pStr1; | |||
1914 | ++pStr2; | |||
1915 | ++i; | |||
1916 | } | |||
1917 | ||||
1918 | return i; | |||
1919 | } | |||
1920 | ||||
1921 | void ScTextWnd::SetTextString( const OUString& rNewString ) | |||
1922 | { | |||
1923 | // Ideally it would be best to create on demand the EditEngine/EditView here, but... for | |||
1924 | // the initialisation scenario where a cell is first clicked on we end up with the text in the | |||
1925 | // inputbar window scrolled to the bottom if we do that here ( because the tableview and topview | |||
1926 | // are synced I guess ). | |||
1927 | // should fix that I suppose :-/ need to look a bit further into that | |||
1928 | mbInvalidate = true; // ensure next Paint ( that uses editengine ) call will call Invalidate first | |||
1929 | ||||
1930 | if ( rNewString != aString ) | |||
1931 | { | |||
1932 | bInputMode = true; | |||
1933 | ||||
1934 | // Find position of the change, only paint the rest | |||
1935 | if (!mpEditEngine) | |||
1936 | { | |||
1937 | bool bPaintAll = mnLines > 1 || bIsRTL; | |||
1938 | if (!bPaintAll) | |||
1939 | { | |||
1940 | // test if CTL script type is involved | |||
1941 | SvtScriptType nOldScript = SvtScriptType::NONE; | |||
1942 | SvtScriptType nNewScript = SvtScriptType::NONE; | |||
1943 | SfxObjectShell* pObjSh = SfxObjectShell::Current(); | |||
1944 | if ( auto pDocShell = dynamic_cast<ScDocShell*>( pObjSh) ) | |||
1945 | { | |||
1946 | // any document can be used (used only for its break iterator) | |||
1947 | ScDocument& rDoc = pDocShell->GetDocument(); | |||
1948 | nOldScript = rDoc.GetStringScriptType( aString ); | |||
1949 | nNewScript = rDoc.GetStringScriptType( rNewString ); | |||
1950 | } | |||
1951 | bPaintAll = ( nOldScript & SvtScriptType::COMPLEX ) || ( nNewScript & SvtScriptType::COMPLEX ); | |||
1952 | } | |||
1953 | ||||
1954 | if ( bPaintAll ) | |||
1955 | { | |||
1956 | // In multiline mode, or if CTL is involved, the whole text has to be redrawn | |||
1957 | Invalidate(); | |||
1958 | } | |||
1959 | else | |||
1960 | { | |||
1961 | long nTextSize = 0; | |||
1962 | sal_Int32 nDifPos; | |||
1963 | if (rNewString.getLength() > aString.getLength()) | |||
1964 | nDifPos = findFirstNonMatchingChar(rNewString, aString); | |||
1965 | else | |||
1966 | nDifPos = findFirstNonMatchingChar(aString, rNewString); | |||
1967 | ||||
1968 | long nSize1 = GetTextWidth(aString); | |||
1969 | long nSize2 = GetTextWidth(rNewString); | |||
1970 | if ( nSize1>0 && nSize2>0 ) | |||
1971 | nTextSize = std::max( nSize1, nSize2 ); | |||
1972 | else | |||
1973 | nTextSize = GetOutputSize().Width(); // Overflow | |||
1974 | ||||
1975 | Point aLogicStart = PixelToLogic(Point(0,0)); | |||
1976 | long nStartPos = aLogicStart.X(); | |||
1977 | long nInvPos = nStartPos; | |||
1978 | if (nDifPos) | |||
1979 | nInvPos += GetTextWidth(aString,0,nDifPos); | |||
1980 | ||||
1981 | InvalidateFlags nFlags = InvalidateFlags::NONE; | |||
1982 | if ( nDifPos == aString.getLength() ) // only new characters appended | |||
1983 | nFlags = InvalidateFlags::NoErase; // then background is already clear | |||
1984 | ||||
1985 | Invalidate( tools::Rectangle( nInvPos, 0, nStartPos+nTextSize, GetOutputSize().Height()-1 ), nFlags ); | |||
1986 | } | |||
1987 | } | |||
1988 | else | |||
1989 | { | |||
1990 | mpEditEngine->SetTextCurrentDefaults(rNewString); | |||
1991 | } | |||
1992 | ||||
1993 | aString = rNewString; | |||
1994 | ||||
1995 | if (!maAccTextDatas.empty()) | |||
1996 | maAccTextDatas.back()->TextChanged(); | |||
1997 | ||||
1998 | bInputMode = false; | |||
1999 | } | |||
2000 | ||||
2001 | SetScrollBarRange(); | |||
2002 | DoScroll(); | |||
2003 | } | |||
2004 | ||||
2005 | const OUString& ScTextWnd::GetTextString() const | |||
2006 | { | |||
2007 | return aString; | |||
2008 | } | |||
2009 | ||||
2010 | bool ScTextWnd::IsInputActive() | |||
2011 | { | |||
2012 | return HasFocus(); | |||
2013 | } | |||
2014 | ||||
2015 | void ScTextWnd::MakeDialogEditView() | |||
2016 | { | |||
2017 | if ( mpEditView ) return; | |||
2018 | ||||
2019 | std::unique_ptr<ScFieldEditEngine> pNew; | |||
2020 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
2021 | if ( pViewSh ) | |||
2022 | { | |||
2023 | ScDocument& rDoc = pViewSh->GetViewData().GetDocument(); | |||
2024 | pNew = std::make_unique<ScFieldEditEngine>(&rDoc, rDoc.GetEnginePool(), rDoc.GetEditPool()); | |||
2025 | } | |||
2026 | else | |||
2027 | pNew = std::make_unique<ScFieldEditEngine>(nullptr, EditEngine::CreatePool(), nullptr, true); | |||
2028 | pNew->SetExecuteURL( false ); | |||
2029 | mpEditEngine = std::move(pNew); | |||
2030 | ||||
2031 | mpEditEngine->SetUpdateMode( false ); | |||
2032 | mpEditEngine->SetWordDelimiters( mpEditEngine->GetWordDelimiters() + "=" ); | |||
2033 | mpEditEngine->SetPaperSize( Size( bIsRTL ? USHRT_MAX(32767 *2 +1) : THESIZE, 300 ) ); | |||
2034 | ||||
2035 | auto pSet = std::make_unique<SfxItemSet>( mpEditEngine->GetEmptyItemSet() ); | |||
2036 | EditEngine::SetFontInfoInItemSet( *pSet, aTextFont ); | |||
2037 | lcl_ExtendEditFontAttribs( *pSet ); | |||
2038 | if ( bIsRTL ) | |||
2039 | lcl_ModifyRTLDefaults( *pSet ); | |||
2040 | mpEditEngine->SetDefaults( std::move(pSet) ); | |||
2041 | mpEditEngine->SetUpdateMode( true ); | |||
2042 | ||||
2043 | mpEditView = std::make_unique<EditView>(mpEditEngine.get(), this); | |||
2044 | if (comphelper::LibreOfficeKit::isActive()) | |||
2045 | mpEditView->RegisterViewShell(mpViewShell); | |||
2046 | mpEditEngine->InsertView( mpEditView.get(), EE_APPEND ); | |||
2047 | ||||
2048 | Resize(); | |||
2049 | ||||
2050 | if ( bIsRTL ) | |||
2051 | lcl_ModifyRTLVisArea( mpEditView.get() ); | |||
2052 | ||||
2053 | if (!maAccTextDatas.empty()) | |||
2054 | maAccTextDatas.back()->StartEdit(); | |||
2055 | } | |||
2056 | ||||
2057 | void ScTextWnd::ImplInitSettings() | |||
2058 | { | |||
2059 | bIsRTL = AllSettings::GetLayoutRTL(); | |||
2060 | ||||
2061 | const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); | |||
2062 | ||||
2063 | Color aBgColor= rStyleSettings.GetWindowColor(); | |||
2064 | Color aTxtColor= rStyleSettings.GetWindowTextColor(); | |||
2065 | ||||
2066 | aTextFont.SetFillColor ( aBgColor ); | |||
2067 | aTextFont.SetColor (aTxtColor); | |||
2068 | SetBackground ( aBgColor ); | |||
2069 | Invalidate(); | |||
2070 | } | |||
2071 | ||||
2072 | css::uno::Reference< css::accessibility::XAccessible > ScTextWnd::CreateAccessible() | |||
2073 | { | |||
2074 | return new ScAccessibleEditObject(GetAccessibleParentWindow()->GetAccessible(), nullptr, this, | |||
2075 | ScResId(STR_ACC_EDITLINE_NAMEreinterpret_cast<char const *>("STR_ACC_EDITLINE_NAME" "\004" u8"Input line")), | |||
2076 | ScResId(STR_ACC_EDITLINE_DESCRreinterpret_cast<char const *>("STR_ACC_EDITLINE_DESCR" "\004" u8"This is where you enter or edit text, numbers and formulas." )), ScAccessibleEditObject::EditLine); | |||
2077 | } | |||
2078 | ||||
2079 | void ScTextWnd::InsertAccessibleTextData( ScAccessibleEditLineTextData& rTextData ) | |||
2080 | { | |||
2081 | OSL_ENSURE( ::std::find( maAccTextDatas.begin(), maAccTextDatas.end(), &rTextData ) == maAccTextDatas.end(),do { if (true && (!(::std::find( maAccTextDatas.begin (), maAccTextDatas.end(), &rTextData ) == maAccTextDatas. end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ( "legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "2082" ": "), "%s", "ScTextWnd::InsertAccessibleTextData - passed object already registered" ); } } while (false) | |||
2082 | "ScTextWnd::InsertAccessibleTextData - passed object already registered" )do { if (true && (!(::std::find( maAccTextDatas.begin (), maAccTextDatas.end(), &rTextData ) == maAccTextDatas. end()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ( "legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "2082" ": "), "%s", "ScTextWnd::InsertAccessibleTextData - passed object already registered" ); } } while (false); | |||
2083 | maAccTextDatas.push_back( &rTextData ); | |||
2084 | } | |||
2085 | ||||
2086 | void ScTextWnd::RemoveAccessibleTextData( ScAccessibleEditLineTextData& rTextData ) | |||
2087 | { | |||
2088 | AccTextDataVector::iterator aEnd = maAccTextDatas.end(); | |||
2089 | AccTextDataVector::iterator aIt = ::std::find( maAccTextDatas.begin(), aEnd, &rTextData ); | |||
2090 | OSL_ENSURE( aIt != aEnd, "ScTextWnd::RemoveAccessibleTextData - passed object not registered" )do { if (true && (!(aIt != aEnd))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/ui/app/inputwin.cxx" ":" "2090" ": "), "%s", "ScTextWnd::RemoveAccessibleTextData - passed object not registered" ); } } while (false); | |||
2091 | if( aIt != aEnd ) | |||
2092 | maAccTextDatas.erase( aIt ); | |||
2093 | } | |||
2094 | ||||
2095 | void ScTextWnd::DataChanged( const DataChangedEvent& rDCEvt ) | |||
2096 | { | |||
2097 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && | |||
2098 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) | |||
2099 | { | |||
2100 | ImplInitSettings(); | |||
2101 | Invalidate(); | |||
2102 | } | |||
2103 | else | |||
2104 | Window::DataChanged( rDCEvt ); | |||
2105 | } | |||
2106 | ||||
2107 | void ScTextWnd::TextGrabFocus() | |||
2108 | { | |||
2109 | GrabFocus(); | |||
2110 | } | |||
2111 | ||||
2112 | // Position window | |||
2113 | ScPosWnd::ScPosWnd(vcl::Window* pParent) | |||
2114 | : InterimItemWindow(pParent, "modules/scalc/ui/posbox.ui", "PosBox") | |||
2115 | , m_xWidget(m_xBuilder->weld_combo_box("pos_window")) | |||
2116 | , m_nAsyncGetFocusId(nullptr) | |||
2117 | , nTipVisible(nullptr) | |||
2118 | , bFormulaMode(false) | |||
2119 | { | |||
2120 | InitControlBase(m_xWidget.get()); | |||
2121 | ||||
2122 | // Use calculation according to tdf#132338 to align combobox width to width of fontname combobox within formatting toolbar; | |||
2123 | // formatting toolbar is placed above formulabar when using multiple toolbars typically | |||
2124 | ||||
2125 | m_xWidget->set_entry_width_chars(1); | |||
2126 | Size aSize(LogicToPixel(Size(POSITION_COMBOBOX_WIDTH * 4, 0), MapMode(MapUnit::MapAppFont))); | |||
2127 | m_xWidget->set_size_request(aSize.Width(), -1); | |||
2128 | SetSizePixel(m_xContainer->get_preferred_size()); | |||
2129 | ||||
2130 | FillRangeNames(); | |||
2131 | ||||
2132 | StartListening( *SfxGetpApp() ); // For Navigator rangename updates | |||
2133 | ||||
2134 | m_xWidget->connect_key_press(LINK(this, ScPosWnd, KeyInputHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubKeyInputHdl)); | |||
2135 | m_xWidget->connect_entry_activate(LINK(this, ScPosWnd, ActivateHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubActivateHdl)); | |||
2136 | m_xWidget->connect_changed(LINK(this, ScPosWnd, ModifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubModifyHdl)); | |||
2137 | m_xWidget->connect_focus_in(LINK(this, ScPosWnd, FocusInHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubFocusInHdl)); | |||
2138 | m_xWidget->connect_focus_out(LINK(this, ScPosWnd, FocusOutHdl)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubFocusOutHdl)); | |||
2139 | } | |||
2140 | ||||
2141 | ScPosWnd::~ScPosWnd() | |||
2142 | { | |||
2143 | disposeOnce(); | |||
2144 | } | |||
2145 | ||||
2146 | void ScPosWnd::dispose() | |||
2147 | { | |||
2148 | EndListening( *SfxGetpApp() ); | |||
2149 | ||||
2150 | HideTip(); | |||
2151 | ||||
2152 | if (m_nAsyncGetFocusId) | |||
2153 | { | |||
2154 | Application::RemoveUserEvent(m_nAsyncGetFocusId); | |||
2155 | m_nAsyncGetFocusId = nullptr; | |||
2156 | } | |||
2157 | m_xWidget.reset(); | |||
2158 | ||||
2159 | InterimItemWindow::dispose(); | |||
2160 | } | |||
2161 | ||||
2162 | void ScPosWnd::SetFormulaMode( bool bSet ) | |||
2163 | { | |||
2164 | if ( bSet != bFormulaMode ) | |||
2165 | { | |||
2166 | bFormulaMode = bSet; | |||
2167 | ||||
2168 | if ( bSet ) | |||
2169 | FillFunctions(); | |||
2170 | else | |||
2171 | FillRangeNames(); | |||
2172 | ||||
2173 | HideTip(); | |||
2174 | } | |||
2175 | } | |||
2176 | ||||
2177 | void ScPosWnd::SetPos( const OUString& rPosStr ) | |||
2178 | { | |||
2179 | if ( aPosStr != rPosStr ) | |||
2180 | { | |||
2181 | aPosStr = rPosStr; | |||
2182 | m_xWidget->set_entry_text(aPosStr); | |||
2183 | } | |||
2184 | } | |||
2185 | ||||
2186 | namespace { | |||
2187 | ||||
2188 | OUString createLocalRangeName(const OUString& rName, const OUString& rTableName) | |||
2189 | { | |||
2190 | return rName + " (" + rTableName + ")"; | |||
2191 | } | |||
2192 | ||||
2193 | } | |||
2194 | ||||
2195 | void ScPosWnd::FillRangeNames() | |||
2196 | { | |||
2197 | m_xWidget->clear(); | |||
2198 | m_xWidget->freeze(); | |||
2199 | ||||
2200 | SfxObjectShell* pObjSh = SfxObjectShell::Current(); | |||
2201 | if ( auto pDocShell = dynamic_cast<ScDocShell*>( pObjSh) ) | |||
2202 | { | |||
2203 | ScDocument& rDoc = pDocShell->GetDocument(); | |||
2204 | ||||
2205 | m_xWidget->append_text(ScResId(STR_MANAGE_NAMESreinterpret_cast<char const *>("STR_MANAGE_NAMES" "\004" u8"Manage Names..."))); | |||
2206 | m_xWidget->append_separator("separator"); | |||
2207 | ||||
2208 | ScRange aDummy; | |||
2209 | std::set<OUString> aSet; | |||
2210 | ScRangeName* pRangeNames = rDoc.GetRangeName(); | |||
2211 | for (const auto& rEntry : *pRangeNames) | |||
2212 | { | |||
2213 | if (rEntry.second->IsValidReference(aDummy)) | |||
2214 | aSet.insert(rEntry.second->GetName()); | |||
2215 | } | |||
2216 | for (SCTAB i = 0; i < rDoc.GetTableCount(); ++i) | |||
2217 | { | |||
2218 | ScRangeName* pLocalRangeName = rDoc.GetRangeName(i); | |||
2219 | if (pLocalRangeName && !pLocalRangeName->empty()) | |||
2220 | { | |||
2221 | OUString aTableName; | |||
2222 | rDoc.GetName(i, aTableName); | |||
2223 | for (const auto& rEntry : *pLocalRangeName) | |||
2224 | { | |||
2225 | if (rEntry.second->IsValidReference(aDummy)) | |||
2226 | aSet.insert(createLocalRangeName(rEntry.second->GetName(), aTableName)); | |||
2227 | } | |||
2228 | } | |||
2229 | } | |||
2230 | ||||
2231 | for (const auto& rItem : aSet) | |||
2232 | { | |||
2233 | m_xWidget->append_text(rItem); | |||
2234 | } | |||
2235 | } | |||
2236 | m_xWidget->thaw(); | |||
2237 | m_xWidget->set_entry_text(aPosStr); | |||
2238 | } | |||
2239 | ||||
2240 | void ScPosWnd::FillFunctions() | |||
2241 | { | |||
2242 | m_xWidget->clear(); | |||
2243 | m_xWidget->freeze(); | |||
2244 | ||||
2245 | OUString aFirstName; | |||
2246 | const ScAppOptions& rOpt = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetAppOptions(); | |||
2247 | sal_uInt16 nMRUCount = rOpt.GetLRUFuncListCount(); | |||
2248 | const sal_uInt16* pMRUList = rOpt.GetLRUFuncList(); | |||
2249 | if (pMRUList) | |||
2250 | { | |||
2251 | const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); | |||
2252 | sal_uInt32 nListCount = pFuncList->GetCount(); | |||
2253 | for (sal_uInt16 i=0; i<nMRUCount; i++) | |||
2254 | { | |||
2255 | sal_uInt16 nId = pMRUList[i]; | |||
2256 | for (sal_uInt32 j=0; j<nListCount; j++) | |||
2257 | { | |||
2258 | const ScFuncDesc* pDesc = pFuncList->GetFunction( j ); | |||
2259 | if ( pDesc->nFIndex == nId && pDesc->mxFuncName ) | |||
2260 | { | |||
2261 | m_xWidget->append_text(*pDesc->mxFuncName); | |||
2262 | if (aFirstName.isEmpty()) | |||
2263 | aFirstName = *pDesc->mxFuncName; | |||
2264 | break; // Stop searching | |||
2265 | } | |||
2266 | } | |||
2267 | } | |||
2268 | } | |||
2269 | ||||
2270 | //! Re-add entry "Other..." for Function AutoPilot if it can work with text that | |||
2271 | // has been entered so far | |||
2272 | ||||
2273 | // m_xWidget->append_text(ScResId(STR_FUNCTIONLIST_MORE)); | |||
2274 | ||||
2275 | m_xWidget->thaw(); | |||
2276 | m_xWidget->set_entry_text(aFirstName); | |||
2277 | } | |||
2278 | ||||
2279 | void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint ) | |||
2280 | { | |||
2281 | if ( bFormulaMode ) | |||
2282 | return; | |||
2283 | ||||
2284 | // Does the list of range names need updating? | |||
2285 | if ( dynamic_cast<const SfxEventHint*>(&rHint) ) | |||
2286 | { | |||
2287 | SfxEventHintId nEventId = static_cast<const SfxEventHint*>(&rHint)->GetEventId(); | |||
2288 | if ( nEventId == SfxEventHintId::ActivateDoc ) | |||
2289 | FillRangeNames(); | |||
2290 | } | |||
2291 | else | |||
2292 | { | |||
2293 | const SfxHintId nHintId = rHint.GetId(); | |||
2294 | if ( nHintId == SfxHintId::ScAreasChanged || nHintId == SfxHintId::ScNavigatorUpdateAll) | |||
2295 | FillRangeNames(); | |||
2296 | } | |||
2297 | } | |||
2298 | ||||
2299 | void ScPosWnd::HideTip() | |||
2300 | { | |||
2301 | if (nTipVisible) | |||
2302 | { | |||
2303 | Help::HidePopover(this, nTipVisible); | |||
2304 | nTipVisible = nullptr; | |||
2305 | } | |||
2306 | } | |||
2307 | ||||
2308 | static ScNameInputType lcl_GetInputType( const OUString& rText ) | |||
2309 | { | |||
2310 | ScNameInputType eRet = SC_NAME_INPUT_BAD_NAME; // the more general error | |||
2311 | ||||
2312 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
2313 | if ( pViewSh ) | |||
2314 | { | |||
2315 | ScViewData& rViewData = pViewSh->GetViewData(); | |||
2316 | ScDocument& rDoc = rViewData.GetDocument(); | |||
2317 | SCTAB nTab = rViewData.GetTabNo(); | |||
2318 | formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention(); | |||
2319 | ||||
2320 | // test in same order as in SID_CURRENTCELL execute | |||
2321 | ||||
2322 | ScRange aRange; | |||
2323 | ScAddress aAddress; | |||
2324 | SCTAB nNameTab; | |||
2325 | sal_Int32 nNumeric; | |||
2326 | ||||
2327 | if (rText == ScResId(STR_MANAGE_NAMESreinterpret_cast<char const *>("STR_MANAGE_NAMES" "\004" u8"Manage Names..."))) | |||
2328 | eRet = SC_MANAGE_NAMES; | |||
2329 | else if ( aRange.Parse( rText, rDoc, eConv ) & ScRefFlags::VALID ) | |||
2330 | eRet = SC_NAME_INPUT_RANGE; | |||
2331 | else if ( aAddress.Parse( rText, rDoc, eConv ) & ScRefFlags::VALID ) | |||
2332 | eRet = SC_NAME_INPUT_CELL; | |||
2333 | else if ( ScRangeUtil::MakeRangeFromName( rText, rDoc, nTab, aRange, RUTL_NAMES, eConv ) ) | |||
2334 | eRet = SC_NAME_INPUT_NAMEDRANGE; | |||
2335 | else if ( ScRangeUtil::MakeRangeFromName( rText, rDoc, nTab, aRange, RUTL_DBASE, eConv ) ) | |||
2336 | eRet = SC_NAME_INPUT_DATABASE; | |||
2337 | else if ( comphelper::string::isdigitAsciiString( rText ) && | |||
2338 | ( nNumeric = rText.toInt32() ) > 0 && nNumeric <= rDoc.MaxRow()+1 ) | |||
2339 | eRet = SC_NAME_INPUT_ROW; | |||
2340 | else if ( rDoc.GetTable( rText, nNameTab ) ) | |||
2341 | eRet = SC_NAME_INPUT_SHEET; | |||
2342 | else if ( ScRangeData::IsNameValid( rText, rDoc ) == ScRangeData::NAME_VALID ) // nothing found, create new range? | |||
2343 | { | |||
2344 | if ( rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) | |||
2345 | eRet = SC_NAME_INPUT_DEFINE; | |||
2346 | else | |||
2347 | eRet = SC_NAME_INPUT_BAD_SELECTION; | |||
2348 | } | |||
2349 | else | |||
2350 | eRet = SC_NAME_INPUT_BAD_NAME; | |||
2351 | } | |||
2352 | ||||
2353 | return eRet; | |||
2354 | } | |||
2355 | ||||
2356 | IMPL_LINK_NOARG(ScPosWnd, ModifyHdl, weld::ComboBox&, void)void ScPosWnd::LinkStubModifyHdl(void * instance, weld::ComboBox & data) { return static_cast<ScPosWnd *>(instance)-> ModifyHdl(data); } void ScPosWnd::ModifyHdl(__attribute__ ((unused )) weld::ComboBox&) | |||
2357 | { | |||
2358 | HideTip(); | |||
2359 | ||||
2360 | if (m_xWidget->changed_by_direct_pick()) | |||
2361 | { | |||
2362 | DoEnter(); | |||
2363 | return; | |||
2364 | } | |||
2365 | ||||
2366 | if (bFormulaMode) | |||
2367 | return; | |||
2368 | ||||
2369 | // determine the action that would be taken for the current input | |||
2370 | ||||
2371 | ScNameInputType eType = lcl_GetInputType(m_xWidget->get_active_text()); // uses current view | |||
2372 | const char* pStrId = nullptr; | |||
2373 | switch ( eType ) | |||
2374 | { | |||
2375 | case SC_NAME_INPUT_CELL: | |||
2376 | pStrId = STR_NAME_INPUT_CELLreinterpret_cast<char const *>("STR_NAME_INPUT_CELL" "\004" u8"Select Cell"); | |||
2377 | break; | |||
2378 | case SC_NAME_INPUT_RANGE: | |||
2379 | case SC_NAME_INPUT_NAMEDRANGE: | |||
2380 | pStrId = STR_NAME_INPUT_RANGEreinterpret_cast<char const *>("STR_NAME_INPUT_RANGE" "\004" u8"Select Range"); // named range or range reference | |||
2381 | break; | |||
2382 | case SC_NAME_INPUT_DATABASE: | |||
2383 | pStrId = STR_NAME_INPUT_DBRANGEreinterpret_cast<char const *>("STR_NAME_INPUT_DBRANGE" "\004" u8"Select Database Range"); | |||
2384 | break; | |||
2385 | case SC_NAME_INPUT_ROW: | |||
2386 | pStrId = STR_NAME_INPUT_ROWreinterpret_cast<char const *>("STR_NAME_INPUT_ROW" "\004" u8"Go To Row"); | |||
2387 | break; | |||
2388 | case SC_NAME_INPUT_SHEET: | |||
2389 | pStrId = STR_NAME_INPUT_SHEETreinterpret_cast<char const *>("STR_NAME_INPUT_SHEET" "\004" u8"Go To Sheet"); | |||
2390 | break; | |||
2391 | case SC_NAME_INPUT_DEFINE: | |||
2392 | pStrId = STR_NAME_INPUT_DEFINEreinterpret_cast<char const *>("STR_NAME_INPUT_DEFINE" "\004" u8"Define Name for Range"); | |||
2393 | break; | |||
2394 | default: | |||
2395 | // other cases (error): no tip help | |||
2396 | break; | |||
2397 | } | |||
2398 | ||||
2399 | if (!pStrId) | |||
2400 | return; | |||
2401 | ||||
2402 | // show the help tip at the text cursor position | |||
2403 | Point aPos; | |||
2404 | vcl::Cursor* pCur = GetCursor(); | |||
2405 | if (pCur) | |||
2406 | aPos = LogicToPixel( pCur->GetPos() ); | |||
2407 | aPos = OutputToScreenPixel( aPos ); | |||
2408 | tools::Rectangle aRect( aPos, aPos ); | |||
2409 | ||||
2410 | OUString aText = ScResId(pStrId); | |||
2411 | QuickHelpFlags const nAlign = QuickHelpFlags::Left|QuickHelpFlags::Bottom; | |||
2412 | nTipVisible = Help::ShowPopover(this, aRect, aText, nAlign); | |||
2413 | } | |||
2414 | ||||
2415 | void ScPosWnd::DoEnter() | |||
2416 | { | |||
2417 | OUString aText = m_xWidget->get_active_text(); | |||
2418 | if ( !aText.isEmpty() ) | |||
2419 | { | |||
2420 | if ( bFormulaMode ) | |||
2421 | { | |||
2422 | ScModule* pScMod = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) ); | |||
2423 | if ( aText == ScResId(STR_FUNCTIONLIST_MOREreinterpret_cast<char const *>("STR_FUNCTIONLIST_MORE" "\004" u8"More...")) ) | |||
2424 | { | |||
2425 | // Function AutoPilot | |||
2426 | //! Continue working with the text entered so far | |||
2427 | ||||
2428 | //! new method at ScModule to query if function autopilot is open | |||
2429 | SfxViewFrame* pViewFrm = SfxViewFrame::Current(); | |||
2430 | if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION((26000 + 100) + 52) ) ) | |||
2431 | pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION((26000 + 100) + 52), | |||
2432 | SfxCallMode::SYNCHRON | SfxCallMode::RECORD ); | |||
2433 | } | |||
2434 | else | |||
2435 | { | |||
2436 | ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); | |||
2437 | ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh ); | |||
2438 | if (pHdl) | |||
2439 | pHdl->InsertFunction( aText ); | |||
2440 | } | |||
2441 | } | |||
2442 | else | |||
2443 | { | |||
2444 | // depending on the input, select something or create a new named range | |||
2445 | ||||
2446 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); | |||
2447 | if ( pViewSh ) | |||
2448 | { | |||
2449 | ScViewData& rViewData = pViewSh->GetViewData(); | |||
2450 | ScDocShell* pDocShell = rViewData.GetDocShell(); | |||
2451 | ScDocument& rDoc = pDocShell->GetDocument(); | |||
2452 | ||||
2453 | ScNameInputType eType = lcl_GetInputType( aText ); | |||
2454 | if ( eType == SC_NAME_INPUT_BAD_NAME || eType == SC_NAME_INPUT_BAD_SELECTION ) | |||
2455 | { | |||
2456 | const char* pId = (eType == SC_NAME_INPUT_BAD_NAME) ? STR_NAME_ERROR_NAMEreinterpret_cast<char const *>("STR_NAME_ERROR_NAME" "\004" u8"You must enter a valid reference or type a valid name for the selected range." ) : STR_NAME_ERROR_SELECTIONreinterpret_cast<char const *>("STR_NAME_ERROR_SELECTION" "\004" u8"The selection needs to be rectangular in order to name it." ); | |||
2457 | pViewSh->ErrorMessage(pId); | |||
2458 | } | |||
2459 | else if ( eType == SC_NAME_INPUT_DEFINE ) | |||
2460 | { | |||
2461 | ScRangeName* pNames = rDoc.GetRangeName(); | |||
2462 | ScRange aSelection; | |||
2463 | if ( pNames && !pNames->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(aText)) && | |||
2464 | (rViewData.GetSimpleArea( aSelection ) == SC_MARK_SIMPLE) ) | |||
2465 | { | |||
2466 | ScRangeName aNewRanges( *pNames ); | |||
2467 | ScAddress aCursor( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() ); | |||
2468 | OUString aContent(aSelection.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention())); | |||
2469 | ScRangeData* pNew = new ScRangeData( rDoc, aText, aContent, aCursor ); | |||
2470 | if ( aNewRanges.insert(pNew) ) | |||
2471 | { | |||
2472 | pDocShell->GetDocFunc().ModifyRangeNames( aNewRanges ); | |||
2473 | pViewSh->UpdateInputHandler(true); | |||
2474 | } | |||
2475 | } | |||
2476 | } | |||
2477 | else if (eType == SC_MANAGE_NAMES) | |||
2478 | { | |||
2479 | sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId(); | |||
2480 | SfxViewFrame* pViewFrm = pViewSh->GetViewFrame(); | |||
2481 | SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId ); | |||
2482 | ||||
2483 | SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->SetRefDialog( nId, pWnd == nullptr ); | |||
2484 | } | |||
2485 | else | |||
2486 | { | |||
2487 | // for all selection types, execute the SID_CURRENTCELL slot. | |||
2488 | if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE) | |||
2489 | { | |||
2490 | // Note that SID_CURRENTCELL always expects address to | |||
2491 | // be in Calc A1 format. Convert the text. | |||
2492 | ScRange aRange(0,0, rViewData.GetTabNo()); | |||
2493 | aRange.ParseAny(aText, rDoc, rDoc.GetAddressConvention()); | |||
2494 | aText = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, ::formula::FormulaGrammar::CONV_OOO); | |||
2495 | } | |||
2496 | ||||
2497 | SfxStringItem aPosItem( SID_CURRENTCELL((26000) + 41), aText ); | |||
2498 | SfxBoolItem aUnmarkItem( FN_PARAM_1((20000 + 1100)+60), true ); // remove existing selection | |||
2499 | ||||
2500 | pViewSh->GetViewData().GetDispatcher().ExecuteList( SID_CURRENTCELL((26000) + 41), | |||
2501 | SfxCallMode::SYNCHRON | SfxCallMode::RECORD, | |||
2502 | { &aPosItem, &aUnmarkItem }); | |||
2503 | } | |||
2504 | } | |||
2505 | } | |||
2506 | } | |||
2507 | else | |||
2508 | m_xWidget->set_entry_text(aPosStr); | |||
2509 | ||||
2510 | ReleaseFocus_Impl(); | |||
2511 | } | |||
2512 | ||||
2513 | IMPL_LINK_NOARG(ScPosWnd, ActivateHdl, weld::ComboBox&, bool)bool ScPosWnd::LinkStubActivateHdl(void * instance, weld::ComboBox & data) { return static_cast<ScPosWnd *>(instance)-> ActivateHdl(data); } bool ScPosWnd::ActivateHdl(__attribute__ ((unused)) weld::ComboBox&) | |||
2514 | { | |||
2515 | DoEnter(); | |||
2516 | return true; | |||
2517 | } | |||
2518 | ||||
2519 | IMPL_LINK(ScPosWnd, KeyInputHdl, const KeyEvent&, rKEvt, bool)bool ScPosWnd::LinkStubKeyInputHdl(void * instance, const KeyEvent & data) { return static_cast<ScPosWnd *>(instance)-> KeyInputHdl(data); } bool ScPosWnd::KeyInputHdl(const KeyEvent & rKEvt) | |||
2520 | { | |||
2521 | bool bHandled = true; | |||
2522 | ||||
2523 | switch (rKEvt.GetKeyCode().GetCode()) | |||
2524 | { | |||
2525 | case KEY_RETURN: | |||
2526 | bHandled = ActivateHdl(*m_xWidget); | |||
2527 | break; | |||
2528 | case KEY_ESCAPE: | |||
2529 | if (nTipVisible) | |||
2530 | { | |||
2531 | // escape when the tip help is shown: only hide the tip | |||
2532 | HideTip(); | |||
2533 | } | |||
2534 | else | |||
2535 | { | |||
2536 | if (!bFormulaMode) | |||
2537 | m_xWidget->set_entry_text(aPosStr); | |||
2538 | ReleaseFocus_Impl(); | |||
2539 | } | |||
2540 | break; | |||
2541 | default: | |||
2542 | bHandled = false; | |||
2543 | break; | |||
2544 | } | |||
2545 | ||||
2546 | return bHandled || ChildKeyInput(rKEvt); | |||
2547 | } | |||
2548 | ||||
2549 | IMPL_LINK_NOARG(ScPosWnd, OnAsyncGetFocus, void*, void)void ScPosWnd::LinkStubOnAsyncGetFocus(void * instance, void* data) { return static_cast<ScPosWnd *>(instance)->OnAsyncGetFocus (data); } void ScPosWnd::OnAsyncGetFocus(__attribute__ ((unused )) void*) | |||
2550 | { | |||
2551 | m_nAsyncGetFocusId = nullptr; | |||
2552 | m_xWidget->select_entry_region(0, -1); | |||
2553 | } | |||
2554 | ||||
2555 | IMPL_LINK_NOARG(ScPosWnd, FocusInHdl, weld::Widget&, void)void ScPosWnd::LinkStubFocusInHdl(void * instance, weld::Widget & data) { return static_cast<ScPosWnd *>(instance)-> FocusInHdl(data); } void ScPosWnd::FocusInHdl(__attribute__ ( (unused)) weld::Widget&) | |||
2556 | { | |||
2557 | if (m_nAsyncGetFocusId) | |||
2558 | return; | |||
2559 | // do it async to defeat entry in combobox having its own ideas about the focus | |||
2560 | m_nAsyncGetFocusId = Application::PostUserEvent(LINK(this, ScPosWnd, OnAsyncGetFocus)::tools::detail::makeLink( ::tools::detail::castTo<ScPosWnd *>(this), &ScPosWnd::LinkStubOnAsyncGetFocus)); | |||
2561 | } | |||
2562 | ||||
2563 | IMPL_LINK_NOARG(ScPosWnd, FocusOutHdl, weld::Widget&, void)void ScPosWnd::LinkStubFocusOutHdl(void * instance, weld::Widget & data) { return static_cast<ScPosWnd *>(instance)-> FocusOutHdl(data); } void ScPosWnd::FocusOutHdl(__attribute__ ((unused)) weld::Widget&) | |||
2564 | { | |||
2565 | if (m_nAsyncGetFocusId) | |||
2566 | { | |||
2567 | Application::RemoveUserEvent(m_nAsyncGetFocusId); | |||
2568 | m_nAsyncGetFocusId = nullptr; | |||
2569 | } | |||
2570 | ||||
2571 | HideTip(); | |||
2572 | } | |||
2573 | ||||
2574 | void ScPosWnd::ReleaseFocus_Impl() | |||
2575 | { | |||
2576 | HideTip(); | |||
2577 | ||||
2578 | SfxViewShell* pCurSh = SfxViewShell::Current(); | |||
2579 | ScInputHandler* pHdl = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetInputHdl( dynamic_cast<ScTabViewShell*>( pCurSh ) ); | |||
2580 | if ( pHdl && pHdl->IsTopMode() ) | |||
2581 | { | |||
2582 | // Focus back in input row? | |||
2583 | ScInputWindow* pInputWin = pHdl->GetInputWindow(); | |||
2584 | if (pInputWin) | |||
2585 | { | |||
2586 | pInputWin->TextGrabFocus(); | |||
2587 | return; | |||
2588 | } | |||
2589 | } | |||
2590 | ||||
2591 | // Set focus to active View | |||
2592 | if ( pCurSh ) | |||
2593 | { | |||
2594 | vcl::Window* pShellWnd = pCurSh->GetWindow(); | |||
2595 | ||||
2596 | if ( pShellWnd ) | |||
2597 | pShellWnd->GrabFocus(); | |||
2598 | } | |||
2599 | } | |||
2600 | ||||
2601 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2020 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H1 |
31 | #define _UNIQUE_PTR_H1 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | #if __cplusplus201703L > 201703L |
41 | # include <compare> |
42 | # include <ostream> |
43 | #endif |
44 | |
45 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
46 | { |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
48 | |
49 | /** |
50 | * @addtogroup pointer_abstractions |
51 | * @{ |
52 | */ |
53 | |
54 | #if _GLIBCXX_USE_DEPRECATED1 |
55 | #pragma GCC diagnostic push |
56 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
57 | template<typename> class auto_ptr; |
58 | #pragma GCC diagnostic pop |
59 | #endif |
60 | |
61 | /// Primary template of default_delete, used by unique_ptr for single objects |
62 | template<typename _Tp> |
63 | struct default_delete |
64 | { |
65 | /// Default constructor |
66 | constexpr default_delete() noexcept = default; |
67 | |
68 | /** @brief Converting constructor. |
69 | * |
70 | * Allows conversion from a deleter for objects of another type, `_Up`, |
71 | * only if `_Up*` is convertible to `_Tp*`. |
72 | */ |
73 | template<typename _Up, |
74 | typename = _Require<is_convertible<_Up*, _Tp*>>> |
75 | default_delete(const default_delete<_Up>&) noexcept { } |
76 | |
77 | /// Calls `delete __ptr` |
78 | void |
79 | operator()(_Tp* __ptr) const |
80 | { |
81 | static_assert(!is_void<_Tp>::value, |
82 | "can't delete pointer to incomplete type"); |
83 | static_assert(sizeof(_Tp)>0, |
84 | "can't delete pointer to incomplete type"); |
85 | delete __ptr; |
86 | } |
87 | }; |
88 | |
89 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
90 | // DR 740 - omit specialization for array objects with a compile time length |
91 | |
92 | /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>` |
93 | template<typename _Tp> |
94 | struct default_delete<_Tp[]> |
95 | { |
96 | public: |
97 | /// Default constructor |
98 | constexpr default_delete() noexcept = default; |
99 | |
100 | /** @brief Converting constructor. |
101 | * |
102 | * Allows conversion from a deleter for arrays of another type, such as |
103 | * a const-qualified version of `_Tp`. |
104 | * |
105 | * Conversions from types derived from `_Tp` are not allowed because |
106 | * it is undefined to `delete[]` an array of derived types through a |
107 | * pointer to the base type. |
108 | */ |
109 | template<typename _Up, |
110 | typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>> |
111 | default_delete(const default_delete<_Up[]>&) noexcept { } |
112 | |
113 | /// Calls `delete[] __ptr` |
114 | template<typename _Up> |
115 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
116 | operator()(_Up* __ptr) const |
117 | { |
118 | static_assert(sizeof(_Tp)>0, |
119 | "can't delete pointer to incomplete type"); |
120 | delete [] __ptr; |
121 | } |
122 | }; |
123 | |
124 | /// @cond undocumented |
125 | |
126 | // Manages the pointer and deleter of a unique_ptr |
127 | template <typename _Tp, typename _Dp> |
128 | class __uniq_ptr_impl |
129 | { |
130 | template <typename _Up, typename _Ep, typename = void> |
131 | struct _Ptr |
132 | { |
133 | using type = _Up*; |
134 | }; |
135 | |
136 | template <typename _Up, typename _Ep> |
137 | struct |
138 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
139 | { |
140 | using type = typename remove_reference<_Ep>::type::pointer; |
141 | }; |
142 | |
143 | public: |
144 | using _DeleterConstraint = enable_if< |
145 | __and_<__not_<is_pointer<_Dp>>, |
146 | is_default_constructible<_Dp>>::value>; |
147 | |
148 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
149 | |
150 | static_assert( !is_rvalue_reference<_Dp>::value, |
151 | "unique_ptr's deleter type must be a function object type" |
152 | " or an lvalue reference type" ); |
153 | |
154 | __uniq_ptr_impl() = default; |
155 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
156 | |
157 | template<typename _Del> |
158 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
159 | : _M_t(__p, std::forward<_Del>(__d)) { } |
160 | |
161 | __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept |
162 | : _M_t(std::move(__u._M_t)) |
163 | { __u._M_ptr() = nullptr; } |
164 | |
165 | __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept |
166 | { |
167 | reset(__u.release()); |
168 | _M_deleter() = std::forward<_Dp>(__u._M_deleter()); |
169 | return *this; |
170 | } |
171 | |
172 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
173 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
174 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
175 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
176 | |
177 | void reset(pointer __p) noexcept |
178 | { |
179 | const pointer __old_p = _M_ptr(); |
180 | _M_ptr() = __p; |
181 | if (__old_p) |
182 | _M_deleter()(__old_p); |
183 | } |
184 | |
185 | pointer release() noexcept |
186 | { |
187 | pointer __p = _M_ptr(); |
188 | _M_ptr() = nullptr; |
189 | return __p; |
190 | } |
191 | |
192 | void |
193 | swap(__uniq_ptr_impl& __rhs) noexcept |
194 | { |
195 | using std::swap; |
196 | swap(this->_M_ptr(), __rhs._M_ptr()); |
197 | swap(this->_M_deleter(), __rhs._M_deleter()); |
198 | } |
199 | |
200 | private: |
201 | tuple<pointer, _Dp> _M_t; |
202 | }; |
203 | |
204 | // Defines move construction + assignment as either defaulted or deleted. |
205 | template <typename _Tp, typename _Dp, |
206 | bool = is_move_constructible<_Dp>::value, |
207 | bool = is_move_assignable<_Dp>::value> |
208 | struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> |
209 | { |
210 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
211 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
212 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
213 | }; |
214 | |
215 | template <typename _Tp, typename _Dp> |
216 | struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> |
217 | { |
218 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
219 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
220 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
221 | }; |
222 | |
223 | template <typename _Tp, typename _Dp> |
224 | struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> |
225 | { |
226 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
227 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
228 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
229 | }; |
230 | |
231 | template <typename _Tp, typename _Dp> |
232 | struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> |
233 | { |
234 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
235 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
236 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
237 | }; |
238 | /// @endcond |
239 | |
240 | /// 20.7.1.2 unique_ptr for single objects. |
241 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
242 | class unique_ptr |
243 | { |
244 | template <typename _Up> |
245 | using _DeleterConstraint = |
246 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
247 | |
248 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
249 | |
250 | public: |
251 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
252 | using element_type = _Tp; |
253 | using deleter_type = _Dp; |
254 | |
255 | private: |
256 | // helper template for detecting a safe conversion from another |
257 | // unique_ptr |
258 | template<typename _Up, typename _Ep> |
259 | using __safe_conversion_up = __and_< |
260 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
261 | __not_<is_array<_Up>> |
262 | >; |
263 | |
264 | public: |
265 | // Constructors. |
266 | |
267 | /// Default constructor, creates a unique_ptr that owns nothing. |
268 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
269 | constexpr unique_ptr() noexcept |
270 | : _M_t() |
271 | { } |
272 | |
273 | /** Takes ownership of a pointer. |
274 | * |
275 | * @param __p A pointer to an object of @c element_type |
276 | * |
277 | * The deleter will be value-initialized. |
278 | */ |
279 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
280 | explicit |
281 | unique_ptr(pointer __p) noexcept |
282 | : _M_t(__p) |
283 | { } |
284 | |
285 | /** Takes ownership of a pointer. |
286 | * |
287 | * @param __p A pointer to an object of @c element_type |
288 | * @param __d A reference to a deleter. |
289 | * |
290 | * The deleter will be initialized with @p __d |
291 | */ |
292 | template<typename _Del = deleter_type, |
293 | typename = _Require<is_copy_constructible<_Del>>> |
294 | unique_ptr(pointer __p, const deleter_type& __d) noexcept |
295 | : _M_t(__p, __d) { } |
296 | |
297 | /** Takes ownership of a pointer. |
298 | * |
299 | * @param __p A pointer to an object of @c element_type |
300 | * @param __d An rvalue reference to a (non-reference) deleter. |
301 | * |
302 | * The deleter will be initialized with @p std::move(__d) |
303 | */ |
304 | template<typename _Del = deleter_type, |
305 | typename = _Require<is_move_constructible<_Del>>> |
306 | unique_ptr(pointer __p, |
307 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
308 | _Del&&> __d) noexcept |
309 | : _M_t(__p, std::move(__d)) |
310 | { } |
311 | |
312 | template<typename _Del = deleter_type, |
313 | typename _DelUnref = typename remove_reference<_Del>::type> |
314 | unique_ptr(pointer, |
315 | __enable_if_t<is_lvalue_reference<_Del>::value, |
316 | _DelUnref&&>) = delete; |
317 | |
318 | /// Creates a unique_ptr that owns nothing. |
319 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
320 | constexpr unique_ptr(nullptr_t) noexcept |
321 | : _M_t() |
322 | { } |
323 | |
324 | // Move constructors. |
325 | |
326 | /// Move constructor. |
327 | unique_ptr(unique_ptr&&) = default; |
328 | |
329 | /** @brief Converting constructor from another type |
330 | * |
331 | * Requires that the pointer owned by @p __u is convertible to the |
332 | * type of pointer owned by this object, @p __u does not own an array, |
333 | * and @p __u has a compatible deleter type. |
334 | */ |
335 | template<typename _Up, typename _Ep, typename = _Require< |
336 | __safe_conversion_up<_Up, _Ep>, |
337 | typename conditional<is_reference<_Dp>::value, |
338 | is_same<_Ep, _Dp>, |
339 | is_convertible<_Ep, _Dp>>::type>> |
340 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
341 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
342 | { } |
343 | |
344 | #if _GLIBCXX_USE_DEPRECATED1 |
345 | #pragma GCC diagnostic push |
346 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
347 | /// Converting constructor from @c auto_ptr |
348 | template<typename _Up, typename = _Require< |
349 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
350 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
351 | #pragma GCC diagnostic pop |
352 | #endif |
353 | |
354 | /// Destructor, invokes the deleter if the stored pointer is not null. |
355 | ~unique_ptr() noexcept |
356 | { |
357 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
358 | "unique_ptr's deleter must be invocable with a pointer"); |
359 | auto& __ptr = _M_t._M_ptr(); |
360 | if (__ptr != nullptr) |
361 | get_deleter()(std::move(__ptr)); |
362 | __ptr = pointer(); |
363 | } |
364 | |
365 | // Assignment. |
366 | |
367 | /** @brief Move assignment operator. |
368 | * |
369 | * Invokes the deleter if this object owns a pointer. |
370 | */ |
371 | unique_ptr& operator=(unique_ptr&&) = default; |
372 | |
373 | /** @brief Assignment from another type. |
374 | * |
375 | * @param __u The object to transfer ownership from, which owns a |
376 | * convertible pointer to a non-array object. |
377 | * |
378 | * Invokes the deleter if this object owns a pointer. |
379 | */ |
380 | template<typename _Up, typename _Ep> |
381 | typename enable_if< __and_< |
382 | __safe_conversion_up<_Up, _Ep>, |
383 | is_assignable<deleter_type&, _Ep&&> |
384 | >::value, |
385 | unique_ptr&>::type |
386 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
387 | { |
388 | reset(__u.release()); |
389 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
390 | return *this; |
391 | } |
392 | |
393 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
394 | unique_ptr& |
395 | operator=(nullptr_t) noexcept |
396 | { |
397 | reset(); |
398 | return *this; |
399 | } |
400 | |
401 | // Observers. |
402 | |
403 | /// Dereference the stored pointer. |
404 | typename add_lvalue_reference<element_type>::type |
405 | operator*() const |
406 | { |
407 | __glibcxx_assert(get() != pointer()); |
408 | return *get(); |
409 | } |
410 | |
411 | /// Return the stored pointer. |
412 | pointer |
413 | operator->() const noexcept |
414 | { |
415 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
416 | return get(); |
417 | } |
418 | |
419 | /// Return the stored pointer. |
420 | pointer |
421 | get() const noexcept |
422 | { return _M_t._M_ptr(); } |
423 | |
424 | /// Return a reference to the stored deleter. |
425 | deleter_type& |
426 | get_deleter() noexcept |
427 | { return _M_t._M_deleter(); } |
428 | |
429 | /// Return a reference to the stored deleter. |
430 | const deleter_type& |
431 | get_deleter() const noexcept |
432 | { return _M_t._M_deleter(); } |
433 | |
434 | /// Return @c true if the stored pointer is not null. |
435 | explicit operator bool() const noexcept |
436 | { return get() == pointer() ? false : true; } |
437 | |
438 | // Modifiers. |
439 | |
440 | /// Release ownership of any stored pointer. |
441 | pointer |
442 | release() noexcept |
443 | { return _M_t.release(); } |
444 | |
445 | /** @brief Replace the stored pointer. |
446 | * |
447 | * @param __p The new pointer to store. |
448 | * |
449 | * The deleter will be invoked if a pointer is already owned. |
450 | */ |
451 | void |
452 | reset(pointer __p = pointer()) noexcept |
453 | { |
454 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
455 | "unique_ptr's deleter must be invocable with a pointer"); |
456 | _M_t.reset(std::move(__p)); |
457 | } |
458 | |
459 | /// Exchange the pointer and deleter with another object. |
460 | void |
461 | swap(unique_ptr& __u) noexcept |
462 | { |
463 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
464 | _M_t.swap(__u._M_t); |
465 | } |
466 | |
467 | // Disable copy from lvalue. |
468 | unique_ptr(const unique_ptr&) = delete; |
469 | unique_ptr& operator=(const unique_ptr&) = delete; |
470 | }; |
471 | |
472 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
473 | // [unique.ptr.runtime] |
474 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
475 | // DR 740 - omit specialization for array objects with a compile time length |
476 | template<typename _Tp, typename _Dp> |
477 | class unique_ptr<_Tp[], _Dp> |
478 | { |
479 | template <typename _Up> |
480 | using _DeleterConstraint = |
481 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
482 | |
483 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
484 | |
485 | template<typename _Up> |
486 | using __remove_cv = typename remove_cv<_Up>::type; |
487 | |
488 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
489 | template<typename _Up> |
490 | using __is_derived_Tp |
491 | = __and_< is_base_of<_Tp, _Up>, |
492 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
493 | |
494 | public: |
495 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
496 | using element_type = _Tp; |
497 | using deleter_type = _Dp; |
498 | |
499 | // helper template for detecting a safe conversion from another |
500 | // unique_ptr |
501 | template<typename _Up, typename _Ep, |
502 | typename _UPtr = unique_ptr<_Up, _Ep>, |
503 | typename _UP_pointer = typename _UPtr::pointer, |
504 | typename _UP_element_type = typename _UPtr::element_type> |
505 | using __safe_conversion_up = __and_< |
506 | is_array<_Up>, |
507 | is_same<pointer, element_type*>, |
508 | is_same<_UP_pointer, _UP_element_type*>, |
509 | is_convertible<_UP_element_type(*)[], element_type(*)[]> |
510 | >; |
511 | |
512 | // helper template for detecting a safe conversion from a raw pointer |
513 | template<typename _Up> |
514 | using __safe_conversion_raw = __and_< |
515 | __or_<__or_<is_same<_Up, pointer>, |
516 | is_same<_Up, nullptr_t>>, |
517 | __and_<is_pointer<_Up>, |
518 | is_same<pointer, element_type*>, |
519 | is_convertible< |
520 | typename remove_pointer<_Up>::type(*)[], |
521 | element_type(*)[]> |
522 | > |
523 | > |
524 | >; |
525 | |
526 | // Constructors. |
527 | |
528 | /// Default constructor, creates a unique_ptr that owns nothing. |
529 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
530 | constexpr unique_ptr() noexcept |
531 | : _M_t() |
532 | { } |
533 | |
534 | /** Takes ownership of a pointer. |
535 | * |
536 | * @param __p A pointer to an array of a type safely convertible |
537 | * to an array of @c element_type |
538 | * |
539 | * The deleter will be value-initialized. |
540 | */ |
541 | template<typename _Up, |
542 | typename _Vp = _Dp, |
543 | typename = _DeleterConstraint<_Vp>, |
544 | typename = typename enable_if< |
545 | __safe_conversion_raw<_Up>::value, bool>::type> |
546 | explicit |
547 | unique_ptr(_Up __p) noexcept |
548 | : _M_t(__p) |
549 | { } |
550 | |
551 | /** Takes ownership of a pointer. |
552 | * |
553 | * @param __p A pointer to an array of a type safely convertible |
554 | * to an array of @c element_type |
555 | * @param __d A reference to a deleter. |
556 | * |
557 | * The deleter will be initialized with @p __d |
558 | */ |
559 | template<typename _Up, typename _Del = deleter_type, |
560 | typename = _Require<__safe_conversion_raw<_Up>, |
561 | is_copy_constructible<_Del>>> |
562 | unique_ptr(_Up __p, const deleter_type& __d) noexcept |
563 | : _M_t(__p, __d) { } |
564 | |
565 | /** Takes ownership of a pointer. |
566 | * |
567 | * @param __p A pointer to an array of a type safely convertible |
568 | * to an array of @c element_type |
569 | * @param __d A reference to a deleter. |
570 | * |
571 | * The deleter will be initialized with @p std::move(__d) |
572 | */ |
573 | template<typename _Up, typename _Del = deleter_type, |
574 | typename = _Require<__safe_conversion_raw<_Up>, |
575 | is_move_constructible<_Del>>> |
576 | unique_ptr(_Up __p, |
577 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
578 | _Del&&> __d) noexcept |
579 | : _M_t(std::move(__p), std::move(__d)) |
580 | { } |
581 | |
582 | template<typename _Up, typename _Del = deleter_type, |
583 | typename _DelUnref = typename remove_reference<_Del>::type, |
584 | typename = _Require<__safe_conversion_raw<_Up>>> |
585 | unique_ptr(_Up, |
586 | __enable_if_t<is_lvalue_reference<_Del>::value, |
587 | _DelUnref&&>) = delete; |
588 | |
589 | /// Move constructor. |
590 | unique_ptr(unique_ptr&&) = default; |
591 | |
592 | /// Creates a unique_ptr that owns nothing. |
593 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
594 | constexpr unique_ptr(nullptr_t) noexcept |
595 | : _M_t() |
596 | { } |
597 | |
598 | template<typename _Up, typename _Ep, typename = _Require< |
599 | __safe_conversion_up<_Up, _Ep>, |
600 | typename conditional<is_reference<_Dp>::value, |
601 | is_same<_Ep, _Dp>, |
602 | is_convertible<_Ep, _Dp>>::type>> |
603 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
604 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
605 | { } |
606 | |
607 | /// Destructor, invokes the deleter if the stored pointer is not null. |
608 | ~unique_ptr() |
609 | { |
610 | auto& __ptr = _M_t._M_ptr(); |
611 | if (__ptr != nullptr) |
612 | get_deleter()(__ptr); |
613 | __ptr = pointer(); |
614 | } |
615 | |
616 | // Assignment. |
617 | |
618 | /** @brief Move assignment operator. |
619 | * |
620 | * Invokes the deleter if this object owns a pointer. |
621 | */ |
622 | unique_ptr& |
623 | operator=(unique_ptr&&) = default; |
624 | |
625 | /** @brief Assignment from another type. |
626 | * |
627 | * @param __u The object to transfer ownership from, which owns a |
628 | * convertible pointer to an array object. |
629 | * |
630 | * Invokes the deleter if this object owns a pointer. |
631 | */ |
632 | template<typename _Up, typename _Ep> |
633 | typename |
634 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
635 | is_assignable<deleter_type&, _Ep&&> |
636 | >::value, |
637 | unique_ptr&>::type |
638 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
639 | { |
640 | reset(__u.release()); |
641 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
642 | return *this; |
643 | } |
644 | |
645 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
646 | unique_ptr& |
647 | operator=(nullptr_t) noexcept |
648 | { |
649 | reset(); |
650 | return *this; |
651 | } |
652 | |
653 | // Observers. |
654 | |
655 | /// Access an element of owned array. |
656 | typename std::add_lvalue_reference<element_type>::type |
657 | operator[](size_t __i) const |
658 | { |
659 | __glibcxx_assert(get() != pointer()); |
660 | return get()[__i]; |
661 | } |
662 | |
663 | /// Return the stored pointer. |
664 | pointer |
665 | get() const noexcept |
666 | { return _M_t._M_ptr(); } |
667 | |
668 | /// Return a reference to the stored deleter. |
669 | deleter_type& |
670 | get_deleter() noexcept |
671 | { return _M_t._M_deleter(); } |
672 | |
673 | /// Return a reference to the stored deleter. |
674 | const deleter_type& |
675 | get_deleter() const noexcept |
676 | { return _M_t._M_deleter(); } |
677 | |
678 | /// Return @c true if the stored pointer is not null. |
679 | explicit operator bool() const noexcept |
680 | { return get() == pointer() ? false : true; } |
681 | |
682 | // Modifiers. |
683 | |
684 | /// Release ownership of any stored pointer. |
685 | pointer |
686 | release() noexcept |
687 | { return _M_t.release(); } |
688 | |
689 | /** @brief Replace the stored pointer. |
690 | * |
691 | * @param __p The new pointer to store. |
692 | * |
693 | * The deleter will be invoked if a pointer is already owned. |
694 | */ |
695 | template <typename _Up, |
696 | typename = _Require< |
697 | __or_<is_same<_Up, pointer>, |
698 | __and_<is_same<pointer, element_type*>, |
699 | is_pointer<_Up>, |
700 | is_convertible< |
701 | typename remove_pointer<_Up>::type(*)[], |
702 | element_type(*)[] |
703 | > |
704 | > |
705 | > |
706 | >> |
707 | void |
708 | reset(_Up __p) noexcept |
709 | { _M_t.reset(std::move(__p)); } |
710 | |
711 | void reset(nullptr_t = nullptr) noexcept |
712 | { reset(pointer()); } |
713 | |
714 | /// Exchange the pointer and deleter with another object. |
715 | void |
716 | swap(unique_ptr& __u) noexcept |
717 | { |
718 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
719 | _M_t.swap(__u._M_t); |
720 | } |
721 | |
722 | // Disable copy from lvalue. |
723 | unique_ptr(const unique_ptr&) = delete; |
724 | unique_ptr& operator=(const unique_ptr&) = delete; |
725 | }; |
726 | |
727 | /// @relates unique_ptr @{ |
728 | |
729 | /// Swap overload for unique_ptr |
730 | template<typename _Tp, typename _Dp> |
731 | inline |
732 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
733 | // Constrained free swap overload, see p0185r1 |
734 | typename enable_if<__is_swappable<_Dp>::value>::type |
735 | #else |
736 | void |
737 | #endif |
738 | swap(unique_ptr<_Tp, _Dp>& __x, |
739 | unique_ptr<_Tp, _Dp>& __y) noexcept |
740 | { __x.swap(__y); } |
741 | |
742 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
743 | template<typename _Tp, typename _Dp> |
744 | typename enable_if<!__is_swappable<_Dp>::value>::type |
745 | swap(unique_ptr<_Tp, _Dp>&, |
746 | unique_ptr<_Tp, _Dp>&) = delete; |
747 | #endif |
748 | |
749 | /// Equality operator for unique_ptr objects, compares the owned pointers |
750 | template<typename _Tp, typename _Dp, |
751 | typename _Up, typename _Ep> |
752 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
753 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
754 | const unique_ptr<_Up, _Ep>& __y) |
755 | { return __x.get() == __y.get(); } |
756 | |
757 | /// unique_ptr comparison with nullptr |
758 | template<typename _Tp, typename _Dp> |
759 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
760 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
761 | { return !__x; } |
762 | |
763 | #ifndef __cpp_lib_three_way_comparison |
764 | /// unique_ptr comparison with nullptr |
765 | template<typename _Tp, typename _Dp> |
766 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
767 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
768 | { return !__x; } |
769 | |
770 | /// Inequality operator for unique_ptr objects, compares the owned pointers |
771 | template<typename _Tp, typename _Dp, |
772 | typename _Up, typename _Ep> |
773 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
774 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
775 | const unique_ptr<_Up, _Ep>& __y) |
776 | { return __x.get() != __y.get(); } |
777 | |
778 | /// unique_ptr comparison with nullptr |
779 | template<typename _Tp, typename _Dp> |
780 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
781 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
782 | { return (bool)__x; } |
783 | |
784 | /// unique_ptr comparison with nullptr |
785 | template<typename _Tp, typename _Dp> |
786 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
787 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
788 | { return (bool)__x; } |
789 | #endif // three way comparison |
790 | |
791 | /// Relational operator for unique_ptr objects, compares the owned pointers |
792 | template<typename _Tp, typename _Dp, |
793 | typename _Up, typename _Ep> |
794 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
795 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
796 | const unique_ptr<_Up, _Ep>& __y) |
797 | { |
798 | typedef typename |
799 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
800 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
801 | return std::less<_CT>()(__x.get(), __y.get()); |
802 | } |
803 | |
804 | /// unique_ptr comparison with nullptr |
805 | template<typename _Tp, typename _Dp> |
806 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
807 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
808 | { |
809 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
810 | nullptr); |
811 | } |
812 | |
813 | /// unique_ptr comparison with nullptr |
814 | template<typename _Tp, typename _Dp> |
815 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
816 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
817 | { |
818 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
819 | __x.get()); |
820 | } |
821 | |
822 | /// Relational operator for unique_ptr objects, compares the owned pointers |
823 | template<typename _Tp, typename _Dp, |
824 | typename _Up, typename _Ep> |
825 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
826 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
827 | const unique_ptr<_Up, _Ep>& __y) |
828 | { return !(__y < __x); } |
829 | |
830 | /// unique_ptr comparison with nullptr |
831 | template<typename _Tp, typename _Dp> |
832 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
833 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
834 | { return !(nullptr < __x); } |
835 | |
836 | /// unique_ptr comparison with nullptr |
837 | template<typename _Tp, typename _Dp> |
838 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
839 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
840 | { return !(__x < nullptr); } |
841 | |
842 | /// Relational operator for unique_ptr objects, compares the owned pointers |
843 | template<typename _Tp, typename _Dp, |
844 | typename _Up, typename _Ep> |
845 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
846 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
847 | const unique_ptr<_Up, _Ep>& __y) |
848 | { return (__y < __x); } |
849 | |
850 | /// unique_ptr comparison with nullptr |
851 | template<typename _Tp, typename _Dp> |
852 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
853 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
854 | { |
855 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
856 | __x.get()); |
857 | } |
858 | |
859 | /// unique_ptr comparison with nullptr |
860 | template<typename _Tp, typename _Dp> |
861 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
862 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
863 | { |
864 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
865 | nullptr); |
866 | } |
867 | |
868 | /// Relational operator for unique_ptr objects, compares the owned pointers |
869 | template<typename _Tp, typename _Dp, |
870 | typename _Up, typename _Ep> |
871 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
872 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
873 | const unique_ptr<_Up, _Ep>& __y) |
874 | { return !(__x < __y); } |
875 | |
876 | /// unique_ptr comparison with nullptr |
877 | template<typename _Tp, typename _Dp> |
878 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
879 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
880 | { return !(__x < nullptr); } |
881 | |
882 | /// unique_ptr comparison with nullptr |
883 | template<typename _Tp, typename _Dp> |
884 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
885 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
886 | { return !(nullptr < __x); } |
887 | |
888 | #ifdef __cpp_lib_three_way_comparison |
889 | template<typename _Tp, typename _Dp, typename _Up, typename _Ep> |
890 | requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer, |
891 | typename unique_ptr<_Up, _Ep>::pointer> |
892 | inline |
893 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer, |
894 | typename unique_ptr<_Up, _Ep>::pointer> |
895 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, |
896 | const unique_ptr<_Up, _Ep>& __y) |
897 | { return compare_three_way()(__x.get(), __y.get()); } |
898 | |
899 | template<typename _Tp, typename _Dp> |
900 | requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer> |
901 | inline |
902 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer> |
903 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
904 | { |
905 | using pointer = typename unique_ptr<_Tp, _Dp>::pointer; |
906 | return compare_three_way()(__x.get(), static_cast<pointer>(nullptr)); |
907 | } |
908 | #endif |
909 | // @} relates unique_ptr |
910 | |
911 | /// @cond undocumented |
912 | template<typename _Up, typename _Ptr = typename _Up::pointer, |
913 | bool = __poison_hash<_Ptr>::__enable_hash_call> |
914 | struct __uniq_ptr_hash |
915 | #if ! _GLIBCXX_INLINE_VERSION0 |
916 | : private __poison_hash<_Ptr> |
917 | #endif |
918 | { |
919 | size_t |
920 | operator()(const _Up& __u) const |
921 | noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>()))) |
922 | { return hash<_Ptr>()(__u.get()); } |
923 | }; |
924 | |
925 | template<typename _Up, typename _Ptr> |
926 | struct __uniq_ptr_hash<_Up, _Ptr, false> |
927 | : private __poison_hash<_Ptr> |
928 | { }; |
929 | /// @endcond |
930 | |
931 | /// std::hash specialization for unique_ptr. |
932 | template<typename _Tp, typename _Dp> |
933 | struct hash<unique_ptr<_Tp, _Dp>> |
934 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
935 | public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>> |
936 | { }; |
937 | |
938 | #if __cplusplus201703L >= 201402L |
939 | /// @relates unique_ptr @{ |
940 | #define __cpp_lib_make_unique201304 201304 |
941 | |
942 | /// @cond undocumented |
943 | |
944 | template<typename _Tp> |
945 | struct _MakeUniq |
946 | { typedef unique_ptr<_Tp> __single_object; }; |
947 | |
948 | template<typename _Tp> |
949 | struct _MakeUniq<_Tp[]> |
950 | { typedef unique_ptr<_Tp[]> __array; }; |
951 | |
952 | template<typename _Tp, size_t _Bound> |
953 | struct _MakeUniq<_Tp[_Bound]> |
954 | { struct __invalid_type { }; }; |
955 | |
956 | /// @endcond |
957 | |
958 | /// std::make_unique for single objects |
959 | template<typename _Tp, typename... _Args> |
960 | inline typename _MakeUniq<_Tp>::__single_object |
961 | make_unique(_Args&&... __args) |
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
963 | |
964 | /// std::make_unique for arrays of unknown bound |
965 | template<typename _Tp> |
966 | inline typename _MakeUniq<_Tp>::__array |
967 | make_unique(size_t __num) |
968 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
969 | |
970 | /// Disable std::make_unique for arrays of known bound |
971 | template<typename _Tp, typename... _Args> |
972 | inline typename _MakeUniq<_Tp>::__invalid_type |
973 | make_unique(_Args&&...) = delete; |
974 | // @} relates unique_ptr |
975 | #endif // C++14 |
976 | |
977 | #if __cplusplus201703L > 201703L && __cpp_concepts |
978 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
979 | // 2948. unique_ptr does not define operator<< for stream output |
980 | /// Stream output operator for unique_ptr |
981 | template<typename _CharT, typename _Traits, typename _Tp, typename _Dp> |
982 | inline basic_ostream<_CharT, _Traits>& |
983 | operator<<(basic_ostream<_CharT, _Traits>& __os, |
984 | const unique_ptr<_Tp, _Dp>& __p) |
985 | requires requires { __os << __p.get(); } |
986 | { |
987 | __os << __p.get(); |
988 | return __os; |
989 | } |
990 | #endif // C++20 |
991 | |
992 | // @} group pointer_abstractions |
993 | |
994 | #if __cplusplus201703L >= 201703L |
995 | namespace __detail::__variant |
996 | { |
997 | template<typename> struct _Never_valueless_alt; // see <variant> |
998 | |
999 | // Provide the strong exception-safety guarantee when emplacing a |
1000 | // unique_ptr into a variant. |
1001 | template<typename _Tp, typename _Del> |
1002 | struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>> |
1003 | : std::true_type |
1004 | { }; |
1005 | } // namespace __detail::__variant |
1006 | #endif // C++17 |
1007 | |
1008 | _GLIBCXX_END_NAMESPACE_VERSION |
1009 | } // namespace |
1010 | |
1011 | #endif /* _UNIQUE_PTR_H */ |
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 | #ifndef INCLUDED_VCL_PTR_HXX |
21 | #define INCLUDED_VCL_PTR_HXX |
22 | |
23 | #include <sal/config.h> |
24 | |
25 | #include <rtl/ref.hxx> |
26 | |
27 | #include <utility> |
28 | #include <type_traits> |
29 | |
30 | #ifdef DBG_UTIL |
31 | #ifndef _WIN32 |
32 | #include <vcl/vclmain.hxx> |
33 | #endif |
34 | #endif |
35 | |
36 | class VclReferenceBase; |
37 | |
38 | namespace vcl::detail { |
39 | |
40 | template<typename> |
41 | constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; } |
42 | |
43 | template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase( |
44 | int (*)[sizeof(T)]) |
45 | { return std::is_base_of<VclReferenceBase, T>::value; } |
46 | |
47 | } // namespace vcl::detail |
48 | |
49 | /** |
50 | * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. |
51 | * |
52 | * For more details on the design please see vcl/README.lifecycle |
53 | * |
54 | * @param reference_type must be a subclass of vcl::Window |
55 | */ |
56 | template <class reference_type> |
57 | class VclPtr |
58 | { |
59 | static_assert( |
60 | vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>( |
61 | nullptr), |
62 | "template argument type must be derived from VclReferenceBase"); |
63 | |
64 | ::rtl::Reference<reference_type> m_rInnerRef; |
65 | |
66 | public: |
67 | /** Constructor... |
68 | */ |
69 | VclPtr() |
70 | : m_rInnerRef() |
71 | {} |
72 | |
73 | /** Constructor... |
74 | */ |
75 | VclPtr (reference_type * pBody) |
76 | : m_rInnerRef(pBody) |
77 | {} |
78 | |
79 | /** Constructor... that doesn't take a ref. |
80 | */ |
81 | VclPtr (reference_type * pBody, __sal_NoAcquire) |
82 | : m_rInnerRef(pBody, SAL_NO_ACQUIRE) |
83 | {} |
84 | |
85 | /** Up-casting conversion constructor: Copies interface reference. |
86 | |
87 | Does not work for up-casts to ambiguous bases. For the special case of |
88 | up-casting to Reference< XInterface >, see the corresponding conversion |
89 | operator. |
90 | |
91 | @param rRef another reference |
92 | */ |
93 | template< class derived_type > |
94 | VclPtr( |
95 | const VclPtr< derived_type > & rRef, |
96 | typename std::enable_if< |
97 | std::is_base_of<reference_type, derived_type>::value, int>::type |
98 | = 0 ) |
99 | : m_rInnerRef( static_cast<reference_type*>(rRef) ) |
100 | { |
101 | } |
102 | |
103 | #if defined(DBG_UTIL) && !defined(_WIN32) |
104 | virtual ~VclPtr() |
105 | { |
106 | assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain ::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 106, __extension__ __PRETTY_FUNCTION__)); |
107 | // We can be one of the intermediate counts, but if we are the last |
108 | // VclPtr keeping this object alive, then something forgot to call dispose(). |
109 | assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)) |
110 | && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef ->isDisposed() || m_rInnerRef->getRefCount() > 1) && "someone forgot to call dispose()") ? void (0) : __assert_fail ("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\"" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 110, __extension__ __PRETTY_FUNCTION__)); |
111 | } |
112 | VclPtr(VclPtr const &) = default; |
113 | VclPtr(VclPtr &&) = default; |
114 | VclPtr & operator =(VclPtr const &) = default; |
115 | VclPtr & operator =(VclPtr &&) = default; |
116 | #endif |
117 | |
118 | /** |
119 | * A construction helper for VclPtr. Since VclPtr types are created |
120 | * with a reference-count of one - to help fit into the existing |
121 | * code-flow; this helps us to construct them easily. |
122 | * |
123 | * For more details on the design please see vcl/README.lifecycle |
124 | * |
125 | * @tparam reference_type must be a subclass of vcl::Window |
126 | */ |
127 | template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg) |
128 | { |
129 | return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ); |
130 | } |
131 | |
132 | /** Probably most common used: handle->someBodyOp(). |
133 | */ |
134 | reference_type * operator->() const |
135 | { |
136 | return m_rInnerRef.get(); |
137 | } |
138 | |
139 | /** Get the body. Can be used instead of operator->(). |
140 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() |
141 | are the same. |
142 | */ |
143 | reference_type * get() const |
144 | { |
145 | return m_rInnerRef.get(); |
146 | } |
147 | |
148 | void set(reference_type *pBody) |
149 | { |
150 | m_rInnerRef.set(pBody); |
151 | } |
152 | |
153 | void reset(reference_type *pBody) |
154 | { |
155 | m_rInnerRef.set(pBody); |
156 | } |
157 | |
158 | /** Up-casting copy assignment operator. |
159 | |
160 | Does not work for up-casts to ambiguous bases. |
161 | |
162 | @param rRef another reference |
163 | */ |
164 | template<typename derived_type> |
165 | typename std::enable_if< |
166 | std::is_base_of<reference_type, derived_type>::value, |
167 | VclPtr &>::type |
168 | operator =(VclPtr<derived_type> const & rRef) |
169 | { |
170 | m_rInnerRef.set(rRef.get()); |
171 | return *this; |
172 | } |
173 | |
174 | VclPtr & operator =(reference_type * pBody) |
175 | { |
176 | m_rInnerRef.set(pBody); |
177 | return *this; |
178 | } |
179 | |
180 | operator reference_type * () const |
181 | { |
182 | return m_rInnerRef.get(); |
183 | } |
184 | |
185 | explicit operator bool () const |
186 | { |
187 | return m_rInnerRef.get() != nullptr; |
188 | } |
189 | |
190 | void clear() |
191 | { |
192 | m_rInnerRef.clear(); |
193 | } |
194 | |
195 | void reset() |
196 | { |
197 | m_rInnerRef.clear(); |
198 | } |
199 | |
200 | void disposeAndClear() |
201 | { |
202 | // hold it alive for the lifetime of this method |
203 | ::rtl::Reference<reference_type> aTmp(m_rInnerRef); |
204 | m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-) |
205 | if (aTmp.get()) { |
206 | aTmp->disposeOnce(); |
207 | } |
208 | } |
209 | |
210 | /** Needed to place VclPtr's into STL collection. |
211 | */ |
212 | bool operator< (const VclPtr<reference_type> & handle) const |
213 | { |
214 | return (m_rInnerRef < handle.m_rInnerRef); |
215 | } |
216 | }; // class VclPtr |
217 | |
218 | template<typename T1, typename T2> |
219 | inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
220 | return p1.get() == p2.get(); |
221 | } |
222 | |
223 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2) |
224 | { |
225 | return p1.get() == p2; |
226 | } |
227 | |
228 | template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) { |
229 | return p1.get() == p2; |
230 | } |
231 | |
232 | template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2) |
233 | { |
234 | return p1 == p2.get(); |
235 | } |
236 | |
237 | template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) { |
238 | return p1 == p2.get(); |
239 | } |
240 | |
241 | template<typename T1, typename T2> |
242 | inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) { |
243 | return !(p1 == p2); |
244 | } |
245 | |
246 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2) |
247 | { |
248 | return !(p1 == p2); |
249 | } |
250 | |
251 | template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) { |
252 | return !(p1 == p2); |
253 | } |
254 | |
255 | template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2) |
256 | { |
257 | return !(p1 == p2); |
258 | } |
259 | |
260 | template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) { |
261 | return !(p1 == p2); |
262 | } |
263 | |
264 | /** |
265 | * A construction helper for a temporary VclPtr. Since VclPtr types |
266 | * are created with a reference-count of one - to help fit into |
267 | * the existing code-flow; this helps us to construct them easily. |
268 | * see also VclPtr::Create and ScopedVclPtr |
269 | * |
270 | * For more details on the design please see vcl/README.lifecycle |
271 | * |
272 | * @param reference_type must be a subclass of vcl::Window |
273 | */ |
274 | template <class reference_type> |
275 | class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type> |
276 | { |
277 | public: |
278 | template<typename... Arg> VclPtrInstance(Arg &&... arg) |
279 | : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
280 | { |
281 | } |
282 | |
283 | /** |
284 | * Override and disallow this, to prevent people accidentally calling it and actually |
285 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
286 | */ |
287 | template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete; |
288 | }; |
289 | |
290 | template <class reference_type> |
291 | class ScopedVclPtr : public VclPtr<reference_type> |
292 | { |
293 | public: |
294 | /** Constructor... |
295 | */ |
296 | ScopedVclPtr() |
297 | : VclPtr<reference_type>() |
298 | {} |
299 | |
300 | /** Constructor |
301 | */ |
302 | ScopedVclPtr (reference_type * pBody) |
303 | : VclPtr<reference_type>(pBody) |
304 | {} |
305 | |
306 | /** Copy constructor... |
307 | */ |
308 | ScopedVclPtr (const VclPtr<reference_type> & handle) |
309 | : VclPtr<reference_type>(handle) |
310 | {} |
311 | |
312 | /** |
313 | Assignment that releases the last reference. |
314 | */ |
315 | void disposeAndReset(reference_type *pBody) |
316 | { |
317 | if (pBody != this->get()) { |
318 | VclPtr<reference_type>::disposeAndClear(); |
319 | VclPtr<reference_type>::set(pBody); |
320 | } |
321 | } |
322 | |
323 | /** |
324 | Assignment that releases the last reference. |
325 | */ |
326 | ScopedVclPtr<reference_type>& operator = (reference_type * pBody) |
327 | { |
328 | disposeAndReset(pBody); |
329 | return *this; |
330 | } |
331 | |
332 | /** Up-casting conversion constructor: Copies interface reference. |
333 | |
334 | Does not work for up-casts to ambiguous bases. For the special case of |
335 | up-casting to Reference< XInterface >, see the corresponding conversion |
336 | operator. |
337 | |
338 | @param rRef another reference |
339 | */ |
340 | template< class derived_type > |
341 | ScopedVclPtr( |
342 | const VclPtr< derived_type > & rRef, |
343 | typename std::enable_if< |
344 | std::is_base_of<reference_type, derived_type>::value, int>::type |
345 | = 0 ) |
346 | : VclPtr<reference_type>( rRef ) |
347 | { |
348 | } |
349 | |
350 | /** Up-casting assignment operator. |
351 | |
352 | Does not work for up-casts to ambiguous bases. |
353 | |
354 | @param rRef another VclPtr |
355 | */ |
356 | template<typename derived_type> |
357 | typename std::enable_if< |
358 | std::is_base_of<reference_type, derived_type>::value, |
359 | ScopedVclPtr &>::type |
360 | operator =(VclPtr<derived_type> const & rRef) |
361 | { |
362 | disposeAndReset(rRef.get()); |
363 | return *this; |
364 | } |
365 | |
366 | /** |
367 | * Override and disallow this, to prevent people accidentally calling it and actually |
368 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
369 | */ |
370 | template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete; |
371 | |
372 | ~ScopedVclPtr() |
373 | { |
374 | VclPtr<reference_type>::disposeAndClear(); |
375 | assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get( ) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr" , "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx" , 375, __extension__ __PRETTY_FUNCTION__)); // make sure there are no lingering references |
376 | } |
377 | |
378 | private: |
379 | // Most likely we don't want this default copy-constructor. |
380 | ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete; |
381 | // And certainly we don't want a default assignment operator. |
382 | ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete; |
383 | // And disallow reset as that doesn't call disposeAndClear on the original reference |
384 | void reset() = delete; |
385 | void reset(reference_type *pBody) = delete; |
386 | |
387 | protected: |
388 | ScopedVclPtr (reference_type * pBody, __sal_NoAcquire) |
389 | : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE) |
390 | {} |
391 | }; |
392 | |
393 | /** |
394 | * A construction helper for ScopedVclPtr. Since VclPtr types are created |
395 | * with a reference-count of one - to help fit into the existing |
396 | * code-flow; this helps us to construct them easily. |
397 | * |
398 | * For more details on the design please see vcl/README.lifecycle |
399 | * |
400 | * @param reference_type must be a subclass of vcl::Window |
401 | */ |
402 | #if defined _MSC_VER |
403 | #pragma warning(push) |
404 | #pragma warning(disable: 4521) // " multiple copy constructors specified" |
405 | #endif |
406 | template <class reference_type> |
407 | class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type> |
408 | { |
409 | public: |
410 | template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg) |
411 | : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE ) |
412 | { |
413 | } |
414 | |
415 | /** |
416 | * Override and disallow this, to prevent people accidentally calling it and actually |
417 | * getting VclPtr::Create and getting a naked VclPtr<> instance |
418 | */ |
419 | template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete; |
420 | |
421 | private: |
422 | // Prevent the above perfect forwarding ctor from hijacking (accidental) |
423 | // attempts at ScopedVclPtrInstance copy construction (where the hijacking |
424 | // would typically lead to somewhat obscure error messages); both non-const |
425 | // and const variants are needed here, as the ScopedVclPtr base class has a |
426 | // const--variant copy ctor, so the implicitly declared copy ctor for |
427 | // ScopedVclPtrInstance would also be the const variant, so non-const copy |
428 | // construction attempts would be hijacked by the perfect forwarding ctor; |
429 | // but if we only declared a non-const variant here, the const variant would |
430 | // no longer be implicitly declared (as there would already be an explicitly |
431 | // declared copy ctor), so const copy construction attempts would then be |
432 | // hijacked by the perfect forwarding ctor: |
433 | ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete; |
434 | ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete; |
435 | }; |
436 | #if defined _MSC_VER |
437 | #pragma warning(pop) |
438 | #endif |
439 | |
440 | #endif // INCLUDED_VCL_PTR_HXX |
441 | |
442 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||||||
22 | |||||||||||
23 | #include "sal/config.h" | ||||||||||
24 | |||||||||||
25 | #include <cassert> | ||||||||||
26 | #include <cstddef> | ||||||||||
27 | #include <functional> | ||||||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||
29 | #include <type_traits> | ||||||||||
30 | #endif | ||||||||||
31 | |||||||||||
32 | #include "sal/types.h" | ||||||||||
33 | |||||||||||
34 | namespace rtl | ||||||||||
35 | { | ||||||||||
36 | |||||||||||
37 | /** Template reference class for reference type. | ||||||||||
38 | */ | ||||||||||
39 | template <class reference_type> | ||||||||||
40 | class Reference | ||||||||||
41 | { | ||||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||||
43 | */ | ||||||||||
44 | reference_type * m_pBody; | ||||||||||
45 | |||||||||||
46 | |||||||||||
47 | public: | ||||||||||
48 | /** Constructor... | ||||||||||
49 | */ | ||||||||||
50 | Reference() | ||||||||||
51 | : m_pBody (NULL__null) | ||||||||||
52 | {} | ||||||||||
53 | |||||||||||
54 | |||||||||||
55 | /** Constructor... | ||||||||||
56 | */ | ||||||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||||||
58 | : m_pBody (pBody) | ||||||||||
59 | { | ||||||||||
60 | } | ||||||||||
61 | |||||||||||
62 | /** Constructor... | ||||||||||
63 | */ | ||||||||||
64 | Reference (reference_type * pBody) | ||||||||||
65 | : m_pBody (pBody) | ||||||||||
66 | { | ||||||||||
67 | if (m_pBody) | ||||||||||
68 | m_pBody->acquire(); | ||||||||||
69 | } | ||||||||||
70 | |||||||||||
71 | /** Copy constructor... | ||||||||||
72 | */ | ||||||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||||||
74 | : m_pBody (handle.m_pBody) | ||||||||||
75 | { | ||||||||||
76 | if (m_pBody) | ||||||||||
77 | m_pBody->acquire(); | ||||||||||
78 | } | ||||||||||
79 | |||||||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||
81 | /** Move constructor... | ||||||||||
82 | */ | ||||||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||||||
84 | : m_pBody (handle.m_pBody) | ||||||||||
85 | { | ||||||||||
86 | handle.m_pBody = nullptr; | ||||||||||
87 | } | ||||||||||
88 | #endif | ||||||||||
89 | |||||||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||||||
92 | |||||||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||||||
94 | |||||||||||
95 | @param rRef another reference | ||||||||||
96 | */ | ||||||||||
97 | template< class derived_type > | ||||||||||
98 | inline Reference( | ||||||||||
99 | const Reference< derived_type > & rRef, | ||||||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||||||
101 | : m_pBody (rRef.get()) | ||||||||||
102 | { | ||||||||||
103 | if (m_pBody) | ||||||||||
104 | m_pBody->acquire(); | ||||||||||
105 | } | ||||||||||
106 | #endif | ||||||||||
107 | |||||||||||
108 | /** Destructor... | ||||||||||
109 | */ | ||||||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||||||
111 | { | ||||||||||
112 | if (m_pBody
| ||||||||||
113 | m_pBody->release(); | ||||||||||
114 | } | ||||||||||
115 | |||||||||||
116 | /** Set... | ||||||||||
117 | Similar to assignment. | ||||||||||
118 | */ | ||||||||||
119 | Reference<reference_type> & | ||||||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||||||
121 | { | ||||||||||
122 | if (pBody) | ||||||||||
123 | pBody->acquire(); | ||||||||||
124 | reference_type * const pOld = m_pBody; | ||||||||||
125 | m_pBody = pBody; | ||||||||||
126 | if (pOld) | ||||||||||
127 | pOld->release(); | ||||||||||
128 | return *this; | ||||||||||
129 | } | ||||||||||
130 | |||||||||||
131 | /** Assignment. | ||||||||||
132 | Unbinds this instance from its body (if bound) and | ||||||||||
133 | bind it to the body represented by the handle. | ||||||||||
134 | */ | ||||||||||
135 | Reference<reference_type> & | ||||||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||||||
137 | { | ||||||||||
138 | return set( handle.m_pBody ); | ||||||||||
139 | } | ||||||||||
140 | |||||||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||
142 | /** Assignment. | ||||||||||
143 | * Unbinds this instance from its body (if bound), | ||||||||||
144 | * bind it to the body represented by the handle, and | ||||||||||
145 | * set the body represented by the handle to nullptr. | ||||||||||
146 | */ | ||||||||||
147 | Reference<reference_type> & | ||||||||||
148 | operator= (Reference<reference_type> && handle) | ||||||||||
149 | { | ||||||||||
150 | // self-movement guts ourself | ||||||||||
151 | if (m_pBody) | ||||||||||
152 | m_pBody->release(); | ||||||||||
153 | m_pBody = handle.m_pBody; | ||||||||||
154 | handle.m_pBody = nullptr; | ||||||||||
155 | return *this; | ||||||||||
156 | } | ||||||||||
157 | #endif | ||||||||||
158 | |||||||||||
159 | /** Assignment... | ||||||||||
160 | */ | ||||||||||
161 | Reference<reference_type> & | ||||||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||||||
163 | { | ||||||||||
164 | return set( pBody ); | ||||||||||
165 | } | ||||||||||
166 | |||||||||||
167 | /** Unbind the body from this handle. | ||||||||||
168 | Note that for a handle representing a large body, | ||||||||||
169 | "handle.clear().set(new body());" _might_ | ||||||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||||||
171 | since in the second case two large objects exist in memory | ||||||||||
172 | (the old body and the new body). | ||||||||||
173 | */ | ||||||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||||||
175 | { | ||||||||||
176 | if (m_pBody) | ||||||||||
177 | { | ||||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||||
179 | m_pBody = NULL__null; | ||||||||||
180 | pOld->release(); | ||||||||||
181 | } | ||||||||||
182 | return *this; | ||||||||||
183 | } | ||||||||||
184 | |||||||||||
185 | |||||||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||||||
188 | are the same. | ||||||||||
189 | */ | ||||||||||
190 | reference_type * SAL_CALL get() const | ||||||||||
191 | { | ||||||||||
192 | return m_pBody; | ||||||||||
| |||||||||||
193 | } | ||||||||||
194 | |||||||||||
195 | |||||||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||||||
197 | */ | ||||||||||
198 | reference_type * SAL_CALL operator->() const | ||||||||||
199 | { | ||||||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||||||
201 | return m_pBody; | ||||||||||
202 | } | ||||||||||
203 | |||||||||||
204 | |||||||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||||||
206 | */ | ||||||||||
207 | reference_type & SAL_CALL operator*() const | ||||||||||
208 | { | ||||||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||||||
210 | return *m_pBody; | ||||||||||
211 | } | ||||||||||
212 | |||||||||||
213 | |||||||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||||||
215 | */ | ||||||||||
216 | bool SAL_CALL is() const | ||||||||||
217 | { | ||||||||||
218 | return (m_pBody != NULL__null); | ||||||||||
219 | } | ||||||||||
220 | |||||||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||||||
223 | */ | ||||||||||
224 | explicit operator bool() const | ||||||||||
225 | { | ||||||||||
226 | return is(); | ||||||||||
227 | } | ||||||||||
228 | #endif | ||||||||||
229 | |||||||||||
230 | /** Returns True if this points to pBody. | ||||||||||
231 | */ | ||||||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||||||
233 | { | ||||||||||
234 | return (m_pBody == pBody); | ||||||||||
235 | } | ||||||||||
236 | |||||||||||
237 | |||||||||||
238 | /** Returns True if handle points to the same body. | ||||||||||
239 | */ | ||||||||||
240 | bool | ||||||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||||||
242 | { | ||||||||||
243 | return (m_pBody == handle.m_pBody); | ||||||||||
244 | } | ||||||||||
245 | |||||||||||
246 | |||||||||||
247 | /** Needed to place References into STL collection. | ||||||||||
248 | */ | ||||||||||
249 | bool | ||||||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||||||
251 | { | ||||||||||
252 | return (m_pBody != handle.m_pBody); | ||||||||||
253 | } | ||||||||||
254 | |||||||||||
255 | |||||||||||
256 | /** Needed to place References into STL collection. | ||||||||||
257 | */ | ||||||||||
258 | bool | ||||||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||||||
260 | { | ||||||||||
261 | return (m_pBody < handle.m_pBody); | ||||||||||
262 | } | ||||||||||
263 | |||||||||||
264 | |||||||||||
265 | /** Needed to place References into STL collection. | ||||||||||
266 | */ | ||||||||||
267 | bool | ||||||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||||||
269 | { | ||||||||||
270 | return (m_pBody > handle.m_pBody); | ||||||||||
271 | } | ||||||||||
272 | }; | ||||||||||
273 | |||||||||||
274 | } // namespace rtl | ||||||||||
275 | |||||||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||
277 | namespace std | ||||||||||
278 | { | ||||||||||
279 | |||||||||||
280 | /// @cond INTERNAL | ||||||||||
281 | /** | ||||||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||||||
283 | |||||||||||
284 | @since LibreOffice 6.3 | ||||||||||
285 | */ | ||||||||||
286 | template<typename T> | ||||||||||
287 | struct hash<::rtl::Reference<T>> | ||||||||||
288 | { | ||||||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||||||
290 | { return std::size_t(s.get()); } | ||||||||||
291 | }; | ||||||||||
292 | /// @endcond | ||||||||||
293 | |||||||||||
294 | } | ||||||||||
295 | |||||||||||
296 | #endif | ||||||||||
297 | |||||||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||||||
299 | |||||||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |