Add a TextEditor property to limit input to maximum characters
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyinput-focus-manager-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "keyinput-focus-manager-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/actors/layer.h>
24 #include <dali-toolkit/public-api/controls/control-impl.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/adaptor-framework/adaptor.h>
27 #include <dali/integration-api/adaptor-framework/scene-holder.h>
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Internal
36 {
37
38 namespace
39 {
40
41 // Signals
42
43 const char* const SIGNAL_KEY_INPUT_FOCUS_CHANGED = "keyInputFocusChanged";
44
45 }
46
47 KeyInputFocusManager::KeyInputFocusManager()
48 : mSlotDelegate( this ),
49   mCurrentFocusControl()
50 {
51   // Retrieve all the existing widnows
52   Dali::SceneHolderList sceneHolders = Adaptor::Get().GetSceneHolders();
53   for( auto iter = sceneHolders.begin(); iter != sceneHolders.end(); ++iter )
54   {
55     ( *iter ).KeyEventGeneratedSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnKeyEvent );
56   }
57
58   // Get notified when any new scene holder is created afterwards
59   Adaptor::Get().WindowCreatedSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnSceneHolderCreated );
60 }
61
62 KeyInputFocusManager::~KeyInputFocusManager()
63 {
64 }
65
66 void KeyInputFocusManager::OnSceneHolderCreated( Dali::Integration::SceneHolder& sceneHolder )
67 {
68   sceneHolder.KeyEventGeneratedSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnKeyEvent );
69 }
70
71 void KeyInputFocusManager::SetFocus( Toolkit::Control control )
72 {
73   if( !control )
74   {
75     // No-op
76     return;
77   }
78
79   if( control == mCurrentFocusControl )
80   {
81     // Control already has focus
82     return;
83   }
84
85   control.OffStageSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnFocusControlStageDisconnection );
86
87   Dali::Toolkit::Control previousFocusControl = GetCurrentFocusControl();
88   if( previousFocusControl )
89   {
90     // Notify the control that it has lost key input focus
91     GetImplementation( previousFocusControl ).OnKeyInputFocusLost();
92   }
93
94   // Set control to currentFocusControl
95   mCurrentFocusControl = control;
96
97   // Tell the new actor that it has gained focus.
98   GetImplementation( control ).OnKeyInputFocusGained();
99
100   // Emit the signal to inform focus change to the application.
101   if ( !mKeyInputFocusChangedSignal.Empty() )
102   {
103     mKeyInputFocusChangedSignal.Emit( control, previousFocusControl );
104   }
105 }
106
107 void KeyInputFocusManager::RemoveFocus( Toolkit::Control control )
108 {
109   if( control == mCurrentFocusControl )
110   {
111     control.OffStageSignal().Disconnect( mSlotDelegate, &KeyInputFocusManager::OnFocusControlStageDisconnection );
112
113     // Notify the control that it has lost key input focus
114     GetImplementation( control ).OnKeyInputFocusLost();
115
116     mCurrentFocusControl.Reset();
117   }
118 }
119
120 Toolkit::Control KeyInputFocusManager::GetCurrentFocusControl() const
121 {
122   return mCurrentFocusControl;
123 }
124
125 Toolkit::KeyInputFocusManager::KeyInputFocusChangedSignalType& KeyInputFocusManager::KeyInputFocusChangedSignal()
126 {
127   return mKeyInputFocusChangedSignal;
128 }
129
130 bool KeyInputFocusManager::OnKeyEvent( const KeyEvent& event )
131 {
132   bool consumed = false;
133
134   Toolkit::Control control = GetCurrentFocusControl();
135   if( control )
136   {
137     // Notify the control about the key event
138     consumed = EmitKeyEventSignal( control, event );
139   }
140
141   return consumed;
142 }
143
144 bool KeyInputFocusManager::EmitKeyEventSignal( Toolkit::Control control, const KeyEvent& event )
145 {
146   bool consumed = false;
147
148   if( control )
149   {
150     consumed = GetImplementation( control ).EmitKeyEventSignal( event );
151
152     // if control doesn't consume KeyEvent, give KeyEvent to its parent.
153     if( !consumed )
154     {
155       Toolkit::Control parent = Toolkit::Control::DownCast( control.GetParent() );
156
157       if( parent )
158       {
159         consumed = EmitKeyEventSignal( parent, event );
160       }
161     }
162   }
163
164   return consumed;
165 }
166
167 void KeyInputFocusManager::OnFocusControlStageDisconnection( Dali::Actor actor )
168 {
169   RemoveFocus( Dali::Toolkit::Control::DownCast( actor ) );
170 }
171
172
173 bool KeyInputFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
174 {
175   bool connected( true );
176   KeyInputFocusManager* manager = dynamic_cast<KeyInputFocusManager*>( object );
177
178   if( manager )
179   {
180     if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_CHANGED ) )
181     {
182       manager->KeyInputFocusChangedSignal().Connect( tracker, functor );
183     }
184     else
185     {
186       // signalName does not match any signal
187       connected = false;
188     }
189   }
190
191   return connected;
192 }
193
194 } // namespace Internal
195
196 } // namespace Toolkit
197
198 } // namespace Dali