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