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