Make ItemView::ActivateLayout do what it says on the tin
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / focus-manager / keyinput-focus-manager-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include "keyinput-focus-manager-impl.h"
19
20 // INTERNAL INCLUDES
21 #include <dali-toolkit/public-api/controls/control-impl.h>
22 #include <dali/integration-api/debug.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
32
33 KeyInputFocusManager::KeyInputFocusManager()
34 : mSlotDelegate( this )
35 {
36   Stage::GetCurrent().KeyEventSignal().Connect(mSlotDelegate, &KeyInputFocusManager::OnKeyEvent);
37 }
38
39 KeyInputFocusManager::~KeyInputFocusManager()
40 {
41 }
42
43 void KeyInputFocusManager::SetFocus(Toolkit::Control control)
44 {
45   if(!control)
46   {
47    //No-op
48     return;
49   }
50
51   unsigned int actorID = control.GetId();
52
53   ActorQueueIterator pos = std::find( mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorID);
54
55   if((!mFocusActorsQueue.empty()) && (pos == mFocusActorsQueue.begin()))
56   {
57     //Actor allready in front, so No-op
58     return;
59   }
60
61   if(pos != mFocusActorsQueue.end())
62   {
63     //A previously focused actor wants to regain focus
64     mFocusActorsQueue.erase(pos);
65   }
66   else
67   {
68     control.OffStageSignal().Connect( mSlotDelegate, &KeyInputFocusManager::OnFocusActorStageDisconnection );
69   }
70
71   Dali::Toolkit::Control previousFocusControl;
72   if(!mFocusActorsQueue.empty())
73   {
74     previousFocusControl = Dali::Toolkit::Control::DownCast(Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front()));
75     if(previousFocusControl)
76     {
77       // Notify the control that it has lost key input focus
78       previousFocusControl.GetImplementation().OnKeyInputFocusLost();
79     }
80   }
81
82   mFocusActorsQueue.push_front(actorID);
83
84   // Tell the new actor that it has gained focus.
85   control.GetImplementation().OnKeyInputFocusGained();
86
87   // Emit the signal to inform focus change to the application.
88   if ( !mKeyInputFocusChangedSignalV2.Empty() )
89   {
90     mKeyInputFocusChangedSignalV2.Emit( control, previousFocusControl );
91   }
92 }
93
94 Control KeyInputFocusManager::GetCurrentFocusControl() const
95 {
96   Control currentFocusControl;
97
98   if(!mFocusActorsQueue.empty())
99   {
100     currentFocusControl = Dali::Toolkit::Control::DownCast(Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front()));
101   }
102
103   return currentFocusControl;
104 }
105
106 void KeyInputFocusManager::RemoveFocus(Toolkit::Control control)
107 {
108   if(control)
109   {
110     unsigned int actorId = control.GetId();
111     ActorQueueIterator pos = std::find( mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorId);
112
113     if(pos != mFocusActorsQueue.end())
114     {
115       control.OffStageSignal().Disconnect( mSlotDelegate, &KeyInputFocusManager::OnFocusActorStageDisconnection );
116
117       // Notify the control that it has lost key input focus
118       control.GetImplementation().OnKeyInputFocusLost();
119
120       if(pos == mFocusActorsQueue.begin())
121       {
122         Actor previousFocusActor;
123
124         mFocusActorsQueue.erase(pos);
125         if(!mFocusActorsQueue.empty())
126         {
127           previousFocusActor = Stage::GetCurrent().GetRootLayer().FindChildById(mFocusActorsQueue.front());
128         }
129
130         Dali::Toolkit::Control previouscontrol = Dali::Toolkit::Control::DownCast(previousFocusActor);
131         if(previouscontrol)
132         {
133           // Tell the new actor that it has gained focus.
134           previouscontrol.GetImplementation().OnKeyInputFocusGained();
135         }
136       }
137       else
138       {
139         //If the removed actor is not currently focused, then no need to emit signal.
140         mFocusActorsQueue.erase(pos);
141       }
142
143     }
144   }
145 }
146
147 bool KeyInputFocusManager::IsKeyboardListener(Toolkit::Control control) const
148 {
149   bool result = false;
150
151   if(!mFocusActorsQueue.empty())
152   {
153     unsigned int actorId = control.GetId();
154     ActorQueueConstIterator pos = std::find(mFocusActorsQueue.begin(), mFocusActorsQueue.end(), actorId);
155
156     if(pos != mFocusActorsQueue.end())
157     {
158       result = true;
159     }
160   }
161
162   return result;
163 }
164
165 Toolkit::KeyInputFocusManager::KeyInputFocusChangedSignalV2& KeyInputFocusManager::KeyInputFocusChangedSignal()
166 {
167   return mKeyInputFocusChangedSignalV2;
168 }
169
170 Toolkit::KeyInputFocusManager::UnhandledKeyEventSignalV2& KeyInputFocusManager::UnhandledKeyEventSignal()
171 {
172   return mUnhandledKeyEventSignalV2;
173 }
174
175 void KeyInputFocusManager::OnKeyEvent(const KeyEvent& event)
176 {
177   bool consumed = false;
178
179   ActorQueueIterator iter = mFocusActorsQueue.begin();
180
181   Layer rootLayer = Stage::GetCurrent().GetRootLayer();
182
183   while(!mFocusActorsQueue.empty() && !consumed && (iter != mFocusActorsQueue.end()))
184   {
185     Actor actor = rootLayer.FindChildById(*iter);
186     Dali::Toolkit::Control control = Dali::Toolkit::Control::DownCast(actor);
187     if(control)
188     {
189       // Notify the control about the key event
190       consumed = control.GetImplementation().EmitKeyEventSignal(event);
191     }
192     iter++;
193   }
194
195   if(!consumed)
196   {
197     // Emit signal to inform that a key event is not consumed.
198     if( !mUnhandledKeyEventSignalV2.Empty() )
199     {
200       mUnhandledKeyEventSignalV2.Emit(event);
201     }
202   }
203 }
204
205 void KeyInputFocusManager::OnFocusActorStageDisconnection( Dali::Actor actor )
206 {
207   RemoveFocus(Dali::Toolkit::Control::DownCast(actor));
208 }
209
210 bool KeyInputFocusManager::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
211 {
212   Dali::BaseHandle handle( object );
213
214   bool connected( true );
215   KeyInputFocusManager* manager = dynamic_cast<KeyInputFocusManager*>(object);
216
217   if( Dali::Toolkit::KeyInputFocusManager::SIGNAL_KEY_INPUT_FOCUS_CHANGED == signalName )
218   {
219     manager->KeyInputFocusChangedSignal().Connect( tracker, functor );
220   }
221   else
222   {
223     // signalName does not match any signal
224     connected = false;
225   }
226
227   return connected;
228 }
229
230 } // namespace Internal
231
232 } // namespace Toolkit
233
234 } // namespace Dali