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