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 <cstring> // for strcmp
23 #include <dali/public-api/animation/animation.h>
24 #include <dali/public-api/events/key-event.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/public-api/size-negotiation/relayout-container.h>
30 #include <dali-toolkit/public-api/focus-manager/focus-manager.h>
31 #include <dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h>
32 #include <dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h>
33 #include <dali-toolkit/public-api/focus-manager/focus-manager.h>
44 namespace // to register type
49 return Toolkit::NavigationControl::New();
52 // Setup properties, signals and actions using the type-registry.
53 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::NavigationControl, Toolkit::Control, Create )
55 DALI_ACTION_REGISTRATION( Toolkit, NavigationControl, "push", ACTION_PUSH )
56 DALI_ACTION_REGISTRATION( Toolkit, NavigationControl, "pop", ACTION_POP )
58 DALI_TYPE_REGISTRATION_END()
62 NavigationControl::NavigationControl()
63 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
66 mOrientationAngle( 0 ),
67 mOrientationAnimationDuration( 1.0f ),
68 mOrientationAnimationAlphaFunc( AlphaFunctions::EaseOut ),
69 mItemPositionCoefficient( Vector3( 0.0f, 1.0f, 0.0f) ),
75 NavigationControl::~NavigationControl()
77 // Clear all the items in the stack, forces their destruction before NavigationControl is destroyed.
81 void NavigationControl::OnInitialize()
83 //create layers for display background, current item, and bars respectively
84 mBackgroundLayer = CreateLayer();
85 mContentLayer = CreateLayer();
86 mBarLayer = CreateLayer();
87 mPopupLayer = CreateLayer();
90 void NavigationControl::OnControlChildAdd( Actor& child )
92 Toolkit::Page page = Toolkit::Page::DownCast(child);
94 // If it's a page then store it locally, Off stage.
97 mUnpushedItems.push_back(page);
99 // Orphan it until needed later during "push".
100 Self().Remove( child );
104 Toolkit::NavigationControl NavigationControl::New()
106 // Create the implementation, temporarily owned by this handle on stack
107 IntrusivePtr< NavigationControl > internalNavigationControl = new NavigationControl();
109 // Pass ownership to CustomActor handle
110 Toolkit::NavigationControl navigationControl( *internalNavigationControl );
112 // Second-phase init of the implementation
113 // This can only be done after the CustomActor connection has been made...
114 internalNavigationControl->Initialize();
116 return navigationControl;
119 void NavigationControl::OnStageConnection()
121 //only works when navigation control is already on stage!
122 mContentLayer.RaiseAbove( mBackgroundLayer );
123 mBarLayer.RaiseAbove( mContentLayer );
124 mPopupLayer.RaiseAbove( mBarLayer );
125 Self().SetSensitive(true);
129 void NavigationControl::PushItem( Toolkit::Page page )
131 // check the uninitialized item
132 // check the duplicated push for the top item
133 if(!page || page == mCurrentItem)
140 mContentLayer.Remove( mCurrentItem );
143 //push the new item into the stack and show it
144 mItemStack.push_back(page);
146 mContentLayer.Add(page);
147 mCurrentItem.SetPositionInheritanceMode(USE_PARENT_POSITION_PLUS_LOCAL_POSITION);
149 //set up the popup menu which would response to the KEY_MENU
153 Toolkit::NavigationControl handle( GetOwner() );
154 mItemPushedSignal.Emit(handle, page);
157 Toolkit::Page NavigationControl::PopItem()
159 // cannot pop out the bottom-most item
160 Toolkit::Page poppedItem;
161 if(mItemStack.size() > 1)
163 // pop out the top item of the stack and show the new item right under the old one.
164 mContentLayer.Remove(mCurrentItem);
165 poppedItem = mItemStack.back();
166 mItemStack.pop_back();
167 mCurrentItem = mItemStack.back();
168 mContentLayer.Add(mCurrentItem);
170 //set up the popup menu which would response to the KEY_MENU
175 Toolkit::NavigationControl handle( GetOwner() );
176 mItemPoppedSignal.Emit(handle, poppedItem);
181 size_t NavigationControl::GetItemCount() const
183 return mItemStack.size();
186 Toolkit::Page NavigationControl::GetItem(std::size_t index) const
188 DALI_ASSERT_ALWAYS( index < mItemStack.size() );
189 return mItemStack[index];
192 Toolkit::Page NavigationControl::GetCurrentItem() const
197 void NavigationControl::SetBackground( Actor background)
199 // It removes the old background
202 mBackgroundLayer.Remove( mBackground );
204 mBackgroundLayer.Add( background );
205 mBackground = background;
206 mBackground.SetSize( mControlSize );
209 void NavigationControl::CreateNavigationToolBar(Toolkit::NaviToolBarStyle toolBarStylePortrait,
210 Toolkit::NaviToolBarStyle toolBarStyleLandscape )
212 // Set a navigation tool bar at the bottom of the navigation frame
213 // the controls on the tool bar will update automatically when item is pushed or popped by responding to the signals
214 mToolBar = new NavigationToolBar(*this, toolBarStylePortrait, toolBarStyleLandscape);
217 void NavigationControl::CreateNavigationTitleBar(Toolkit::NaviTitleBarStyle titleBarStylePortrait,
218 Toolkit::NaviTitleBarStyle titleBarStyleLandscape)
220 // Set a navigation title bar at the top of the navigation frame
221 // the tile/subtitle/titl icon/buttons will update automatically when item is pushed or popped by responding to the signals
222 mTitleBar = new NavigationTitleBar(*this, titleBarStylePortrait, titleBarStyleLandscape);
225 void NavigationControl::OrientationChanged( int angle )
227 if( mOrientationAngle != angle )
229 Vector2 targetSize = Vector2(GetSizeSet());
231 // checking to see if changing from landscape -> portrait, or portrait -> landscape
232 if( mOrientationAngle%180 != angle%180 )
234 targetSize = Vector2( targetSize.height, targetSize.width );
237 mOrientationAngle = angle;
243 mItemPositionCoefficient = Vector3(0.0f, 1.0f, 0.0f);
248 mItemPositionCoefficient = Vector3(1.0f, 0.0f, 0.0f);
253 mItemPositionCoefficient = Vector3(0.0f, -1.0f, 0.0f);
258 mItemPositionCoefficient = Vector3(-1.0f, 0.0f, 0.0f);
263 DALI_ASSERT_ALWAYS(false);
269 Animation animation = Animation::New( mOrientationAnimationDuration );
270 animation.AnimateTo( Property( self, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( -angle ) ), Vector3::ZAXIS ), mOrientationAnimationAlphaFunc );
273 self.SetSize( targetSize );
279 void NavigationControl::SetOrientationRotateAnimation( float duration, AlphaFunction alphaFunc)
281 mOrientationAnimationDuration = duration;
282 mOrientationAnimationAlphaFunc = alphaFunc;
285 Layer NavigationControl::GetBarLayer() const
290 void NavigationControl::OnRelayout( const Vector2& size, RelayoutContainer& container )
292 const Vector2 setSize( size );
296 // always set the current item to fully occupy navigationControl space apart from the bars,
297 // here the bars might be hidden if the current item does not need them
298 float positionOffset = 0.0f;
299 float sizeShrink = 0.0f;
302 positionOffset += mTitleBar->GetBarHeight()*0.5f;
303 sizeShrink += mTitleBar->GetBarHeight();
307 positionOffset -= mToolBar->GetBarHeight()*0.5f;
308 sizeShrink += mToolBar->GetBarHeight();
310 mCurrentItem.SetPosition( mItemPositionCoefficient * positionOffset);
311 Vector2 itemSize( setSize.x, setSize.y-sizeShrink );
313 container.Add( mCurrentItem, itemSize );
316 container.Add( mBarLayer, setSize );
317 container.Add( mPopupLayer, setSize );
320 void NavigationControl::OnControlSizeSet( const Vector3& size )
322 if( mControlSize == Vector2(size) )
326 mControlSize = Vector2(size);
328 mBarLayer.SetSize(mControlSize);
329 mPopupLayer.SetSize(mControlSize);
333 mBackground.SetSize( mControlSize );
337 mToolBar->ScaleStyleUpdate( mControlSize, mOrientationAngle );
341 mTitleBar->ScaleStyleUpdate( mControlSize, mOrientationAngle );
345 bool NavigationControl::OnKeyEvent( const KeyEvent& event )
347 bool consumed = false;
349 if(event.state == KeyEvent::Down)
351 if(event.keyCode == 96 ) // F12 == for test
352 //if( event.keyCode == Dali::DALI_KEY_BACK || event.keyCode == Dali::DALI_KEY_ESCAPE )
354 if( mPopupMenu && mPopupMenu.IsSensitive() ) // State:POPUP_SHOW
365 if( mPopupMenu && event.keyCode == 9)
366 //if( mPopupMenu && ( event.keyCode == Dali::DALI_KEY_MENU || event.keyCode == Dali::DALI_KEY_SEND ) )
367 //Todo: replace with dali key enum after the mapping between X key definition and dali key enum is implemented in dali-adapto
368 //if( mPopupMenu && event.keyPressedName == "XF86Send" )
370 if( !mPopupMenu.IsSensitive() ) // State: POPUP_HIDE
374 else // State:POPUP_SHOW
385 Layer NavigationControl::CreateLayer()
387 Layer layer = Layer::New();
388 layer.SetPositionInheritanceMode(USE_PARENT_POSITION);
393 void NavigationControl::SetupPopupMenu()
397 mPopupLayer.Remove( mPopupMenu );
399 mPopupMenu = mCurrentItem.GetPopupMenu();
402 mPopupLayer.Add( mPopupMenu );
403 mPopupMenu.OutsideTouchedSignal().Connect(this, &NavigationControl::OnPopupTouchedOutside);
407 void NavigationControl::OnPopupTouchedOutside()
415 Toolkit::NavigationControl::ItemPushedSignalType& NavigationControl::ItemPushedSignal()
417 return mItemPushedSignal;
420 Toolkit::NavigationControl::ItemPoppedSignalType& NavigationControl::ItemPoppedSignal()
422 return mItemPoppedSignal;
425 bool NavigationControl::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
429 Dali::BaseHandle handle( object );
430 Toolkit::NavigationControl control = Toolkit::NavigationControl::DownCast( handle );
431 DALI_ASSERT_ALWAYS( control );
433 if( 0 == strcmp( actionName.c_str(), ACTION_PUSH ) )
435 for( PropertyValueConstIter iter = attributes.begin(); iter != attributes.end(); ++iter )
437 const Property::Value& value = *iter;
439 DALI_ASSERT_ALWAYS( value.GetType() == Property::STRING );
440 std::string itemName = value.Get<std::string>();
442 for( std::list<Toolkit::Page>::iterator itemsIter = GetImpl( control ).mUnpushedItems.begin(); itemsIter != GetImpl( control ).mUnpushedItems.end(); ++itemsIter )
444 Toolkit::Page page = *itemsIter;
445 if( page.GetName() == itemName )
447 GetImpl( control ).PushItem( page );
454 else if( 0 == strcmp( actionName.c_str(), ACTION_POP ) )
456 GetImpl( control ).PopItem();
464 } // namespace Internal
466 } // namespace Toolkit