File: | home/maarten/src/libreoffice/core/include/tools/ref.hxx |
Warning: | line 97, column 56 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 <svtools/editbrowsebox.hxx> | ||||
21 | |||||
22 | #include <tools/debug.hxx> | ||||
23 | #include <vcl/image.hxx> | ||||
24 | #include <vcl/settings.hxx> | ||||
25 | #include <vcl/window.hxx> | ||||
26 | #include <vcl/svapp.hxx> | ||||
27 | |||||
28 | #include <bitmaps.hlst> | ||||
29 | |||||
30 | #include <algorithm> | ||||
31 | #include "editbrowseboximpl.hxx" | ||||
32 | #include <com/sun/star/accessibility/AccessibleEventId.hpp> | ||||
33 | |||||
34 | |||||
35 | namespace svt | ||||
36 | { | ||||
37 | |||||
38 | namespace | ||||
39 | { | ||||
40 | |||||
41 | GetFocusFlags getRealGetFocusFlags( vcl::Window* _pWindow ) | ||||
42 | { | ||||
43 | GetFocusFlags nFlags = GetFocusFlags::NONE; | ||||
44 | while ( _pWindow && nFlags == GetFocusFlags::NONE ) | ||||
45 | { | ||||
46 | nFlags = _pWindow->GetGetFocusFlags( ); | ||||
47 | _pWindow = _pWindow->GetParent(); | ||||
48 | } | ||||
49 | return nFlags; | ||||
50 | } | ||||
51 | } | ||||
52 | |||||
53 | using namespace ::com::sun::star::uno; | ||||
54 | using namespace com::sun::star::accessibility::AccessibleEventId; | ||||
55 | |||||
56 | |||||
57 | IEditImplementation::~IEditImplementation() | ||||
58 | { | ||||
59 | } | ||||
60 | |||||
61 | //= EditBrowserHeader | ||||
62 | |||||
63 | void EditBrowserHeader::DoubleClick() | ||||
64 | { | ||||
65 | sal_uInt16 nColId = GetCurItemId(); | ||||
66 | if (nColId) | ||||
67 | { | ||||
68 | sal_uInt32 nAutoWidth = static_cast<EditBrowseBox*>(GetParent())->GetAutoColumnWidth(nColId); | ||||
69 | if (nAutoWidth != static_cast<EditBrowseBox*>(GetParent())->GetColumnWidth(nColId)) | ||||
70 | { | ||||
71 | static_cast<EditBrowseBox*>(GetParent())->SetColumnWidth(nColId, nAutoWidth); | ||||
72 | static_cast<EditBrowseBox*>(GetParent())->ColumnResized(nColId); | ||||
73 | } | ||||
74 | } | ||||
75 | } | ||||
76 | |||||
77 | //= EditBrowseBox | ||||
78 | |||||
79 | void EditBrowseBox::BrowserMouseEventPtr::Clear() | ||||
80 | { | ||||
81 | pEvent.reset(); | ||||
82 | } | ||||
83 | |||||
84 | void EditBrowseBox::BrowserMouseEventPtr::Set(const BrowserMouseEvent* pEvt, bool bIsDown) | ||||
85 | { | ||||
86 | if (pEvt == pEvent.get()) | ||||
87 | { | ||||
88 | bDown = bIsDown; | ||||
89 | return; | ||||
90 | } | ||||
91 | pEvent.reset(); | ||||
92 | if (pEvt) | ||||
93 | { | ||||
94 | pEvent.reset(new BrowserMouseEvent(pEvt->GetWindow(), | ||||
95 | *pEvt, | ||||
96 | pEvt->GetRow(), | ||||
97 | pEvt->GetColumn(), | ||||
98 | pEvt->GetColumnId(), | ||||
99 | pEvt->GetRect())); | ||||
100 | bDown = bIsDown; | ||||
101 | } | ||||
102 | } | ||||
103 | |||||
104 | EditBrowseBox::EditBrowseBox( vcl::Window* pParent, EditBrowseBoxFlags nBrowserFlags, WinBits nBits, BrowserMode _nMode ) | ||||
105 | :BrowseBox( pParent, nBits, _nMode ) | ||||
106 | ,nStartEvent(nullptr) | ||||
107 | ,nEndEvent(nullptr) | ||||
108 | ,nCellModifiedEvent(nullptr) | ||||
109 | ,m_pFocusWhileRequest(nullptr) | ||||
110 | ,nPaintRow(-1) | ||||
111 | ,nEditRow(-1) | ||||
112 | ,nEditCol(0) | ||||
113 | ,bHasFocus(false) | ||||
114 | ,bPaintStatus(true) | ||||
115 | ,bActiveBeforeTracking( false ) | ||||
116 | ,m_nBrowserFlags(nBrowserFlags) | ||||
117 | ,pHeader(nullptr) | ||||
118 | { | ||||
119 | m_aImpl.reset(new EditBrowseBoxImpl); | ||||
120 | |||||
121 | SetCompoundControl(true); | ||||
122 | |||||
123 | ImplInitSettings(true, true, true); | ||||
124 | |||||
125 | pCheckBoxPaint = VclPtr<CheckBoxControl>::Create(&GetDataWindow()); | ||||
126 | pCheckBoxPaint->SetPaintTransparent( true ); | ||||
127 | pCheckBoxPaint->SetBackground(); | ||||
128 | } | ||||
129 | |||||
130 | void EditBrowseBox::Init() | ||||
131 | { | ||||
132 | // late construction | ||||
133 | } | ||||
134 | |||||
135 | EditBrowseBox::~EditBrowseBox() | ||||
136 | { | ||||
137 | disposeOnce(); | ||||
138 | } | ||||
139 | |||||
140 | void EditBrowseBox::dispose() | ||||
141 | { | ||||
142 | if (nStartEvent) | ||||
143 | Application::RemoveUserEvent(nStartEvent); | ||||
144 | if (nEndEvent) | ||||
145 | Application::RemoveUserEvent(nEndEvent); | ||||
146 | if (nCellModifiedEvent) | ||||
147 | Application::RemoveUserEvent(nCellModifiedEvent); | ||||
148 | |||||
149 | pCheckBoxPaint.disposeAndClear(); | ||||
150 | m_pFocusWhileRequest.clear(); | ||||
151 | pHeader.clear(); | ||||
152 | BrowseBox::dispose(); | ||||
153 | } | ||||
154 | |||||
155 | |||||
156 | void EditBrowseBox::RemoveRows() | ||||
157 | { | ||||
158 | BrowseBox::Clear(); | ||||
159 | nEditRow = nPaintRow = -1; | ||||
160 | nEditCol = 0; | ||||
161 | } | ||||
162 | |||||
163 | |||||
164 | VclPtr<BrowserHeader> EditBrowseBox::CreateHeaderBar(BrowseBox* pParent) | ||||
165 | { | ||||
166 | pHeader = imp_CreateHeaderBar(pParent); | ||||
167 | if (!IsUpdateMode()) | ||||
168 | pHeader->SetUpdateMode(false); | ||||
169 | return pHeader; | ||||
170 | } | ||||
171 | |||||
172 | |||||
173 | VclPtr<BrowserHeader> EditBrowseBox::imp_CreateHeaderBar(BrowseBox* pParent) | ||||
174 | { | ||||
175 | return VclPtr<EditBrowserHeader>::Create(pParent); | ||||
176 | } | ||||
177 | |||||
178 | |||||
179 | void EditBrowseBox::LoseFocus() | ||||
180 | { | ||||
181 | BrowseBox::LoseFocus(); | ||||
182 | DetermineFocus(); | ||||
183 | } | ||||
184 | |||||
185 | |||||
186 | void EditBrowseBox::GetFocus() | ||||
187 | { | ||||
188 | BrowseBox::GetFocus(); | ||||
189 | |||||
190 | // This should handle the case that the BrowseBox (or one of its children) | ||||
191 | // gets the focus from outside by pressing Tab | ||||
192 | if (IsEditing() && Controller()->GetWindow().IsVisible()) | ||||
193 | Controller()->GetWindow().GrabFocus(); | ||||
194 | |||||
195 | DetermineFocus( getRealGetFocusFlags( this ) ); | ||||
196 | } | ||||
197 | |||||
198 | |||||
199 | bool EditBrowseBox::SeekRow(long nRow) | ||||
200 | { | ||||
201 | nPaintRow = nRow; | ||||
202 | return true; | ||||
203 | } | ||||
204 | |||||
205 | |||||
206 | IMPL_LINK_NOARG(EditBrowseBox, StartEditHdl, void*, void)void EditBrowseBox::LinkStubStartEditHdl(void * instance, void * data) { return static_cast<EditBrowseBox *>(instance) ->StartEditHdl(data); } void EditBrowseBox::StartEditHdl(__attribute__ ((unused)) void*) | ||||
207 | { | ||||
208 | nStartEvent = nullptr; | ||||
209 | if (IsEditing()) | ||||
210 | { | ||||
211 | EnableAndShow(); | ||||
212 | if (!ControlHasFocus() && (m_pFocusWhileRequest.get() == Application::GetFocusWindow())) | ||||
213 | aController->GetWindow().GrabFocus(); | ||||
214 | } | ||||
215 | } | ||||
216 | |||||
217 | void EditBrowseBox::PaintField( vcl::RenderContext& rDev, const tools::Rectangle& rRect, | ||||
218 | sal_uInt16 nColumnId ) const | ||||
219 | { | ||||
220 | if (nColumnId == HandleColumnId) | ||||
221 | { | ||||
222 | if (bPaintStatus) | ||||
223 | PaintStatusCell(rDev, rRect); | ||||
224 | } | ||||
225 | else | ||||
226 | { | ||||
227 | // don't paint the current cell | ||||
228 | if (&rDev == &GetDataWindow()) | ||||
229 | // but only if we're painting onto our data win (which is the usual painting) | ||||
230 | if (nPaintRow == nEditRow) | ||||
231 | { | ||||
232 | if (IsEditing() && nEditCol == nColumnId && aController->GetWindow().IsVisible()) | ||||
233 | return; | ||||
234 | } | ||||
235 | PaintCell(rDev, rRect, nColumnId); | ||||
236 | } | ||||
237 | } | ||||
238 | |||||
239 | Image EditBrowseBox::GetImage(RowStatus eStatus) const | ||||
240 | { | ||||
241 | BitmapEx aBitmap; | ||||
242 | bool bNeedMirror = IsRTLEnabled(); | ||||
243 | switch (eStatus) | ||||
244 | { | ||||
245 | case CURRENT: | ||||
246 | aBitmap = BitmapEx(BMP_CURRENT"svtools/res/ed01.png"); | ||||
247 | break; | ||||
248 | case CURRENTNEW: | ||||
249 | aBitmap = BitmapEx(BMP_CURRENTNEW"svtools/res/ed05.png"); | ||||
250 | break; | ||||
251 | case MODIFIED: | ||||
252 | aBitmap = BitmapEx(BMP_MODIFIED"svtools/res/ed02.png"); | ||||
253 | bNeedMirror = false; // the pen is not mirrored | ||||
254 | break; | ||||
255 | case NEW: | ||||
256 | aBitmap = BitmapEx(BMP_NEW"svtools/res/ed03.png"); | ||||
257 | break; | ||||
258 | case DELETED: | ||||
259 | aBitmap = BitmapEx(BMP_DELETED"svtools/res/ed04.png"); | ||||
260 | break; | ||||
261 | case PRIMARYKEY: | ||||
262 | aBitmap = BitmapEx(BMP_PRIMARYKEY"svtools/res/ed06.png"); | ||||
263 | break; | ||||
264 | case CURRENT_PRIMARYKEY: | ||||
265 | aBitmap = BitmapEx(BMP_CURRENT_PRIMARYKEY"svtools/res/ed07.png"); | ||||
266 | break; | ||||
267 | case FILTER: | ||||
268 | aBitmap = BitmapEx(BMP_FILTER"svtools/res/ed08.png"); | ||||
269 | break; | ||||
270 | case HEADERFOOTER: | ||||
271 | aBitmap = BitmapEx(BMP_HEADERFOOTER"svtools/res/ed09.png"); | ||||
272 | break; | ||||
273 | case CLEAN: | ||||
274 | break; | ||||
275 | } | ||||
276 | if ( bNeedMirror ) | ||||
277 | { | ||||
278 | aBitmap.Mirror( BmpMirrorFlags::Horizontal ); | ||||
279 | } | ||||
280 | return Image(aBitmap); | ||||
281 | } | ||||
282 | |||||
283 | void EditBrowseBox::PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const | ||||
284 | { | ||||
285 | if (nPaintRow < 0) | ||||
286 | return; | ||||
287 | |||||
288 | RowStatus eStatus = GetRowStatus( nPaintRow ); | ||||
289 | EditBrowseBoxFlags nBrowserFlags = GetBrowserFlags(); | ||||
290 | |||||
291 | if (nBrowserFlags & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT) | ||||
292 | return; | ||||
293 | |||||
294 | // draw the text of the header column | ||||
295 | if (nBrowserFlags & EditBrowseBoxFlags::HANDLE_COLUMN_TEXT ) | ||||
296 | { | ||||
297 | rDev.DrawText( rRect, GetCellText( nPaintRow, 0 ), | ||||
298 | DrawTextFlags::Center | DrawTextFlags::VCenter | DrawTextFlags::Clip ); | ||||
299 | } | ||||
300 | // draw an image | ||||
301 | else if (eStatus != CLEAN && rDev.GetOutDevType() == OUTDEV_WINDOW) | ||||
302 | { | ||||
303 | Image aImage(GetImage(eStatus)); | ||||
304 | // calc the image position | ||||
305 | Size aImageSize(aImage.GetSizePixel()); | ||||
306 | aImageSize.setWidth( CalcZoom(aImageSize.Width()) ); | ||||
307 | aImageSize.setHeight( CalcZoom(aImageSize.Height()) ); | ||||
308 | Point aPos( rRect.TopLeft() ); | ||||
309 | |||||
310 | if ( ( aImageSize.Width() > rRect.GetWidth() ) || ( aImageSize.Height() > rRect.GetHeight() ) ) | ||||
311 | rDev.SetClipRegion(vcl::Region(rRect)); | ||||
312 | |||||
313 | if ( aImageSize.Width() < rRect.GetWidth() ) | ||||
314 | aPos.AdjustX(( rRect.GetWidth() - aImageSize.Width() ) / 2 ); | ||||
315 | |||||
316 | if ( aImageSize.Height() < rRect.GetHeight() ) | ||||
317 | aPos.AdjustY(( rRect.GetHeight() - aImageSize.Height() ) / 2 ); | ||||
318 | |||||
319 | if ( IsZoom() ) | ||||
320 | rDev.DrawImage( aPos, aImageSize, aImage ); | ||||
321 | else | ||||
322 | rDev.DrawImage( aPos, aImage ); | ||||
323 | |||||
324 | if (rDev.IsClipRegion()) | ||||
325 | rDev.SetClipRegion(); | ||||
326 | } | ||||
327 | } | ||||
328 | |||||
329 | |||||
330 | void EditBrowseBox::ImplStartTracking() | ||||
331 | { | ||||
332 | bActiveBeforeTracking = IsEditing(); | ||||
333 | if ( bActiveBeforeTracking
| ||||
| |||||
334 | { | ||||
335 | DeactivateCell(); | ||||
336 | PaintImmediately(); | ||||
337 | } | ||||
338 | |||||
339 | BrowseBox::ImplStartTracking(); | ||||
340 | } | ||||
341 | |||||
342 | |||||
343 | void EditBrowseBox::ImplEndTracking() | ||||
344 | { | ||||
345 | if ( bActiveBeforeTracking ) | ||||
346 | ActivateCell(); | ||||
347 | bActiveBeforeTracking = false; | ||||
348 | |||||
349 | BrowseBox::ImplEndTracking(); | ||||
350 | } | ||||
351 | |||||
352 | |||||
353 | void EditBrowseBox::RowHeightChanged() | ||||
354 | { | ||||
355 | if ( IsEditing() ) | ||||
356 | { | ||||
357 | tools::Rectangle aRect( GetCellRect( nEditRow, nEditCol, false ) ); | ||||
358 | CellControllerRef aCellController( Controller() ); | ||||
359 | ResizeController( aCellController, aRect ); | ||||
360 | aCellController->GetWindow().GrabFocus(); | ||||
361 | } | ||||
362 | |||||
363 | BrowseBox::RowHeightChanged(); | ||||
364 | } | ||||
365 | |||||
366 | |||||
367 | EditBrowseBox::RowStatus EditBrowseBox::GetRowStatus(long) const | ||||
368 | { | ||||
369 | return CLEAN; | ||||
370 | } | ||||
371 | |||||
372 | |||||
373 | void EditBrowseBox::KeyInput( const KeyEvent& rEvt ) | ||||
374 | { | ||||
375 | sal_uInt16 nCode = rEvt.GetKeyCode().GetCode(); | ||||
376 | bool bShift = rEvt.GetKeyCode().IsShift(); | ||||
377 | bool bCtrl = rEvt.GetKeyCode().IsMod1(); | ||||
378 | |||||
379 | switch (nCode) | ||||
380 | { | ||||
381 | case KEY_RETURN: | ||||
382 | if (!bCtrl && !bShift && IsTabAllowed(true)) | ||||
383 | { | ||||
384 | Dispatch(BROWSER_CURSORRIGHT734); | ||||
385 | } | ||||
386 | else | ||||
387 | BrowseBox::KeyInput(rEvt); | ||||
388 | return; | ||||
389 | case KEY_TAB: | ||||
390 | if (!bCtrl && !bShift) | ||||
391 | { | ||||
392 | if (IsTabAllowed(true)) | ||||
393 | Dispatch(BROWSER_CURSORRIGHT734); | ||||
394 | else | ||||
395 | // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now | ||||
396 | // that tab isn't allowed here. So give the Control class a chance | ||||
397 | Control::KeyInput(rEvt); | ||||
398 | return; | ||||
399 | } | ||||
400 | else if (!bCtrl && bShift) | ||||
401 | { | ||||
402 | if (IsTabAllowed(false)) | ||||
403 | Dispatch(BROWSER_CURSORLEFT733); | ||||
404 | else | ||||
405 | // do NOT call BrowseBox::KeyInput : this would handle the tab, but we already now | ||||
406 | // that tab isn't allowed here. So give the Control class a chance | ||||
407 | Control::KeyInput(rEvt); | ||||
408 | return; | ||||
409 | } | ||||
410 | [[fallthrough]]; | ||||
411 | default: | ||||
412 | BrowseBox::KeyInput(rEvt); | ||||
413 | } | ||||
414 | } | ||||
415 | |||||
416 | |||||
417 | void EditBrowseBox::MouseButtonDown(const BrowserMouseEvent& rEvt) | ||||
418 | { | ||||
419 | // absorb double clicks | ||||
420 | if (rEvt.GetClicks() > 1 && rEvt.GetRow() >= 0) | ||||
421 | return; | ||||
422 | |||||
423 | // we are about to leave the current cell. If there is a "this cell has been modified" notification | ||||
424 | // pending (asynchronously), this may be deadly -> do it synchronously | ||||
425 | if ( nCellModifiedEvent ) | ||||
426 | { | ||||
427 | Application::RemoveUserEvent( nCellModifiedEvent ); | ||||
428 | nCellModifiedEvent = nullptr; | ||||
429 | LINK( this, EditBrowseBox, CellModifiedHdl )::tools::detail::makeLink( ::tools::detail::castTo<EditBrowseBox *>(this), &EditBrowseBox::LinkStubCellModifiedHdl).Call( nullptr ); | ||||
430 | } | ||||
431 | |||||
432 | if (rEvt.GetColumnId() == HandleColumnId) | ||||
433 | { // it was the handle column. save the current cell content if necessary | ||||
434 | // (clicking on the handle column results in selecting the current row) | ||||
435 | if (IsEditing() && aController->IsValueChangedFromSaved()) | ||||
436 | SaveModified(); | ||||
437 | } | ||||
438 | |||||
439 | aMouseEvent.Set(&rEvt,true); | ||||
440 | BrowseBox::MouseButtonDown(rEvt); | ||||
441 | aMouseEvent.Clear(); | ||||
442 | |||||
443 | if (m_nBrowserFlags & EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN) | ||||
444 | { | ||||
445 | // the base class does not travel upon MouseButtonDown, but implActivateCellOnMouseEvent assumes we traveled ... | ||||
446 | GoToRowColumnId( rEvt.GetRow(), rEvt.GetColumnId() ); | ||||
447 | if (rEvt.GetRow() >= 0) | ||||
448 | implActivateCellOnMouseEvent(rEvt, false); | ||||
449 | } | ||||
450 | } | ||||
451 | |||||
452 | void EditBrowseBox::MouseButtonUp( const BrowserMouseEvent& rEvt ) | ||||
453 | { | ||||
454 | // absorb double clicks | ||||
455 | if (rEvt.GetClicks() > 1 && rEvt.GetRow() >= 0) | ||||
456 | return; | ||||
457 | |||||
458 | aMouseEvent.Set(&rEvt,false); | ||||
459 | BrowseBox::MouseButtonUp(rEvt); | ||||
460 | aMouseEvent.Clear(); | ||||
461 | |||||
462 | if (!(m_nBrowserFlags & EditBrowseBoxFlags::ACTIVATE_ON_BUTTONDOWN)) | ||||
463 | if (rEvt.GetRow() >= 0) | ||||
464 | implActivateCellOnMouseEvent(rEvt, true); | ||||
465 | } | ||||
466 | |||||
467 | bool EditBrowseBox::ControlHasFocus() const | ||||
468 | { | ||||
469 | Window* pControlWindow = aController ? &aController->GetWindow() : nullptr; | ||||
470 | if (ControlBase* pControlBase = dynamic_cast<ControlBase*>(pControlWindow)) | ||||
471 | return pControlBase->ControlHasFocus(); | ||||
472 | return pControlWindow && pControlWindow->HasChildPathFocus(); | ||||
473 | } | ||||
474 | |||||
475 | void EditBrowseBox::implActivateCellOnMouseEvent(const BrowserMouseEvent& _rEvt, bool _bUp) | ||||
476 | { | ||||
477 | if (!IsEditing()) | ||||
478 | ActivateCell(); | ||||
479 | else if (IsEditing() && !aController->GetWindow().IsEnabled()) | ||||
480 | DeactivateCell(); | ||||
481 | else if (IsEditing() && !ControlHasFocus()) | ||||
482 | AsynchGetFocus(); | ||||
483 | |||||
484 | if (!IsEditing() || !aController->GetWindow().IsEnabled()) | ||||
485 | return; | ||||
486 | |||||
487 | // forwards the event to the control | ||||
488 | aController->ActivatingMouseEvent(_rEvt, _bUp); | ||||
489 | } | ||||
490 | |||||
491 | void EditBrowseBox::Dispatch( sal_uInt16 _nId ) | ||||
492 | { | ||||
493 | if ( _nId == BROWSER_ENHANCESELECTION722 ) | ||||
494 | { // this is a workaround for the bug in the base class: | ||||
495 | // if the row selection is to be extended (which is what BROWSER_ENHANCESELECTION tells us) | ||||
496 | // then the base class does not revert any column selections, while, for doing a "simple" | ||||
497 | // selection (BROWSER_SELECT), it does. In fact, it does not only revert the col selection then, | ||||
498 | // but also any current row selections. | ||||
499 | // This clearly tells me that the both ids are for row selection only - there this behaviour does | ||||
500 | // make sense. | ||||
501 | // But here, where we have column selection, too, we take care of this ourself. | ||||
502 | if ( GetSelectColumnCount( ) ) | ||||
503 | { | ||||
504 | while ( GetSelectColumnCount( ) ) | ||||
505 | SelectColumnPos( | ||||
506 | sal::static_int_cast< sal_uInt16 >(FirstSelectedColumn()), | ||||
507 | false ); | ||||
508 | Select(); | ||||
509 | } | ||||
510 | } | ||||
511 | BrowseBox::Dispatch( _nId ); | ||||
512 | } | ||||
513 | |||||
514 | bool EditBrowseBox::ProcessKey(const KeyEvent& rKeyEvent) | ||||
515 | { | ||||
516 | sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); | ||||
517 | bool bShift = rKeyEvent.GetKeyCode().IsShift(); | ||||
518 | bool bCtrl = rKeyEvent.GetKeyCode().IsMod1(); | ||||
519 | bool bAlt = rKeyEvent.GetKeyCode().IsMod2(); | ||||
520 | bool bLocalSelect = false; | ||||
521 | bool bNonEditOnly = false; | ||||
522 | sal_uInt16 nId = BROWSER_NONE0; | ||||
523 | |||||
524 | if (!bAlt && !bCtrl && !bShift ) | ||||
525 | switch ( nCode ) | ||||
526 | { | ||||
527 | case KEY_DOWN: nId = BROWSER_CURSORDOWN731; break; | ||||
528 | case KEY_UP: nId = BROWSER_CURSORUP732; break; | ||||
529 | case KEY_PAGEDOWN: nId = BROWSER_CURSORPAGEDOWN735; break; | ||||
530 | case KEY_PAGEUP: nId = BROWSER_CURSORPAGEUP736; break; | ||||
531 | case KEY_HOME: nId = BROWSER_CURSORHOME745; break; | ||||
532 | case KEY_END: nId = BROWSER_CURSOREND746; break; | ||||
533 | |||||
534 | case KEY_TAB: | ||||
535 | // ask if traveling to the next cell is allowed | ||||
536 | if (IsTabAllowed(true)) | ||||
537 | nId = BROWSER_CURSORRIGHT734; | ||||
538 | break; | ||||
539 | |||||
540 | case KEY_RETURN: | ||||
541 | // save the cell content (if necessary) | ||||
542 | if (IsEditing() && aController->IsValueChangedFromSaved() && !SaveModified()) | ||||
543 | { | ||||
544 | // maybe we're not visible ... | ||||
545 | EnableAndShow(); | ||||
546 | aController->GetWindow().GrabFocus(); | ||||
547 | return true; | ||||
548 | } | ||||
549 | // ask if traveling to the next cell is allowed | ||||
550 | if (IsTabAllowed(true)) | ||||
551 | nId = BROWSER_CURSORRIGHT734; | ||||
552 | |||||
553 | break; | ||||
554 | case KEY_RIGHT: nId = BROWSER_CURSORRIGHT734; break; | ||||
555 | case KEY_LEFT: nId = BROWSER_CURSORLEFT733; break; | ||||
556 | case KEY_SPACE: nId = BROWSER_SELECT720; bNonEditOnly = bLocalSelect = true; break; | ||||
557 | } | ||||
558 | |||||
559 | if ( !bAlt && !bCtrl && bShift ) | ||||
560 | switch ( nCode ) | ||||
561 | { | ||||
562 | case KEY_DOWN: nId = BROWSER_SELECTDOWN724; bLocalSelect = true; break; | ||||
563 | case KEY_UP: nId = BROWSER_SELECTUP725; bLocalSelect = true; break; | ||||
564 | case KEY_HOME: nId = BROWSER_SELECTHOME753; bLocalSelect = true; break; | ||||
565 | case KEY_END: nId = BROWSER_SELECTEND754; bLocalSelect = true; break; | ||||
566 | case KEY_TAB: | ||||
567 | if (IsTabAllowed(false)) | ||||
568 | nId = BROWSER_CURSORLEFT733; | ||||
569 | break; | ||||
570 | } | ||||
571 | |||||
572 | if ( !bAlt && bCtrl && bShift ) | ||||
573 | switch ( nCode ) | ||||
574 | { | ||||
575 | case KEY_SPACE: nId = BROWSER_SELECTCOLUMN755; bLocalSelect = true; break; | ||||
576 | } | ||||
577 | |||||
578 | |||||
579 | if ( !bAlt && bCtrl && !bShift ) | ||||
580 | switch ( nCode ) | ||||
581 | { | ||||
582 | case KEY_DOWN: nId = BROWSER_SCROLLUP752; break; | ||||
583 | case KEY_UP: nId = BROWSER_SCROLLDOWN751; break; | ||||
584 | case KEY_PAGEDOWN: nId = BROWSER_CURSORENDOFFILE741; break; | ||||
585 | case KEY_PAGEUP: nId = BROWSER_CURSORTOPOFFILE742; break; | ||||
586 | case KEY_HOME: nId = BROWSER_CURSORTOPOFSCREEN744; break; | ||||
587 | case KEY_END: nId = BROWSER_CURSORENDOFSCREEN743; break; | ||||
588 | case KEY_SPACE: nId = BROWSER_ENHANCESELECTION722; bLocalSelect = true; break; | ||||
589 | } | ||||
590 | |||||
591 | |||||
592 | if ( ( nId != BROWSER_NONE0 ) | ||||
593 | && ( !IsEditing() | ||||
594 | || ( !bNonEditOnly | ||||
595 | && aController->MoveAllowed(rKeyEvent) | ||||
596 | ) | ||||
597 | ) | ||||
598 | ) | ||||
599 | { | ||||
600 | if (nId == BROWSER_SELECT720 || BROWSER_SELECTCOLUMN755 == nId ) | ||||
601 | { | ||||
602 | // save the cell content (if necessary) | ||||
603 | if (IsEditing() && aController->IsValueChangedFromSaved() && !SaveModified()) | ||||
604 | { | ||||
605 | // maybe we're not visible ... | ||||
606 | EnableAndShow(); | ||||
607 | aController->GetWindow().GrabFocus(); | ||||
608 | return true; | ||||
609 | } | ||||
610 | } | ||||
611 | |||||
612 | Dispatch(nId); | ||||
613 | |||||
614 | if (bLocalSelect && (GetSelectRowCount() || GetSelection() != nullptr)) | ||||
615 | DeactivateCell(); | ||||
616 | return true; | ||||
617 | } | ||||
618 | return false; | ||||
619 | } | ||||
620 | |||||
621 | bool EditBrowseBox::PreNotify(NotifyEvent& rEvt) | ||||
622 | { | ||||
623 | if (rEvt.GetType() == MouseNotifyEvent::KEYINPUT) | ||||
624 | { | ||||
625 | if ( (IsEditing() && ControlHasFocus()) | ||||
626 | || rEvt.GetWindow() == &GetDataWindow() | ||||
627 | || (!IsEditing() && HasChildPathFocus()) | ||||
628 | ) | ||||
629 | { | ||||
630 | if (ProcessKey(*rEvt.GetKeyEvent())) | ||||
631 | return true; | ||||
632 | } | ||||
633 | } | ||||
634 | return BrowseBox::PreNotify(rEvt); | ||||
635 | } | ||||
636 | |||||
637 | bool EditBrowseBox::IsTabAllowed(bool) const | ||||
638 | { | ||||
639 | return true; | ||||
640 | } | ||||
641 | |||||
642 | |||||
643 | bool EditBrowseBox::EventNotify(NotifyEvent& rEvt) | ||||
644 | { | ||||
645 | switch (rEvt.GetType()) | ||||
646 | { | ||||
647 | case MouseNotifyEvent::GETFOCUS: | ||||
648 | DetermineFocus( getRealGetFocusFlags( this ) ); | ||||
649 | break; | ||||
650 | |||||
651 | case MouseNotifyEvent::LOSEFOCUS: | ||||
652 | DetermineFocus(); | ||||
653 | break; | ||||
654 | |||||
655 | default: | ||||
656 | break; | ||||
657 | } | ||||
658 | return BrowseBox::EventNotify(rEvt); | ||||
659 | } | ||||
660 | |||||
661 | |||||
662 | void EditBrowseBox::StateChanged( StateChangedType nType ) | ||||
663 | { | ||||
664 | BrowseBox::StateChanged( nType ); | ||||
665 | |||||
666 | bool bNeedCellReActivation = false; | ||||
667 | if ( nType == StateChangedType::Mirroring ) | ||||
668 | { | ||||
669 | bNeedCellReActivation = true; | ||||
670 | } | ||||
671 | else if ( nType == StateChangedType::Zoom ) | ||||
672 | { | ||||
673 | ImplInitSettings( true, false, false ); | ||||
674 | bNeedCellReActivation = true; | ||||
675 | } | ||||
676 | else if ( nType == StateChangedType::ControlFont ) | ||||
677 | { | ||||
678 | ImplInitSettings( true, false, false ); | ||||
679 | Invalidate(); | ||||
680 | } | ||||
681 | else if ( nType == StateChangedType::ControlForeground ) | ||||
682 | { | ||||
683 | ImplInitSettings( false, true, false ); | ||||
684 | Invalidate(); | ||||
685 | } | ||||
686 | else if ( nType == StateChangedType::ControlBackground ) | ||||
687 | { | ||||
688 | ImplInitSettings( false, false, true ); | ||||
689 | Invalidate(); | ||||
690 | } | ||||
691 | else if (nType == StateChangedType::Style) | ||||
692 | { | ||||
693 | WinBits nStyle = GetStyle(); | ||||
694 | if (!(nStyle & WB_NOTABSTOP) ) | ||||
695 | nStyle |= WB_TABSTOP; | ||||
696 | |||||
697 | SetStyle(nStyle); | ||||
698 | } | ||||
699 | if ( bNeedCellReActivation ) | ||||
700 | { | ||||
701 | if ( IsEditing() ) | ||||
702 | { | ||||
703 | DeactivateCell(); | ||||
704 | ActivateCell(); | ||||
705 | } | ||||
706 | } | ||||
707 | } | ||||
708 | |||||
709 | |||||
710 | void EditBrowseBox::DataChanged( const DataChangedEvent& rDCEvt ) | ||||
711 | { | ||||
712 | BrowseBox::DataChanged( rDCEvt ); | ||||
713 | |||||
714 | if ((( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) || | ||||
715 | ( rDCEvt.GetType() == DataChangedEventType::DISPLAY )) && | ||||
716 | ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )) | ||||
717 | { | ||||
718 | ImplInitSettings( true, true, true ); | ||||
719 | Invalidate(); | ||||
720 | } | ||||
721 | } | ||||
722 | |||||
723 | void EditBrowseBox::ImplInitSettings( bool bFont, bool bForeground, bool bBackground ) | ||||
724 | { | ||||
725 | const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); | ||||
726 | |||||
727 | if (bFont) | ||||
728 | { | ||||
729 | vcl::Font aFont = rStyleSettings.GetFieldFont(); | ||||
730 | if (IsControlFont()) | ||||
731 | { | ||||
732 | GetDataWindow().SetControlFont(GetControlFont()); | ||||
733 | aFont.Merge(GetControlFont()); | ||||
734 | } | ||||
735 | else | ||||
736 | GetDataWindow().SetControlFont(); | ||||
737 | |||||
738 | GetDataWindow().SetZoomedPointFont(GetDataWindow(), aFont); | ||||
739 | } | ||||
740 | |||||
741 | if (bFont || bForeground) | ||||
742 | { | ||||
743 | Color aTextColor = rStyleSettings.GetFieldTextColor(); | ||||
744 | if (IsControlForeground()) | ||||
745 | { | ||||
746 | aTextColor = GetControlForeground(); | ||||
747 | GetDataWindow().SetControlForeground(aTextColor); | ||||
748 | } | ||||
749 | else | ||||
750 | GetDataWindow().SetControlForeground(); | ||||
751 | |||||
752 | GetDataWindow().SetTextColor( aTextColor ); | ||||
753 | } | ||||
754 | |||||
755 | if (!bBackground) // FIXME: Outside of Paint Hierarchy | ||||
756 | return; | ||||
757 | |||||
758 | if (GetDataWindow().IsControlBackground()) | ||||
759 | { | ||||
760 | GetDataWindow().SetControlBackground(GetControlBackground()); | ||||
761 | GetDataWindow().SetBackground(GetDataWindow().GetControlBackground()); | ||||
762 | GetDataWindow().SetFillColor(GetDataWindow().GetControlBackground()); | ||||
763 | } | ||||
764 | else | ||||
765 | { | ||||
766 | GetDataWindow().SetControlBackground(); | ||||
767 | GetDataWindow().SetBackground(rStyleSettings.GetFieldColor()); | ||||
768 | GetDataWindow().SetFillColor(rStyleSettings.GetFieldColor()); | ||||
769 | } | ||||
770 | } | ||||
771 | |||||
772 | |||||
773 | bool EditBrowseBox::IsCursorMoveAllowed(long nNewRow, sal_uInt16 nNewColId) const | ||||
774 | { | ||||
775 | sal_uInt16 nInfo = 0; | ||||
776 | |||||
777 | if (GetSelectColumnCount() || (aMouseEvent.Is() && aMouseEvent->GetRow() < 0)) | ||||
778 | nInfo |= COLSELECT; | ||||
779 | if ((GetSelection() != nullptr && GetSelectRowCount()) || | ||||
780 | (aMouseEvent.Is() && aMouseEvent->GetColumnId() == HandleColumnId)) | ||||
781 | nInfo |= ROWSELECT; | ||||
782 | if (!nInfo && nNewRow != nEditRow) | ||||
783 | nInfo |= ROWCHANGE; | ||||
784 | if (!nInfo && nNewColId != nEditCol) | ||||
785 | nInfo |= COLCHANGE; | ||||
786 | |||||
787 | if (nInfo == 0) // nothing happened | ||||
788 | return true; | ||||
789 | |||||
790 | // save the cell content | ||||
791 | if (IsEditing() && aController->IsValueChangedFromSaved() && !const_cast<EditBrowseBox *>(this)->SaveModified()) | ||||
792 | { | ||||
793 | // maybe we're not visible ... | ||||
794 | EnableAndShow(); | ||||
795 | aController->GetWindow().GrabFocus(); | ||||
796 | return false; | ||||
797 | } | ||||
798 | |||||
799 | EditBrowseBox * pTHIS = const_cast<EditBrowseBox *> (this); | ||||
800 | |||||
801 | // save the cell content if | ||||
802 | // a) a selection is being made | ||||
803 | // b) the row is changing | ||||
804 | if (IsModified() && (nInfo & (ROWCHANGE | COLSELECT | ROWSELECT)) && | ||||
805 | !pTHIS->SaveRow()) | ||||
806 | { | ||||
807 | if (nInfo & COLSELECT || | ||||
808 | nInfo & ROWSELECT) | ||||
809 | { | ||||
810 | // cancel selected | ||||
811 | pTHIS->SetNoSelection(); | ||||
812 | } | ||||
813 | |||||
814 | if (IsEditing()) | ||||
815 | { | ||||
816 | if (!Controller()->GetWindow().IsVisible()) | ||||
817 | { | ||||
818 | EnableAndShow(); | ||||
819 | } | ||||
820 | aController->GetWindow().GrabFocus(); | ||||
821 | } | ||||
822 | return false; | ||||
823 | } | ||||
824 | |||||
825 | if (nNewRow != nEditRow) | ||||
826 | { | ||||
827 | vcl::Window& rWindow = GetDataWindow(); | ||||
828 | if ((nEditRow >= 0) && !(GetBrowserFlags() & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT)) | ||||
829 | { | ||||
830 | tools::Rectangle aRect = GetFieldRectPixel(nEditRow, 0, false ); | ||||
831 | // status cell should be painted if and only if text is displayed | ||||
832 | pTHIS->bPaintStatus = ( GetBrowserFlags() & EditBrowseBoxFlags::HANDLE_COLUMN_TEXT ) == EditBrowseBoxFlags::HANDLE_COLUMN_TEXT; | ||||
833 | rWindow.Invalidate(aRect); | ||||
834 | pTHIS->bPaintStatus = true; | ||||
835 | } | ||||
836 | |||||
837 | // don't paint during row change | ||||
838 | rWindow.EnablePaint(false); | ||||
839 | |||||
840 | // the last veto chance for derived classes | ||||
841 | if (!pTHIS->CursorMoving(nNewRow, nNewColId)) | ||||
842 | { | ||||
843 | pTHIS->InvalidateStatusCell(nEditRow); | ||||
844 | rWindow.EnablePaint(true); | ||||
845 | return false; | ||||
846 | } | ||||
847 | else | ||||
848 | { | ||||
849 | rWindow.EnablePaint(true); | ||||
850 | return true; | ||||
851 | } | ||||
852 | } | ||||
853 | else | ||||
854 | return pTHIS->CursorMoving(nNewRow, nNewColId); | ||||
855 | } | ||||
856 | |||||
857 | |||||
858 | void EditBrowseBox::ColumnMoved(sal_uInt16 nId) | ||||
859 | { | ||||
860 | BrowseBox::ColumnMoved(nId); | ||||
861 | if (IsEditing()) | ||||
862 | { | ||||
863 | tools::Rectangle aRect( GetCellRect(nEditRow, nEditCol, false)); | ||||
864 | CellControllerRef aControllerRef = Controller(); | ||||
865 | ResizeController(aControllerRef, aRect); | ||||
866 | Controller()->GetWindow().GrabFocus(); | ||||
867 | } | ||||
868 | } | ||||
869 | |||||
870 | |||||
871 | bool EditBrowseBox::SaveRow() | ||||
872 | { | ||||
873 | return true; | ||||
874 | } | ||||
875 | |||||
876 | |||||
877 | bool EditBrowseBox::CursorMoving(long, sal_uInt16) | ||||
878 | { | ||||
879 | DeactivateCell(false); | ||||
880 | return true; | ||||
881 | } | ||||
882 | |||||
883 | |||||
884 | void EditBrowseBox::CursorMoved() | ||||
885 | { | ||||
886 | long nNewRow = GetCurRow(); | ||||
887 | if (nEditRow != nNewRow) | ||||
888 | { | ||||
889 | if (!(GetBrowserFlags() & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT)) | ||||
890 | InvalidateStatusCell(nNewRow); | ||||
891 | nEditRow = nNewRow; | ||||
892 | } | ||||
893 | ActivateCell(); | ||||
894 | GetDataWindow().EnablePaint(true); | ||||
895 | // should not be called here because the descant event is not needed here | ||||
896 | //BrowseBox::CursorMoved(); | ||||
897 | } | ||||
898 | |||||
899 | |||||
900 | void EditBrowseBox::EndScroll() | ||||
901 | { | ||||
902 | if (IsEditing()) | ||||
903 | { | ||||
904 | tools::Rectangle aRect = GetCellRect(nEditRow, nEditCol, false); | ||||
905 | ResizeController(aController,aRect); | ||||
906 | AsynchGetFocus(); | ||||
907 | } | ||||
908 | BrowseBox::EndScroll(); | ||||
909 | } | ||||
910 | |||||
911 | |||||
912 | void EditBrowseBox::ActivateCell(long nRow, sal_uInt16 nCol, bool bCellFocus) | ||||
913 | { | ||||
914 | if (IsEditing()) | ||||
915 | return; | ||||
916 | |||||
917 | nEditCol = nCol; | ||||
918 | |||||
919 | if ((GetSelectRowCount() && GetSelection() != nullptr) || GetSelectColumnCount() || | ||||
920 | (aMouseEvent.Is() && (aMouseEvent.IsDown() || aMouseEvent->GetClicks() > 1))) // nothing happens on MouseDown | ||||
921 | { | ||||
922 | return; | ||||
923 | } | ||||
924 | |||||
925 | if (nEditRow < 0 || nEditCol <= HandleColumnId) | ||||
926 | return; | ||||
927 | |||||
928 | aController = GetController(nRow, nCol); | ||||
929 | if (aController.is()) | ||||
930 | { | ||||
931 | tools::Rectangle aRect( GetCellRect(nEditRow, nEditCol, false)); | ||||
932 | ResizeController(aController, aRect); | ||||
933 | |||||
934 | InitController(aController, nEditRow, nEditCol); | ||||
935 | |||||
936 | aController->SaveValue(); | ||||
937 | aController->SetModifyHdl(LINK(this,EditBrowseBox,ModifyHdl)::tools::detail::makeLink( ::tools::detail::castTo<EditBrowseBox *>(this), &EditBrowseBox::LinkStubModifyHdl)); | ||||
938 | EnableAndShow(); | ||||
939 | |||||
940 | if ( isAccessibleAlive() ) | ||||
941 | implCreateActiveAccessible(); | ||||
942 | |||||
943 | // activate the cell only of the browser has the focus | ||||
944 | if ( bHasFocus && bCellFocus ) | ||||
945 | AsynchGetFocus(); | ||||
946 | } | ||||
947 | else | ||||
948 | { | ||||
949 | // no controller -> we have a new "active descendant" | ||||
950 | if ( isAccessibleAlive() && HasFocus() ) | ||||
951 | { | ||||
952 | commitTableEvent( | ||||
953 | ACTIVE_DESCENDANT_CHANGED, | ||||
954 | makeAny( CreateAccessibleCell( nRow, GetColumnPos( nCol -1) ) ), | ||||
955 | Any() | ||||
956 | ); | ||||
957 | } | ||||
958 | } | ||||
959 | } | ||||
960 | |||||
961 | |||||
962 | void EditBrowseBox::DeactivateCell(bool bUpdate) | ||||
963 | { | ||||
964 | if (!IsEditing()) | ||||
965 | return; | ||||
966 | |||||
967 | if ( isAccessibleAlive() ) | ||||
968 | { | ||||
969 | commitBrowseBoxEvent( CHILD, Any(), makeAny( m_aImpl->m_xActiveCell ) ); | ||||
970 | m_aImpl->clearActiveCell(); | ||||
971 | } | ||||
972 | |||||
973 | aOldController = aController; | ||||
974 | aController.clear(); | ||||
975 | |||||
976 | // reset the modify handler | ||||
977 | aOldController->SetModifyHdl(Link<LinkParamNone*,void>()); | ||||
978 | |||||
979 | if (bHasFocus) | ||||
980 | GrabFocus(); // ensure that we have (and keep) the focus | ||||
981 | |||||
982 | aOldController->suspend(); | ||||
983 | |||||
984 | // update if requested | ||||
985 | if (bUpdate) | ||||
986 | PaintImmediately(); | ||||
987 | |||||
988 | // release the controller (asynchronously) | ||||
989 | if (nEndEvent) | ||||
990 | Application::RemoveUserEvent(nEndEvent); | ||||
991 | nEndEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,EndEditHdl)::tools::detail::makeLink( ::tools::detail::castTo<EditBrowseBox *>(this), &EditBrowseBox::LinkStubEndEditHdl), nullptr, true); | ||||
992 | } | ||||
993 | |||||
994 | |||||
995 | tools::Rectangle EditBrowseBox::GetCellRect(long nRow, sal_uInt16 nColId, bool bRel) const | ||||
996 | { | ||||
997 | tools::Rectangle aRect( GetFieldRectPixel(nRow, nColId, bRel)); | ||||
998 | if ((GetMode() & BrowserMode::CURSOR_WO_FOCUS) == BrowserMode::CURSOR_WO_FOCUS) | ||||
999 | { | ||||
1000 | aRect.AdjustTop(1 ); | ||||
1001 | aRect.AdjustBottom( -1 ); | ||||
1002 | } | ||||
1003 | return aRect; | ||||
1004 | } | ||||
1005 | |||||
1006 | |||||
1007 | IMPL_LINK_NOARG(EditBrowseBox, EndEditHdl, void*, void)void EditBrowseBox::LinkStubEndEditHdl(void * instance, void* data) { return static_cast<EditBrowseBox *>(instance)-> EndEditHdl(data); } void EditBrowseBox::EndEditHdl(__attribute__ ((unused)) void*) | ||||
1008 | { | ||||
1009 | nEndEvent = nullptr; | ||||
1010 | |||||
1011 | aOldController = CellControllerRef(); | ||||
1012 | } | ||||
1013 | |||||
1014 | |||||
1015 | IMPL_LINK_NOARG(EditBrowseBox, ModifyHdl, LinkParamNone*, void)void EditBrowseBox::LinkStubModifyHdl(void * instance, LinkParamNone * data) { return static_cast<EditBrowseBox *>(instance) ->ModifyHdl(data); } void EditBrowseBox::ModifyHdl(__attribute__ ((unused)) LinkParamNone*) | ||||
1016 | { | ||||
1017 | if (nCellModifiedEvent) | ||||
1018 | Application::RemoveUserEvent(nCellModifiedEvent); | ||||
1019 | nCellModifiedEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,CellModifiedHdl)::tools::detail::makeLink( ::tools::detail::castTo<EditBrowseBox *>(this), &EditBrowseBox::LinkStubCellModifiedHdl), nullptr, true); | ||||
1020 | } | ||||
1021 | |||||
1022 | |||||
1023 | IMPL_LINK_NOARG(EditBrowseBox, CellModifiedHdl, void*, void)void EditBrowseBox::LinkStubCellModifiedHdl(void * instance, void * data) { return static_cast<EditBrowseBox *>(instance) ->CellModifiedHdl(data); } void EditBrowseBox::CellModifiedHdl (__attribute__ ((unused)) void*) | ||||
1024 | { | ||||
1025 | nCellModifiedEvent = nullptr; | ||||
1026 | CellModified(); | ||||
1027 | } | ||||
1028 | |||||
1029 | void EditBrowseBox::ColumnResized( sal_uInt16 ) | ||||
1030 | { | ||||
1031 | if (IsEditing()) | ||||
1032 | { | ||||
1033 | tools::Rectangle aRect( GetCellRect(nEditRow, nEditCol, false)); | ||||
1034 | CellControllerRef aControllerRef = Controller(); | ||||
1035 | ResizeController(aControllerRef, aRect); | ||||
1036 | // don't grab focus if Field Properties panel is being | ||||
1037 | // resized by split pane drag resizing | ||||
1038 | if (Application::IsUICaptured()) | ||||
1039 | return; | ||||
1040 | Controller()->GetWindow().GrabFocus(); | ||||
1041 | } | ||||
1042 | } | ||||
1043 | |||||
1044 | sal_uInt16 EditBrowseBox::AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nPos, sal_uInt16 nId) | ||||
1045 | { | ||||
1046 | if (nId == BROWSER_INVALIDID((sal_uInt16) 0xFFFF)) | ||||
1047 | { | ||||
1048 | // look for the next free id | ||||
1049 | for (nId = ColCount(); nId > 0 && GetColumnPos(nId) != BROWSER_INVALIDID((sal_uInt16) 0xFFFF); nId--) | ||||
1050 | ; | ||||
1051 | |||||
1052 | if (!nId) | ||||
1053 | { | ||||
1054 | // if there is no handle column | ||||
1055 | // increment the id | ||||
1056 | if ( ColCount() == 0 || GetColumnId(0) != HandleColumnId ) | ||||
1057 | nId = ColCount() + 1; | ||||
1058 | } | ||||
1059 | } | ||||
1060 | |||||
1061 | DBG_ASSERT(nId, "EditBrowseBox::AppendColumn: invalid id!")do { if (true && (!(nId))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svtools/source/brwbox/editbrowsebox.cxx" ":" "1061" ": "), "%s", "EditBrowseBox::AppendColumn: invalid id!" ); } } while (false); | ||||
1062 | |||||
1063 | long w = nWidth; | ||||
1064 | if (!w) | ||||
1065 | w = GetDefaultColumnWidth(rName); | ||||
1066 | |||||
1067 | InsertDataColumn(nId, rName, w, (HeaderBarItemBits::CENTER | HeaderBarItemBits::CLICKABLE), nPos); | ||||
1068 | return nId; | ||||
1069 | } | ||||
1070 | |||||
1071 | void EditBrowseBox::Resize() | ||||
1072 | { | ||||
1073 | BrowseBox::Resize(); | ||||
1074 | |||||
1075 | // if the window is smaller than "title line height" + "control area", | ||||
1076 | // do nothing | ||||
1077 | if (GetOutputSizePixel().Height() < | ||||
1078 | (GetControlArea().GetHeight() + GetDataWindow().GetPosPixel().Y())) | ||||
1079 | return; | ||||
1080 | |||||
1081 | // the size of the control area | ||||
1082 | Point aPoint(GetControlArea().TopLeft()); | ||||
1083 | sal_uInt16 nX = static_cast<sal_uInt16>(aPoint.X()); | ||||
1084 | |||||
1085 | ArrangeControls(nX, static_cast<sal_uInt16>(aPoint.Y())); | ||||
1086 | |||||
1087 | if (!nX) | ||||
1088 | nX = USHRT_MAX(32767 *2 +1); | ||||
1089 | |||||
1090 | bool bChanged = ReserveControlArea(nX); | ||||
1091 | |||||
1092 | //tdf#97731 if the reserved area changed size, give the controls a | ||||
1093 | //chance to adapt to the new size | ||||
1094 | if (bChanged) | ||||
1095 | { | ||||
1096 | nX = static_cast<sal_uInt16>(aPoint.X()); | ||||
1097 | ArrangeControls(nX, static_cast<sal_uInt16>(aPoint.Y())); | ||||
1098 | } | ||||
1099 | } | ||||
1100 | |||||
1101 | void EditBrowseBox::ArrangeControls(sal_uInt16&, sal_uInt16) | ||||
1102 | { | ||||
1103 | } | ||||
1104 | |||||
1105 | CellController* EditBrowseBox::GetController(long, sal_uInt16) | ||||
1106 | { | ||||
1107 | return nullptr; | ||||
1108 | } | ||||
1109 | |||||
1110 | void EditBrowseBox::ResizeController(CellControllerRef const & rController, const tools::Rectangle& rRect) | ||||
1111 | { | ||||
1112 | Point aPoint(rRect.TopLeft()); | ||||
1113 | Size aSize(rRect.GetSize()); | ||||
1114 | Control& rControl = rController->GetWindow(); | ||||
1115 | auto nMinHeight = rControl.get_preferred_size().Height(); | ||||
1116 | if (nMinHeight > aSize.Height()) | ||||
1117 | { | ||||
1118 | auto nOffset = (nMinHeight - aSize.Height()) / 2; | ||||
1119 | aPoint.AdjustY(-nOffset); | ||||
1120 | aSize.setHeight(nMinHeight); | ||||
1121 | } | ||||
1122 | rControl.SetPosSizePixel(aPoint, aSize); | ||||
1123 | } | ||||
1124 | |||||
1125 | void EditBrowseBox::InitController(CellControllerRef&, long, sal_uInt16) | ||||
1126 | { | ||||
1127 | } | ||||
1128 | |||||
1129 | |||||
1130 | void EditBrowseBox::CellModified() | ||||
1131 | { | ||||
1132 | } | ||||
1133 | |||||
1134 | |||||
1135 | bool EditBrowseBox::SaveModified() | ||||
1136 | { | ||||
1137 | return true; | ||||
1138 | } | ||||
1139 | |||||
1140 | |||||
1141 | void EditBrowseBox::DoubleClick(const BrowserMouseEvent& rEvt) | ||||
1142 | { | ||||
1143 | // when double clicking on the column, the optimum size will be calculated | ||||
1144 | sal_uInt16 nColId = rEvt.GetColumnId(); | ||||
1145 | if (nColId != HandleColumnId) | ||||
1146 | SetColumnWidth(nColId, GetAutoColumnWidth(nColId)); | ||||
1147 | } | ||||
1148 | |||||
1149 | |||||
1150 | sal_uInt32 EditBrowseBox::GetAutoColumnWidth(sal_uInt16 nColId) | ||||
1151 | { | ||||
1152 | sal_uInt32 nCurColWidth = GetColumnWidth(nColId); | ||||
1153 | sal_uInt32 nMinColWidth = CalcZoom(20); // minimum | ||||
1154 | sal_uInt32 nNewColWidth = nMinColWidth; | ||||
1155 | long nMaxRows = std::min(long(GetVisibleRows()), GetRowCount()); | ||||
1156 | long nLastVisRow = GetTopRow() + nMaxRows - 1; | ||||
1157 | |||||
1158 | if (GetTopRow() <= nLastVisRow) // calc the column with using the cell contents | ||||
1159 | { | ||||
1160 | for (long i = GetTopRow(); i <= nLastVisRow; ++i) | ||||
1161 | nNewColWidth = std::max(nNewColWidth,GetTotalCellWidth(i,nColId) + 12); | ||||
1162 | |||||
1163 | if (nNewColWidth == nCurColWidth) // size has not changed | ||||
1164 | nNewColWidth = GetDefaultColumnWidth(GetColumnTitle(nColId)); | ||||
1165 | } | ||||
1166 | else | ||||
1167 | nNewColWidth = GetDefaultColumnWidth(GetColumnTitle(nColId)); | ||||
1168 | return nNewColWidth; | ||||
1169 | } | ||||
1170 | |||||
1171 | sal_uInt32 EditBrowseBox::GetTotalCellWidth(long, sal_uInt16) | ||||
1172 | { | ||||
1173 | return 0; | ||||
1174 | } | ||||
1175 | |||||
1176 | void EditBrowseBox::InvalidateHandleColumn() | ||||
1177 | { | ||||
1178 | tools::Rectangle aHdlFieldRect( GetFieldRectPixel( 0, 0 )); | ||||
1179 | tools::Rectangle aInvalidRect( Point(0,0), GetOutputSizePixel() ); | ||||
1180 | aInvalidRect.SetRight( aHdlFieldRect.Right() ); | ||||
1181 | Invalidate( aInvalidRect ); | ||||
1182 | } | ||||
1183 | |||||
1184 | void EditBrowseBox::PaintTristate(const tools::Rectangle& rRect, const TriState& eState, bool _bEnabled) const | ||||
1185 | { | ||||
1186 | pCheckBoxPaint->SetState(eState); | ||||
1187 | |||||
1188 | pCheckBoxPaint->GetBox().set_sensitive(_bEnabled); | ||||
1189 | |||||
1190 | Size aBoxSize = pCheckBoxPaint->GetBox().get_preferred_size(); | ||||
1191 | tools::Rectangle aRect(Point(rRect.Left() + ((rRect.GetWidth() - aBoxSize.Width()) / 2), | ||||
1192 | rRect.Top() + ((rRect.GetHeight() - aBoxSize.Height()) / 2)), | ||||
1193 | aBoxSize); | ||||
1194 | pCheckBoxPaint->SetPosSizePixel(aRect.TopLeft(), aRect.GetSize()); | ||||
1195 | |||||
1196 | pCheckBoxPaint->Draw(&GetDataWindow(), aRect.TopLeft(), DrawFlags::NONE); | ||||
1197 | } | ||||
1198 | |||||
1199 | void EditBrowseBox::AsynchGetFocus() | ||||
1200 | { | ||||
1201 | if (nStartEvent) | ||||
1202 | Application::RemoveUserEvent(nStartEvent); | ||||
1203 | |||||
1204 | m_pFocusWhileRequest = Application::GetFocusWindow(); | ||||
1205 | nStartEvent = Application::PostUserEvent(LINK(this,EditBrowseBox,StartEditHdl)::tools::detail::makeLink( ::tools::detail::castTo<EditBrowseBox *>(this), &EditBrowseBox::LinkStubStartEditHdl), nullptr, true); | ||||
1206 | } | ||||
1207 | |||||
1208 | |||||
1209 | void EditBrowseBox::SetBrowserFlags(EditBrowseBoxFlags nFlags) | ||||
1210 | { | ||||
1211 | if (m_nBrowserFlags == nFlags) | ||||
1212 | return; | ||||
1213 | |||||
1214 | bool RowPicturesChanges = ((m_nBrowserFlags & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT) != | ||||
1215 | (nFlags & EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT)); | ||||
1216 | m_nBrowserFlags = nFlags; | ||||
1217 | |||||
1218 | if (RowPicturesChanges) | ||||
1219 | InvalidateStatusCell(GetCurRow()); | ||||
1220 | } | ||||
1221 | |||||
1222 | inline void EditBrowseBox::EnableAndShow() const | ||||
1223 | { | ||||
1224 | Controller()->resume(); | ||||
1225 | } | ||||
1226 | |||||
1227 | |||||
1228 | CellController::CellController(Control* pW) | ||||
1229 | :pWindow( pW ) | ||||
1230 | ,bSuspended( true ) | ||||
1231 | { | ||||
1232 | |||||
1233 | DBG_ASSERT(pWindow, "CellController::CellController: missing the window!")do { if (true && (!(pWindow))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svtools/source/brwbox/editbrowsebox.cxx" ":" "1233" ": "), "%s", "CellController::CellController: missing the window!" ); } } while (false); | ||||
1234 | DBG_ASSERT(!pWindow->IsVisible(), "CellController::CellController: window should not be visible!")do { if (true && (!(!pWindow->IsVisible()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svtools/source/brwbox/editbrowsebox.cxx" ":" "1234" ": "), "%s", "CellController::CellController: window should not be visible!" ); } } while (false); | ||||
1235 | } | ||||
1236 | |||||
1237 | |||||
1238 | CellController::~CellController() | ||||
1239 | { | ||||
1240 | |||||
1241 | } | ||||
1242 | |||||
1243 | |||||
1244 | void CellController::suspend( ) | ||||
1245 | { | ||||
1246 | DBG_ASSERT( bSuspended == !GetWindow().IsVisible(), "CellController::suspend: inconsistence!" )do { if (true && (!(bSuspended == !GetWindow().IsVisible ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/svtools/source/brwbox/editbrowsebox.cxx" ":" "1246" ": "), "%s", "CellController::suspend: inconsistence!" ); } } while (false); | ||||
1247 | if ( !isSuspended( ) ) | ||||
1248 | { | ||||
1249 | CommitModifications(); | ||||
1250 | GetWindow().Hide( ); | ||||
1251 | GetWindow().Disable( ); | ||||
1252 | bSuspended = true; | ||||
1253 | } | ||||
1254 | } | ||||
1255 | |||||
1256 | void CellController::resume( ) | ||||
1257 | { | ||||
1258 | DBG_ASSERT( bSuspended == !GetWindow().IsVisible(), "CellController::resume: inconsistence!" )do { if (true && (!(bSuspended == !GetWindow().IsVisible ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools" ), ("/home/maarten/src/libreoffice/core/svtools/source/brwbox/editbrowsebox.cxx" ":" "1258" ": "), "%s", "CellController::resume: inconsistence!" ); } } while (false); | ||||
1259 | if ( isSuspended( ) ) | ||||
1260 | { | ||||
1261 | GetWindow().Enable( ); | ||||
1262 | GetWindow().Show( ); | ||||
1263 | bSuspended = false; | ||||
1264 | } | ||||
1265 | } | ||||
1266 | |||||
1267 | void CellController::CommitModifications() | ||||
1268 | { | ||||
1269 | // nothing to do in this base class | ||||
1270 | } | ||||
1271 | |||||
1272 | void CellController::ActivatingMouseEvent(const BrowserMouseEvent& /*rEvt*/, bool /*bUp*/) | ||||
1273 | { | ||||
1274 | // nothing to do in this base class | ||||
1275 | } | ||||
1276 | |||||
1277 | bool CellController::MoveAllowed(const KeyEvent&) const | ||||
1278 | { | ||||
1279 | return true; | ||||
1280 | } | ||||
1281 | |||||
1282 | } // namespace svt | ||||
1283 | |||||
1284 | |||||
1285 | /* 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_TOOLS_REF_HXX | |||
20 | #define INCLUDED_TOOLS_REF_HXX | |||
21 | ||||
22 | #include <sal/config.h> | |||
23 | #include <cassert> | |||
24 | #include <tools/toolsdllapi.h> | |||
25 | #include <utility> | |||
26 | ||||
27 | /** | |||
28 | This implements similar functionality to boost::intrusive_ptr | |||
29 | */ | |||
30 | ||||
31 | namespace tools { | |||
32 | ||||
33 | /** T must be a class that extends SvRefBase */ | |||
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { | |||
35 | public: | |||
36 | SvRef(): pObj(nullptr) {} | |||
37 | ||||
38 | SvRef(SvRef&& rObj) noexcept | |||
39 | { | |||
40 | pObj = rObj.pObj; | |||
41 | rObj.pObj = nullptr; | |||
42 | } | |||
43 | ||||
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) | |||
45 | { | |||
46 | if (pObj != nullptr) pObj->AddNextRef(); | |||
47 | } | |||
48 | ||||
49 | SvRef(T * pObjP): pObj(pObjP) | |||
50 | { | |||
51 | if (pObj != nullptr) pObj->AddFirstRef(); | |||
52 | } | |||
53 | ||||
54 | ~SvRef() | |||
55 | { | |||
56 | if (pObj != nullptr) pObj->ReleaseRef(); | |||
57 | } | |||
58 | ||||
59 | void clear() | |||
60 | { | |||
61 | if (pObj != nullptr) { | |||
62 | T * pRefObj = pObj; | |||
63 | pObj = nullptr; | |||
64 | pRefObj->ReleaseRef(); | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | SvRef & operator =(SvRef const & rObj) | |||
69 | { | |||
70 | if (rObj.pObj != nullptr) { | |||
71 | rObj.pObj->AddNextRef(); | |||
72 | } | |||
73 | T * pRefObj = pObj; | |||
74 | pObj = rObj.pObj; | |||
75 | if (pRefObj != nullptr) { | |||
76 | pRefObj->ReleaseRef(); | |||
77 | } | |||
78 | return *this; | |||
79 | } | |||
80 | ||||
81 | SvRef & operator =(SvRef && rObj) | |||
82 | { | |||
83 | if (pObj != nullptr) { | |||
84 | pObj->ReleaseRef(); | |||
85 | } | |||
86 | pObj = rObj.pObj; | |||
87 | rObj.pObj = nullptr; | |||
88 | return *this; | |||
89 | } | |||
90 | ||||
91 | bool is() const { return pObj != nullptr; } | |||
92 | ||||
93 | explicit operator bool() const { return is(); } | |||
94 | ||||
95 | T * get() const { return pObj; } | |||
96 | ||||
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } | |||
| ||||
98 | ||||
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } | |||
100 | ||||
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } | |||
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } | |||
103 | ||||
104 | private: | |||
105 | T * pObj; | |||
106 | }; | |||
107 | ||||
108 | /** | |||
109 | * This implements similar functionality to std::make_shared. | |||
110 | */ | |||
111 | template<typename T, typename... Args> | |||
112 | SvRef<T> make_ref(Args&& ... args) | |||
113 | { | |||
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); | |||
115 | } | |||
116 | ||||
117 | } | |||
118 | ||||
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ | |||
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase | |||
121 | { | |||
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* | |||
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object | |||
124 | unsigned int nRefCount : 31; | |||
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields | |||
126 | unsigned int bNoDelete : 1; | |||
127 | ||||
128 | protected: | |||
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; | |||
130 | ||||
131 | public: | |||
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} | |||
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} | |||
134 | ||||
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } | |||
136 | ||||
137 | void RestoreNoDelete() | |||
138 | { bNoDelete = 1; } | |||
139 | ||||
140 | void AddNextRef() | |||
141 | { | |||
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); | |||
143 | ++nRefCount; | |||
144 | } | |||
145 | ||||
146 | void AddFirstRef() | |||
147 | { | |||
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); | |||
149 | if( bNoDelete ) | |||
150 | bNoDelete = 0; | |||
151 | ++nRefCount; | |||
152 | } | |||
153 | ||||
154 | void ReleaseRef() | |||
155 | { | |||
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); | |||
157 | if( --nRefCount == 0 && !bNoDelete) | |||
158 | { | |||
159 | // I'm not sure about the original purpose of this line, but right now | |||
160 | // it serves the purpose that anything that attempts to do an AddRef() | |||
161 | // after an object is deleted will trip an assert. | |||
162 | nRefCount = 1 << 30; | |||
163 | delete this; | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | unsigned int GetRefCount() const | |||
168 | { return nRefCount; } | |||
169 | }; | |||
170 | ||||
171 | template<typename T> | |||
172 | class SvCompatWeakBase; | |||
173 | ||||
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. | |||
175 | */ | |||
176 | template<typename T> | |||
177 | class SvCompatWeakHdl final : public SvRefBase | |||
178 | { | |||
179 | friend class SvCompatWeakBase<T>; | |||
180 | T* _pObj; | |||
181 | ||||
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} | |||
183 | ||||
184 | public: | |||
185 | void ResetWeakBase( ) { _pObj = nullptr; } | |||
186 | T* GetObj() { return _pObj; } | |||
187 | }; | |||
188 | ||||
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. | |||
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. | |||
191 | */ | |||
192 | template<typename T> | |||
193 | class SvCompatWeakBase | |||
194 | { | |||
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
196 | ||||
197 | public: | |||
198 | /** Does not use initializer due to compiler warnings, | |||
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. | |||
200 | */ | |||
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } | |||
202 | ||||
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } | |||
204 | ||||
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } | |||
206 | }; | |||
207 | ||||
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. | |||
209 | */ | |||
210 | template<typename T> | |||
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef | |||
212 | { | |||
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
214 | public: | |||
215 | SvCompatWeakRef( ) {} | |||
216 | SvCompatWeakRef( T* pObj ) | |||
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } | |||
218 | #if defined(__COVERITY__) | |||
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} | |||
220 | #endif | |||
221 | SvCompatWeakRef& operator = ( T * pObj ) | |||
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } | |||
223 | bool is() const | |||
224 | { return _xHdl.is() && _xHdl->GetObj(); } | |||
225 | explicit operator bool() const { return is(); } | |||
226 | T* operator -> () const | |||
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
228 | operator T* () const | |||
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
230 | }; | |||
231 | ||||
232 | #endif | |||
233 | ||||
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |