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