Line data Source code
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 : #include <vcl/decoview.hxx>
22 : #include <svtools/fmtfield.hxx>
23 : #include <vcl/xtextedt.hxx>
24 :
25 : #include <algorithm>
26 :
27 :
28 : namespace svt
29 : {
30 :
31 :
32 0 : TYPEINIT0(CellController);
33 117 : TYPEINIT1(EditCellController, CellController);
34 0 : TYPEINIT1(SpinCellController, CellController);
35 0 : TYPEINIT1(CheckBoxCellController, CellController);
36 0 : TYPEINIT1(ComboBoxCellController, CellController);
37 0 : TYPEINIT1(ListBoxCellController, CellController);
38 :
39 117 : TYPEINIT1( FormattedFieldCellController, EditCellController );
40 :
41 :
42 : //= ComboBoxControl
43 :
44 0 : ComboBoxControl::ComboBoxControl(vcl::Window* pParent, WinBits nWinStyle)
45 0 : :ComboBox(pParent, nWinStyle|WB_DROPDOWN|WB_NOBORDER)
46 : {
47 0 : EnableAutoSize(false);
48 0 : EnableAutocomplete(true);
49 0 : SetDropDownLineCount(5);
50 0 : }
51 :
52 :
53 0 : bool ComboBoxControl::PreNotify( NotifyEvent& rNEvt )
54 : {
55 0 : if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT && !IsInDropDown())
56 : {
57 0 : const KeyEvent *pEvt = rNEvt.GetKeyEvent();
58 0 : const vcl::KeyCode rKey = pEvt->GetKeyCode();
59 :
60 0 : if ((rKey.GetCode() == KEY_UP || rKey.GetCode() == KEY_DOWN) &&
61 0 : (!pEvt->GetKeyCode().IsShift() && pEvt->GetKeyCode().IsMod1()))
62 : {
63 : // select next resp. previous entry
64 0 : sal_Int32 nPos = GetEntryPos(GetText());
65 0 : int nDir = (rKey.GetCode() == KEY_DOWN ? 1 : -1);
66 0 : if (!((nPos == 0 && nDir == -1) || (nPos >= GetEntryCount() && nDir == 1)))
67 : {
68 0 : nPos += nDir;
69 0 : SetText(GetEntry(nPos));
70 : }
71 0 : return true;
72 : }
73 : }
74 0 : return ComboBox::PreNotify(rNEvt);
75 : }
76 :
77 : //= ComboBoxCellController
78 0 : ComboBoxCellController::ComboBoxCellController(ComboBoxControl* pWin)
79 0 : :CellController(pWin)
80 : {
81 0 : }
82 :
83 :
84 0 : bool ComboBoxCellController::MoveAllowed(const KeyEvent& rEvt) const
85 : {
86 0 : ComboBoxControl& rBox = GetComboBox();
87 0 : switch (rEvt.GetKeyCode().GetCode())
88 : {
89 : case KEY_END:
90 : case KEY_RIGHT:
91 : {
92 0 : Selection aSel = rBox.GetSelection();
93 0 : return !aSel && aSel.Max() == rBox.GetText().getLength();
94 : }
95 : case KEY_HOME:
96 : case KEY_LEFT:
97 : {
98 0 : Selection aSel = rBox.GetSelection();
99 0 : return !aSel && aSel.Min() == 0;
100 : }
101 : case KEY_UP:
102 : case KEY_DOWN:
103 0 : if (rBox.IsInDropDown())
104 0 : return false;
105 0 : if (!rEvt.GetKeyCode().IsShift() &&
106 0 : rEvt.GetKeyCode().IsMod1())
107 0 : return false;
108 : // drop down the list box
109 0 : else if (rEvt.GetKeyCode().IsMod2() && rEvt.GetKeyCode().GetCode() == KEY_DOWN)
110 0 : return false;
111 : // fall-through
112 : case KEY_PAGEUP:
113 : case KEY_PAGEDOWN:
114 : case KEY_RETURN:
115 0 : if (rBox.IsInDropDown())
116 0 : return false;
117 : default:
118 0 : return true;
119 : }
120 : }
121 :
122 :
123 0 : bool ComboBoxCellController::IsModified() const
124 : {
125 0 : return GetComboBox().IsValueChangedFromSaved();
126 : }
127 :
128 0 : void ComboBoxCellController::ClearModified()
129 : {
130 0 : GetComboBox().SaveValue();
131 0 : }
132 :
133 0 : void ComboBoxCellController::SetModifyHdl(const Link<>& rLink)
134 : {
135 0 : GetComboBox().SetModifyHdl(rLink);
136 0 : }
137 :
138 : //= ListBoxControl
139 0 : ListBoxControl::ListBoxControl(vcl::Window* pParent, WinBits nWinStyle)
140 0 : :ListBox(pParent, nWinStyle|WB_DROPDOWN|WB_NOBORDER)
141 : {
142 0 : EnableAutoSize(false);
143 0 : EnableMultiSelection(false);
144 0 : SetDropDownLineCount(20);
145 0 : }
146 :
147 0 : bool ListBoxControl::PreNotify( NotifyEvent& rNEvt )
148 : {
149 0 : if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT && !IsInDropDown())
150 : {
151 0 : const KeyEvent *pEvt = rNEvt.GetKeyEvent();
152 0 : const vcl::KeyCode rKey = pEvt->GetKeyCode();
153 :
154 0 : if ((rKey.GetCode() == KEY_UP || rKey.GetCode() == KEY_DOWN) &&
155 0 : (!pEvt->GetKeyCode().IsShift() && pEvt->GetKeyCode().IsMod1()))
156 : {
157 : // select next resp. previous entry
158 0 : sal_Int32 nPos = GetSelectEntryPos();
159 0 : int nDir = (rKey.GetCode() == KEY_DOWN ? 1 : -1);
160 0 : if (!((nPos == 0 && nDir == -1) || (nPos >= GetEntryCount() && nDir == 1)))
161 : {
162 0 : nPos += nDir;
163 0 : SelectEntryPos(nPos);
164 : }
165 0 : Select(); // for calling Modify
166 0 : return true;
167 : }
168 0 : else if (GetParent()->PreNotify(rNEvt))
169 0 : return true;
170 : }
171 0 : return ListBox::PreNotify(rNEvt);
172 : }
173 :
174 : //= ListBoxCellController
175 0 : ListBoxCellController::ListBoxCellController(ListBoxControl* pWin)
176 0 : :CellController(pWin)
177 : {
178 0 : }
179 :
180 :
181 0 : bool ListBoxCellController::MoveAllowed(const KeyEvent& rEvt) const
182 : {
183 0 : const ListBoxControl& rBox = GetListBox();
184 0 : switch (rEvt.GetKeyCode().GetCode())
185 : {
186 : case KEY_UP:
187 : case KEY_DOWN:
188 0 : if (!rEvt.GetKeyCode().IsShift() &&
189 0 : rEvt.GetKeyCode().IsMod1())
190 0 : return false;
191 : // drop down the list box
192 : else
193 0 : if (rEvt.GetKeyCode().IsMod2() && rEvt.GetKeyCode().GetCode() == KEY_DOWN)
194 0 : return false;
195 : // fall-through
196 : case KEY_PAGEUP:
197 : case KEY_PAGEDOWN:
198 0 : if (rBox.IsTravelSelect())
199 0 : return false;
200 : default:
201 0 : return true;
202 : }
203 : }
204 :
205 :
206 0 : bool ListBoxCellController::IsModified() const
207 : {
208 0 : return GetListBox().IsValueChangedFromSaved();
209 : }
210 :
211 :
212 0 : void ListBoxCellController::ClearModified()
213 : {
214 0 : GetListBox().SaveValue();
215 0 : }
216 :
217 :
218 0 : void ListBoxCellController::SetModifyHdl(const Link<>& rLink)
219 : {
220 0 : GetListBox().SetSelectHdl(rLink);
221 0 : }
222 :
223 :
224 : //= CheckBoxControl
225 :
226 :
227 20 : CheckBoxControl::CheckBoxControl(vcl::Window* pParent, WinBits nWinStyle)
228 20 : :Control(pParent, nWinStyle)
229 : {
230 20 : const Wallpaper& rParentBackground = pParent->GetBackground();
231 20 : if ( (pParent->GetStyle() & WB_CLIPCHILDREN) || rParentBackground.IsFixed() )
232 20 : SetBackground( rParentBackground );
233 : else
234 : {
235 0 : SetPaintTransparent( true );
236 0 : SetBackground();
237 : }
238 :
239 20 : EnableChildTransparentMode();
240 :
241 20 : pBox = VclPtr<TriStateBox>::Create(this,WB_CENTER|WB_VCENTER);
242 20 : pBox->SetLegacyNoTextAlign( true );
243 20 : pBox->EnableChildTransparentMode();
244 20 : pBox->SetPaintTransparent( true );
245 20 : pBox->SetClickHdl( LINK( this, CheckBoxControl, OnClick ) );
246 20 : pBox->Show();
247 20 : }
248 :
249 :
250 60 : CheckBoxControl::~CheckBoxControl()
251 : {
252 20 : disposeOnce();
253 40 : }
254 :
255 20 : void CheckBoxControl::dispose()
256 : {
257 20 : pBox.disposeAndClear();
258 20 : Control::dispose();
259 20 : }
260 :
261 :
262 0 : IMPL_LINK_NOARG(CheckBoxControl, OnClick)
263 : {
264 0 : m_aClickLink.Call(pBox);
265 0 : return m_aModifyLink.Call(pBox);
266 : }
267 :
268 :
269 0 : void CheckBoxControl::Resize()
270 : {
271 0 : Control::Resize();
272 0 : pBox->SetPosSizePixel(Point(0,0),GetSizePixel());
273 0 : }
274 :
275 :
276 114 : void CheckBoxControl::DataChanged( const DataChangedEvent& _rEvent )
277 : {
278 114 : if ( _rEvent.GetType() == DataChangedEventType::SETTINGS )
279 114 : pBox->SetSettings( GetSettings() );
280 114 : }
281 :
282 :
283 17 : void CheckBoxControl::StateChanged( StateChangedType nStateChange )
284 : {
285 17 : Control::StateChanged(nStateChange);
286 17 : if ( nStateChange == StateChangedType::Zoom )
287 0 : pBox->SetZoom(GetZoom());
288 17 : }
289 :
290 :
291 0 : void CheckBoxControl::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags )
292 : {
293 0 : pBox->Draw(pDev,rPos,rSize,nFlags);
294 0 : }
295 :
296 :
297 0 : void CheckBoxControl::GetFocus()
298 : {
299 0 : pBox->GrabFocus();
300 0 : }
301 :
302 :
303 0 : void CheckBoxControl::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rClientRect)
304 : {
305 0 : Control::Paint(rRenderContext, rClientRect);
306 0 : if (HasFocus())
307 0 : ShowFocus(aFocusRect);
308 0 : }
309 :
310 :
311 0 : bool CheckBoxControl::PreNotify(NotifyEvent& rEvt)
312 : {
313 0 : switch (rEvt.GetType())
314 : {
315 : case MouseNotifyEvent::GETFOCUS:
316 0 : ShowFocus(aFocusRect);
317 0 : break;
318 : case MouseNotifyEvent::LOSEFOCUS:
319 0 : HideFocus();
320 0 : break;
321 : default:
322 0 : break;
323 : }
324 0 : return Control::PreNotify(rEvt);
325 : }
326 :
327 :
328 : //= CheckBoxCellController
329 :
330 :
331 0 : bool CheckBoxCellController::WantMouseEvent() const
332 : {
333 0 : return true;
334 : }
335 :
336 :
337 0 : CheckBox& CheckBoxCellController::GetCheckBox() const
338 : {
339 0 : return static_cast<CheckBoxControl &>(GetWindow()).GetBox();
340 : }
341 :
342 :
343 0 : bool CheckBoxCellController::IsModified() const
344 : {
345 0 : return GetCheckBox().IsValueChangedFromSaved();
346 : }
347 :
348 :
349 0 : void CheckBoxCellController::ClearModified()
350 : {
351 0 : GetCheckBox().SaveValue();
352 0 : }
353 :
354 :
355 0 : void CheckBoxCellController::SetModifyHdl(const Link<>& rLink)
356 : {
357 0 : static_cast<CheckBoxControl &>(GetWindow()).SetModifyHdl(rLink);
358 0 : }
359 :
360 :
361 : //= MultiLineEditImplementation
362 :
363 :
364 0 : OUString MultiLineEditImplementation::GetText( LineEnd aSeparator ) const
365 : {
366 0 : return const_cast< MultiLineEditImplementation* >( this )->GetEditWindow().GetText( aSeparator );
367 : }
368 :
369 :
370 0 : OUString MultiLineEditImplementation::GetSelected( LineEnd aSeparator ) const
371 : {
372 0 : return const_cast< MultiLineEditImplementation* >( this )->GetEditWindow().GetSelected( aSeparator );
373 : }
374 :
375 :
376 : //= EditCellController
377 :
378 :
379 14 : EditCellController::EditCellController( Edit* _pEdit )
380 : :CellController( _pEdit )
381 14 : ,m_pEditImplementation( new EditImplementation( *_pEdit ) )
382 28 : ,m_bOwnImplementation( true )
383 : {
384 14 : }
385 :
386 :
387 17 : EditCellController::EditCellController( IEditImplementation* _pImplementation )
388 17 : :CellController( &_pImplementation->GetControl() )
389 : ,m_pEditImplementation( _pImplementation )
390 17 : ,m_bOwnImplementation( false )
391 : {
392 17 : }
393 :
394 :
395 79 : EditCellController::~EditCellController( )
396 : {
397 31 : if ( m_bOwnImplementation )
398 14 : DELETEZ( m_pEditImplementation );
399 48 : }
400 :
401 :
402 0 : void EditCellController::SetModified()
403 : {
404 0 : m_pEditImplementation->SetModified();
405 0 : }
406 :
407 :
408 1 : void EditCellController::ClearModified()
409 : {
410 1 : m_pEditImplementation->ClearModified();
411 1 : }
412 :
413 :
414 0 : bool EditCellController::MoveAllowed(const KeyEvent& rEvt) const
415 : {
416 : bool bResult;
417 0 : switch (rEvt.GetKeyCode().GetCode())
418 : {
419 : case KEY_END:
420 : case KEY_RIGHT:
421 : {
422 0 : Selection aSel = m_pEditImplementation->GetSelection();
423 0 : bResult = !aSel && aSel.Max() == m_pEditImplementation->GetText( LINEEND_LF ).getLength();
424 0 : } break;
425 : case KEY_HOME:
426 : case KEY_LEFT:
427 : {
428 0 : Selection aSel = m_pEditImplementation->GetSelection();
429 0 : bResult = !aSel && aSel.Min() == 0;
430 0 : } break;
431 : default:
432 0 : bResult = true;
433 : }
434 0 : return bResult;
435 : }
436 :
437 :
438 3 : bool EditCellController::IsModified() const
439 : {
440 3 : return m_pEditImplementation->IsModified();
441 : }
442 :
443 :
444 2 : void EditCellController::SetModifyHdl(const Link<>& rLink)
445 : {
446 2 : m_pEditImplementation->SetModifyHdl(rLink);
447 2 : }
448 :
449 :
450 : //= SpinCellController
451 :
452 :
453 0 : SpinCellController::SpinCellController(SpinField* pWin)
454 0 : :CellController(pWin)
455 : {
456 0 : }
457 :
458 :
459 0 : void SpinCellController::SetModified()
460 : {
461 0 : GetSpinWindow().SetModifyFlag();
462 0 : }
463 :
464 :
465 0 : void SpinCellController::ClearModified()
466 : {
467 0 : GetSpinWindow().ClearModifyFlag();
468 0 : }
469 :
470 :
471 0 : bool SpinCellController::MoveAllowed(const KeyEvent& rEvt) const
472 : {
473 : bool bResult;
474 0 : switch (rEvt.GetKeyCode().GetCode())
475 : {
476 : case KEY_END:
477 : case KEY_RIGHT:
478 : {
479 0 : Selection aSel = GetSpinWindow().GetSelection();
480 0 : bResult = !aSel && aSel.Max() == GetSpinWindow().GetText().getLength();
481 0 : } break;
482 : case KEY_HOME:
483 : case KEY_LEFT:
484 : {
485 0 : Selection aSel = GetSpinWindow().GetSelection();
486 0 : bResult = !aSel && aSel.Min() == 0;
487 0 : } break;
488 : default:
489 0 : bResult = true;
490 : }
491 0 : return bResult;
492 : }
493 :
494 :
495 0 : bool SpinCellController::IsModified() const
496 : {
497 0 : return GetSpinWindow().IsModified();
498 : }
499 :
500 :
501 0 : void SpinCellController::SetModifyHdl(const Link<>& rLink)
502 : {
503 0 : GetSpinWindow().SetModifyHdl(rLink);
504 0 : }
505 :
506 :
507 : //= FormattedFieldCellController
508 :
509 :
510 14 : FormattedFieldCellController::FormattedFieldCellController( FormattedField* _pFormatted )
511 14 : :EditCellController( _pFormatted )
512 : {
513 14 : }
514 :
515 :
516 1 : void FormattedFieldCellController::CommitModifications()
517 : {
518 1 : static_cast< FormattedField& >( GetWindow() ).Commit();
519 1 : }
520 :
521 :
522 : //= MultiLineTextCell
523 :
524 :
525 0 : void MultiLineTextCell::Modify()
526 : {
527 0 : GetTextEngine()->SetModified( true );
528 0 : MultiLineEdit::Modify();
529 0 : }
530 :
531 :
532 0 : bool MultiLineTextCell::dispatchKeyEvent( const KeyEvent& _rEvent )
533 : {
534 0 : Selection aOldSelection( GetSelection() );
535 :
536 0 : bool bWasModified = IsModified();
537 0 : ClearModifyFlag( );
538 :
539 0 : bool bHandled = GetTextView()->KeyInput( _rEvent );
540 :
541 0 : bool bIsModified = IsModified();
542 0 : if ( bWasModified && !bIsModified )
543 : // not sure whether this can really happen
544 0 : SetModifyFlag();
545 :
546 0 : if ( bHandled ) // the view claimed it handled the key input
547 : {
548 : // unfortunately, KeyInput also returns <TRUE/> (means "I handled this key input")
549 : // when nothing really changed. Let's care for this.
550 0 : Selection aNewSelection( GetSelection() );
551 0 : if ( aNewSelection != aOldSelection // selection changed
552 0 : || bIsModified // or some other modification
553 : )
554 0 : return true;
555 : }
556 0 : return false;
557 : }
558 :
559 :
560 0 : bool MultiLineTextCell::PreNotify( NotifyEvent& rNEvt )
561 : {
562 0 : if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
563 : {
564 0 : if ( IsWindowOrChild( rNEvt.GetWindow() ) )
565 : {
566 : // give the text view a chance to handle the keys
567 : // this is necessary since a lot of keys which are normally handled
568 : // by this view (in KeyInput) are intercepted by the EditBrowseBox,
569 : // which uses them for other reasons. An example is the KeyUp key,
570 : // which is used by both the text view and the edit browse box
571 :
572 0 : const KeyEvent* pKeyEvent = rNEvt.GetKeyEvent();
573 0 : const vcl::KeyCode& rKeyCode = pKeyEvent->GetKeyCode();
574 0 : sal_uInt16 nCode = rKeyCode.GetCode();
575 :
576 0 : if ( ( nCode == KEY_RETURN ) && ( rKeyCode.GetModifier() == KEY_MOD1 ) )
577 : {
578 0 : KeyEvent aEvent( pKeyEvent->GetCharCode(),
579 : vcl::KeyCode( KEY_RETURN ),
580 0 : pKeyEvent->GetRepeat()
581 0 : );
582 0 : if ( dispatchKeyEvent( aEvent ) )
583 0 : return true;
584 : }
585 :
586 0 : if ( ( nCode != KEY_TAB ) && ( nCode != KEY_RETURN ) ) // everything but tab and enter
587 : {
588 0 : if ( dispatchKeyEvent( *pKeyEvent ) )
589 0 : return true;
590 : }
591 : }
592 : }
593 0 : return MultiLineEdit::PreNotify( rNEvt );
594 : }
595 :
596 :
597 798 : } // namespace svt
598 :
599 :
600 :
601 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|