2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "navigation-control-impl.h"
22 #include <dali/public-api/animation/animation.h>
23 #include <dali/public-api/events/key-event.h>
24 #include <dali/public-api/object/type-registry.h>
27 #include <dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h>
28 #include <dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h>
29 #include <dali-toolkit/internal/controls/relayout-controller.h>
30 #include <dali-toolkit/public-api/focus-manager/focus-manager.h>
41 namespace // to register type
45 return Toolkit::NavigationControl::New();
48 TypeRegistration mType( typeid(Toolkit::NavigationControl), typeid(Toolkit::Control), Create );
50 TypeAction a1(mType, Toolkit::NavigationControl::ACTION_PUSH, &NavigationControl::DoAction);
51 TypeAction a2(mType, Toolkit::NavigationControl::ACTION_POP, &NavigationControl::DoAction);
54 NavigationControl::NavigationControl()
55 : Control( REQUIRES_TOUCH_EVENTS ),
58 mOrientationAngle( 0 ),
59 mOrientationAnimationDuration( 1.0f ),
60 mOrientationAnimationAlphaFunc( AlphaFunctions::EaseOut ),
61 mItemPositionCoefficient( Vector3( 0.0f, 1.0f, 0.0f) ),
67 NavigationControl::~NavigationControl()
69 // Clear all the items in the stack, forces their destruction before NavigationControl is destroyed.
73 void NavigationControl::OnInitialize()
75 //create layers for display background, current item, and bars respectively
76 mBackgroundLayer = CreateLayer();
77 mContentLayer = CreateLayer();
78 mBarLayer = CreateLayer();
79 mPopupLayer = CreateLayer();
82 void NavigationControl::OnControlChildAdd( Actor& child )
84 Toolkit::Page page = Toolkit::Page::DownCast(child);
86 // If it's a page then store it locally, Off stage.
89 mUnpushedItems.push_back(page);
91 // Orphan it until needed later during "push".
92 Self().Remove( child );
96 Toolkit::NavigationControl NavigationControl::New()
98 // Create the implementation, temporarily owned by this handle on stack
99 IntrusivePtr< NavigationControl > internalNavigationControl = new NavigationControl();
101 // Pass ownership to CustomActor handle
102 Toolkit::NavigationControl navigationControl( *internalNavigationControl );
104 // Second-phase init of the implementation
105 // This can only be done after the CustomActor connection has been made...
106 internalNavigationControl->Initialize();
108 return navigationControl;
111 void NavigationControl::OnStageConnection()
113 //only works when navigation control is already on stage!
114 mContentLayer.RaiseAbove( mBackgroundLayer );
115 mBarLayer.RaiseAbove( mContentLayer );
116 mPopupLayer.RaiseAbove( mBarLayer );
117 Self().SetSensitive(true);
121 void NavigationControl::PushItem( Toolkit::Page page )
123 // check the uninitialized item
124 // check the duplicated push for the top item
125 if(!page || page == mCurrentItem)
132 mContentLayer.Remove( mCurrentItem );
135 //push the new item into the stack and show it
136 mItemStack.push_back(page);
138 mContentLayer.Add(page);
139 mCurrentItem.SetPositionInheritanceMode(USE_PARENT_POSITION_PLUS_LOCAL_POSITION);
141 //set up the popup menu which would response to the KEY_MENU
145 Toolkit::NavigationControl handle( GetOwner() );
146 mItemPushedSignal.Emit(handle, page);
149 Toolkit::Page NavigationControl::PopItem()
151 // cannot pop out the bottom-most item
152 Toolkit::Page poppedItem;
153 if(mItemStack.size() > 1)
155 // pop out the top item of the stack and show the new item right under the old one.
156 mContentLayer.Remove(mCurrentItem);
157 poppedItem = mItemStack.back();
158 mItemStack.pop_back();
159 mCurrentItem = mItemStack.back();
160 mContentLayer.Add(mCurrentItem);
162 //set up the popup menu which would response to the KEY_MENU
167 Toolkit::NavigationControl handle( GetOwner() );
168 mItemPoppedSignal.Emit(handle, poppedItem);
173 size_t NavigationControl::GetItemCount() const
175 return mItemStack.size();
178 Toolkit::Page NavigationControl::GetItem(std::size_t index) const
180 DALI_ASSERT_ALWAYS( index < mItemStack.size() );
181 return mItemStack[index];
184 Toolkit::Page NavigationControl::GetCurrentItem() const
189 void NavigationControl::SetBackground( Actor background)
191 // It removes the old background
194 mBackgroundLayer.Remove( mBackground );
196 mBackgroundLayer.Add( background );
197 mBackground = background;
198 mBackground.SetSize( mControlSize );
201 void NavigationControl::CreateNavigationToolBar(Toolkit::NaviToolBarStyle toolBarStylePortrait,
202 Toolkit::NaviToolBarStyle toolBarStyleLandscape )
204 // Set a navigation tool bar at the bottom of the navigation frame
205 // the controls on the tool bar will update automatically when item is pushed or popped by responding to the signals
206 mToolBar = new NavigationToolBar(*this, toolBarStylePortrait, toolBarStyleLandscape);
209 void NavigationControl::CreateNavigationTitleBar(Toolkit::NaviTitleBarStyle titleBarStylePortrait,
210 Toolkit::NaviTitleBarStyle titleBarStyleLandscape)
212 // Set a navigation title bar at the top of the navigation frame
213 // the tile/subtitle/titl icon/buttons will update automatically when item is pushed or popped by responding to the signals
214 mTitleBar = new NavigationTitleBar(*this, titleBarStylePortrait, titleBarStyleLandscape);
217 void NavigationControl::OrientationChanged( int angle )
219 if( mOrientationAngle != angle )
221 Vector2 targetSize = Vector2(GetSizeSet());
223 // checking to see if changing from landscape -> portrait, or portrait -> landscape
224 if( mOrientationAngle%180 != angle%180 )
226 targetSize = Vector2( targetSize.height, targetSize.width );
229 mOrientationAngle = angle;
235 mItemPositionCoefficient = Vector3(0.0f, 1.0f, 0.0f);
240 mItemPositionCoefficient = Vector3(1.0f, 0.0f, 0.0f);
245 mItemPositionCoefficient = Vector3(0.0f, -1.0f, 0.0f);
250 mItemPositionCoefficient = Vector3(-1.0f, 0.0f, 0.0f);
255 DALI_ASSERT_ALWAYS(false);
260 Animation animation = Animation::New( mOrientationAnimationDuration );
261 animation.RotateTo( Self(), Degree( -angle ), Vector3::ZAXIS, mOrientationAnimationAlphaFunc );
264 Self().SetSize( targetSize );
270 void NavigationControl::SetOrientationRotateAnimation( float duration, AlphaFunction alphaFunc)
272 mOrientationAnimationDuration = duration;
273 mOrientationAnimationAlphaFunc = alphaFunc;
276 Layer NavigationControl::GetBarLayer() const
281 void NavigationControl::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
283 const Vector2 setSize( size );
287 // always set the current item to fully occupy navigationControl space apart from the bars,
288 // here the bars might be hidden if the current item does not need them
289 float positionOffset = 0.0f;
290 float sizeShrink = 0.0f;
293 positionOffset += mTitleBar->GetBarHeight()*0.5f;
294 sizeShrink += mTitleBar->GetBarHeight();
298 positionOffset -= mToolBar->GetBarHeight()*0.5f;
299 sizeShrink += mToolBar->GetBarHeight();
301 mCurrentItem.SetPosition( mItemPositionCoefficient * positionOffset);
302 Vector2 itemSize( setSize.x, setSize.y-sizeShrink );
304 Relayout(mCurrentItem, itemSize, container);
307 container.push_back(ActorSizePair( mBarLayer, setSize ));
308 container.push_back(ActorSizePair( mPopupLayer, setSize ));
311 void NavigationControl::OnControlSizeSet( const Vector3& size )
313 if( mControlSize == Vector2(size) )
317 mControlSize = Vector2(size);
319 mBarLayer.SetSize(mControlSize);
320 mPopupLayer.SetSize(mControlSize);
324 mBackground.SetSize( mControlSize );
328 mToolBar->ScaleStyleUpdate( mControlSize, mOrientationAngle );
332 mTitleBar->ScaleStyleUpdate( mControlSize, mOrientationAngle );
336 bool NavigationControl::OnKeyEvent( const KeyEvent& event )
338 bool consumed = false;
340 if(event.state == KeyEvent::Down)
342 if(event.keyCode == 96 ) // F12 == for test
343 //if( event.keyCode == Dali::DALI_KEY_BACK || event.keyCode == Dali::DALI_KEY_ESCAPE )
345 if( mPopupMenu && mPopupMenu.IsSensitive() ) // State:POPUP_SHOW
356 if( mPopupMenu && event.keyCode == 9)
357 //if( mPopupMenu && ( event.keyCode == Dali::DALI_KEY_MENU || event.keyCode == Dali::DALI_KEY_SEND ) )
358 //Todo: replace with dali key enum after the mapping between X key definition and dali key enum is implemented in dali-adapto
359 //if( mPopupMenu && event.keyPressedName == "XF86Send" )
361 if( !mPopupMenu.IsSensitive() ) // State: POPUP_HIDE
365 else // State:POPUP_SHOW
376 Layer NavigationControl::CreateLayer()
378 Layer layer = Layer::New();
379 layer.SetPositionInheritanceMode(USE_PARENT_POSITION);
384 void NavigationControl::SetupPopupMenu()
388 mPopupLayer.Remove( mPopupMenu );
390 mPopupMenu = mCurrentItem.GetPopupMenu();
393 mPopupLayer.Add( mPopupMenu );
394 mPopupMenu.OutsideTouchedSignal().Connect(this, &NavigationControl::OnPopupTouchedOutside);
398 void NavigationControl::OnPopupTouchedOutside()
406 Toolkit::NavigationControl::ItemPushedSignalV2& NavigationControl::ItemPushedSignal()
408 return mItemPushedSignal;
411 Toolkit::NavigationControl::ItemPoppedSignalV2& NavigationControl::ItemPoppedSignal()
413 return mItemPoppedSignal;
416 bool NavigationControl::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
420 Dali::BaseHandle handle(object);
421 Toolkit::NavigationControl control = Toolkit::NavigationControl::DownCast(handle);
422 DALI_ASSERT_ALWAYS(control);
424 if (Toolkit::NavigationControl::ACTION_PUSH == actionName)
426 for (PropertyValueConstIter iter = attributes.begin(); iter != attributes.end(); ++iter)
428 const Property::Value& value = *iter;
430 DALI_ASSERT_ALWAYS(value.GetType() == Property::STRING);
431 std::string itemName = value.Get<std::string> ();
433 for (std::list<Toolkit::Page>::iterator itemsIter = GetImpl(control).mUnpushedItems.begin(); itemsIter != GetImpl(control).mUnpushedItems.end(); ++itemsIter)
435 Toolkit::Page page = *itemsIter;
436 if (page.GetName() == itemName)
438 GetImpl(control).PushItem(page);
445 else if(Toolkit::NavigationControl::ACTION_POP == actionName)
447 GetImpl(control).PopItem();
455 } // namespace Internal
457 } // namespace Toolkit