From: Adeel Kazmi Date: Wed, 17 Oct 2018 17:37:40 +0000 (+0100) Subject: (ContactCards) Use a mask image when not animating & add Back/Esc key handling to... X-Git-Tag: dali_1.3.47~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F11%2F191511%2F2;p=platform%2Fcore%2Fuifw%2Fdali-demo.git (ContactCards) Use a mask image when not animating & add Back/Esc key handling to fold contact-cards - Applying a mask is better quality - When a contact card is unfolded and Esc/Back is pressed, the contact card is folded - Before we used to Quit the application Change-Id: I85f245dea9e24b98e312a7870129b2c44711ba2d --- diff --git a/examples/contact-cards/contact-card.cpp b/examples/contact-cards/contact-card.cpp index 61fd38e..60d3d0a 100644 --- a/examples/contact-cards/contact-card.cpp +++ b/examples/contact-cards/contact-card.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,12 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include "contact-card-layout-info.h" #include "clipped-image.h" +#include "masked-image.h" using namespace Dali; using namespace Dali::Toolkit; @@ -93,14 +95,20 @@ ContactCard::ContactCard( mContactCard(), mHeader(), mClippedImage(), + mMaskedImage(), mNameText(), mDetailText(), + mAnimation(), mSlotDelegate( this ), mContactCardLayoutInfo( contactCardLayoutInfo ), foldedPosition( position ), mClippedImagePropertyIndex( Property::INVALID_INDEX ), mFolded( true ) { + // Connect to the stage's key signal to allow Back and Escape to fold a contact card if it is unfolded + Stage stage = Stage::GetCurrent(); + stage.KeyEventSignal().Connect( mSlotDelegate, &ContactCard::OnKeyEvent ); + // Create a control which will be used for the background and to clip the contents mContactCard = Control::New(); mContactCard.SetProperty( Control::Property::BACKGROUND, @@ -111,7 +119,7 @@ ContactCard::ContactCard( mContactCard.SetAnchorPoint( AnchorPoint::TOP_LEFT ); mContactCard.SetPosition( foldedPosition.x, foldedPosition.y ); mContactCard.SetSize( mContactCardLayoutInfo.foldedSize ); - Stage::GetCurrent().Add( mContactCard ); + stage.Add( mContactCard ); // Create the header which will be shown only when the contact is unfolded mHeader = Control::New(); @@ -129,8 +137,17 @@ ContactCard::ContactCard( mClippedImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); mClippedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); mClippedImage.SetPosition( mContactCardLayoutInfo.imageFoldedPosition.x, mContactCardLayoutInfo.imageFoldedPosition.y ); + mClippedImage.SetVisible( false ); // Hide image as we only want to display it if we are animating or unfolded mContactCard.Add( mClippedImage ); + // Create an image with a mask which is to be used when the contact is folded + mMaskedImage = MaskedImage::Create( imagePath ); + mMaskedImage.SetSize( mContactCardLayoutInfo.imageSize ); + mMaskedImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mMaskedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mMaskedImage.SetPosition( mContactCardLayoutInfo.imageFoldedPosition.x, mContactCardLayoutInfo.imageFoldedPosition.y ); + mContactCard.Add( mMaskedImage ); + // Add the text label for just the name mNameText = TextLabel::New( contactName ); mNameText.SetStyleName( "ContactNameTextLabel" ); @@ -167,112 +184,158 @@ ContactCard::~ContactCard() } } -void ContactCard::OnTap( Actor actor, const TapGesture& gesture ) +void ContactCard::OnTap( Actor actor, const TapGesture& /* gesture */ ) +{ + if( actor == mContactCard ) + { + Animate(); + } +} + +void ContactCard::Animate() { + KeyInputFocusManager keyInputFocusManager = KeyInputFocusManager::Get(); + + mAnimation = Animation::New( 0.0f ); // Overall duration is unimportant as superseded by TimePeriods set later + if( mFolded ) { + // Set key-input-focus to our contact-card so that we can fold the contact-card if we receive a Back or Esc key + keyInputFocusManager.SetFocus( mContactCard ); + mContactCard.Add( mHeader ); mContactCard.Add( mDetailText ); + // Show clipped-image to animate geometry and hide the masked-image + mClippedImage.SetVisible( true ); + mMaskedImage.SetVisible( false ); + // Animate the size of the control (and clipping area) - Animation animation = Animation::New( 0.0f ); // Overall duration is unimportant as superseded by TimePeriods set later - animation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_X ), mContactCardLayoutInfo.unfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); - animation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.unfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); - animation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_WIDTH ), mContactCardLayoutInfo.unfoldedSize.width, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_WIDTH ); - animation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_HEIGHT ), mContactCardLayoutInfo.unfoldedSize.height, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_HEIGHT ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_X ), mContactCardLayoutInfo.unfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.unfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_WIDTH ), mContactCardLayoutInfo.unfoldedSize.width, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_WIDTH ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_HEIGHT ), mContactCardLayoutInfo.unfoldedSize.height, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_HEIGHT ); // Animate the header area into position - animation.AnimateTo( Property( mHeader, Actor::Property::POSITION_X ), mContactCardLayoutInfo.headerUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); - animation.AnimateTo( Property( mHeader, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.headerUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); + mAnimation.AnimateTo( Property( mHeader, Actor::Property::POSITION_X ), mContactCardLayoutInfo.headerUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); + mAnimation.AnimateTo( Property( mHeader, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.headerUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); // Animate the clipped image into the unfolded position and into a quad - animation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_X ), mContactCardLayoutInfo.imageUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); - animation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.imageUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); - animation.AnimateTo( Property( mClippedImage, mClippedImagePropertyIndex ), ClippedImage::QUAD_GEOMETRY, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_MESH_MORPH ); + mAnimation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_X ), mContactCardLayoutInfo.imageUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); + mAnimation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.imageUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); + mAnimation.AnimateTo( Property( mClippedImage, mClippedImagePropertyIndex ), ClippedImage::QUAD_GEOMETRY, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_MESH_MORPH ); // Fade out the opacity of the name, and animate into the unfolded position - animation.AnimateTo( Property( mNameText, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_NAME_OPACITY ); - animation.AnimateTo( Property( mNameText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); - animation.AnimateTo( Property( mNameText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_NAME_OPACITY ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); // Fade in the opacity of the detail, and animate into the unfolded position - animation.AnimateTo( Property( mDetailText, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_DETAIL_OPACITY ); - animation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); - animation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_DETAIL_OPACITY ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textUnfoldedPosition.x, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_X ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textUnfoldedPosition.y, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_Y ); // Fade out all the siblings - Actor parent = actor.GetParent(); + Actor parent = mContactCard.GetParent(); for( size_t i = 0; i < parent.GetChildCount(); ++i ) { Actor sibling = parent.GetChildAt( i ); - if( sibling != actor ) + if( sibling != mContactCard ) { - animation.AnimateTo( Property( sibling, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_SIBLING_OPACITY ); + mAnimation.AnimateTo( Property( sibling, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_UNFOLD, TIME_PERIOD_UNFOLD_SIBLING_OPACITY ); sibling.SetSensitive( false ); } } - animation.FinishedSignal().Connect( mSlotDelegate, &ContactCard::OnAnimationFinished ); - animation.Play(); + mAnimation.FinishedSignal().Connect( mSlotDelegate, &ContactCard::OnAnimationFinished ); + mAnimation.Play(); } else { + // Remove key-input-focus from our contact-card when we are folded + keyInputFocusManager.RemoveFocus( mContactCard ); + mContactCard.Add( mNameText ); // Animate the size of the control (and clipping area) - Animation animation = Animation::New( 0.0f ); // Overall duration is unimportant as superseded by TimePeriods set later - animation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_X ), foldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); - animation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_Y ), foldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); - animation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_WIDTH ), mContactCardLayoutInfo.foldedSize.width, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_WIDTH ); - animation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_HEIGHT ), mContactCardLayoutInfo.foldedSize.height, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_HEIGHT ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_X ), foldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::POSITION_Y ), foldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_WIDTH ), mContactCardLayoutInfo.foldedSize.width, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_WIDTH ); + mAnimation.AnimateTo( Property( mContactCard, Actor::Property::SIZE_HEIGHT ), mContactCardLayoutInfo.foldedSize.height, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_HEIGHT ); // Animate the header area out of position - animation.AnimateTo( Property( mHeader, Actor::Property::POSITION_X ), mContactCardLayoutInfo.headerFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); - animation.AnimateTo( Property( mHeader, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.headerFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); + mAnimation.AnimateTo( Property( mHeader, Actor::Property::POSITION_X ), mContactCardLayoutInfo.headerFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); + mAnimation.AnimateTo( Property( mHeader, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.headerFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); // Animate the clipped image into the folded position and into a circle - animation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_X ), mContactCardLayoutInfo.imageFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); - animation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.imageFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); - animation.AnimateTo( Property( mClippedImage, mClippedImagePropertyIndex ), ClippedImage::CIRCLE_GEOMETRY, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_MESH_MORPH ); + mAnimation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_X ), mContactCardLayoutInfo.imageFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); + mAnimation.AnimateTo( Property( mClippedImage, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.imageFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); + mAnimation.AnimateTo( Property( mClippedImage, mClippedImagePropertyIndex ), ClippedImage::CIRCLE_GEOMETRY, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_MESH_MORPH ); // Fade in the opacity of the name, and animate into the folded position - animation.AnimateTo( Property( mNameText, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_NAME_OPACITY ); - animation.AnimateTo( Property( mNameText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); - animation.AnimateTo( Property( mNameText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_NAME_OPACITY ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); + mAnimation.AnimateTo( Property( mNameText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); // Fade out the opacity of the detail, and animate into the folded position - animation.AnimateTo( Property( mDetailText, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_DETAIL_OPACITY ); - animation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); - animation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::COLOR_ALPHA ), 0.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_DETAIL_OPACITY ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_X ), mContactCardLayoutInfo.textFoldedPosition.x, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_X ); + mAnimation.AnimateTo( Property( mDetailText, Actor::Property::POSITION_Y ), mContactCardLayoutInfo.textFoldedPosition.y, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_Y ); // Slowly fade in all the siblings - Actor parent = actor.GetParent(); + Actor parent = mContactCard.GetParent(); for( size_t i = 0; i < parent.GetChildCount(); ++i ) { Actor sibling = parent.GetChildAt( i ); - if( sibling != actor ) + if( sibling != mContactCard ) { - animation.AnimateTo( Property( sibling, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_SIBLING_OPACITY ); + mAnimation.AnimateTo( Property( sibling, Actor::Property::COLOR_ALPHA ), 1.0f, ALPHA_FUNCTION_FOLD, TIME_PERIOD_FOLD_SIBLING_OPACITY ); sibling.SetSensitive( true ); } } - animation.FinishedSignal().Connect( mSlotDelegate, &ContactCard::OnAnimationFinished ); - animation.Play(); + mAnimation.FinishedSignal().Connect( mSlotDelegate, &ContactCard::OnAnimationFinished ); + mAnimation.Play(); } mFolded = !mFolded; } -void ContactCard::OnAnimationFinished( Dali::Animation& animation ) +void ContactCard::OnAnimationFinished( Animation& animation ) { - if( mFolded ) + // Ensure the finishing animation is the latest as we do not want to change state if a previous animation has finished + if( mAnimation == animation ) { - mHeader.Unparent(); - mDetailText.Unparent(); + if( mFolded ) + { + mHeader.Unparent(); + mDetailText.Unparent(); + + // Hide the clipped-image as we have finished animating the geometry and show the masked-image again + mClippedImage.SetVisible( false ); + mMaskedImage.SetVisible( true ); + } + else + { + mNameText.Unparent(); + } + mAnimation.Reset(); } - else +} + +void ContactCard::OnKeyEvent( const KeyEvent& event ) +{ + if( ( ! mFolded ) && // If we're folded then there's no need to do any more checking + ( event.state == KeyEvent::Down ) ) { - mNameText.Unparent(); + if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + { + KeyInputFocusManager keyInputFocusManager = KeyInputFocusManager::Get(); + if( keyInputFocusManager.GetCurrentFocusControl() == mContactCard ) + { + // Our contact-card is set to receive focus so call OnTap which should trigger the required animation + Animate(); + } + } } } diff --git a/examples/contact-cards/contact-card.h b/examples/contact-cards/contact-card.h index 043bfde..c922e58 100644 --- a/examples/contact-cards/contact-card.h +++ b/examples/contact-cards/contact-card.h @@ -2,7 +2,7 @@ #define CONTACT_CARD_H /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include #include #include #include @@ -67,24 +68,40 @@ private: /** * @brief Called when this contact card is tapped. - * @param[in] actor The tapped actor. - * @param[in] gesture The tap gesture. + * @param[in] actor The tapped actor. + * @param[in] gesture The tap gesture. */ void OnTap( Dali::Actor actor, const Dali::TapGesture& gesture ); /** + * @brief Animates the fold/unfold animation as required. + */ + void Animate(); + + /** * @brief Called when the animation finishes. - * @param[in] animation The animation which has just finished. + * @param[in] animation The animation which has just finished. */ void OnAnimationFinished( Dali::Animation& animation ); + /** + * @brief Called when any key event is received + * + * Will use this to fold a contact card if it is unfolded. + * @param[in] event The key event information + */ + void OnKeyEvent( const Dali::KeyEvent& event ); + Dali::TapGestureDetector mTapDetector; ///< Used for tap detection. Dali::Toolkit::Control mContactCard; ///< Used for the background and to clip the contents. Dali::Toolkit::Control mHeader; ///< Header shown when unfolded. Dali::Toolkit::Control mClippedImage; ///< The image representing the contact (whose clipping can be animated). + Dali::Toolkit::Control mMaskedImage; ///< The image with a mask (better quality around the edges than the clipped image when folded). Dali::Toolkit::Control mNameText; ///< The text shown when folded. Dali::Toolkit::Control mDetailText; ///< The text shown when unfolded. + Dali::Animation mAnimation; ///< The fold/unfold animation. + Dali::SlotDelegate< ContactCard > mSlotDelegate; ///< Used to automatically disconnect our member functions from signals that this class connects to upon destruction. Can be used instead of inheriting from ConnectionTracker. const ContactCardLayoutInfo& mContactCardLayoutInfo; ///< Reference to the common data used by all contact cards. diff --git a/examples/contact-cards/contact-cards-example.cpp b/examples/contact-cards/contact-cards-example.cpp index d9c4d57..a0967a1 100644 --- a/examples/contact-cards/contact-cards-example.cpp +++ b/examples/contact-cards/contact-cards-example.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,12 +21,14 @@ #include #include #include +#include // INTERNAL INCLUDES #include "contact-card-layouter.h" #include "contact-data.h" using namespace Dali; +using namespace Dali::Toolkit; namespace { @@ -51,6 +53,8 @@ const char * const THEME_PATH( DEMO_STYLE_DIR "contact-cards-example-theme.json" * This clipping comes in the form of a Circle or Quad. * The Vertex shader mixes in the Circle and Quad geometry depending on the value of a uniform float. * Animating this float between CIRCLE_GEOMETRY and QUAD_GEOMETRY is what enables the morphing between the two geometries. + * MaskedImage: This namespace provides a helper function which creates an ImageView with a mask that matches the Circle geometry provided by ClippedImage. + * Using a mask yields much better quality than when using an image with a circle geometry, so this is ONLY used when the contact card is folded. */ class ContactCardController : public ConnectionTracker // Inherit from ConnectionTracker so that our signals can be automatically disconnected upon our destruction. { @@ -100,9 +104,13 @@ private: { if( event.state == KeyEvent::Down ) { - if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + KeyInputFocusManager keyInputFocusManager = KeyInputFocusManager::Get(); + if( ! keyInputFocusManager.GetCurrentFocusControl() ) // Don't quit if a control has focus { - mApplication.Quit(); + if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + { + mApplication.Quit(); + } } } } diff --git a/examples/contact-cards/masked-image.cpp b/examples/contact-cards/masked-image.cpp new file mode 100644 index 0000000..abf7001 --- /dev/null +++ b/examples/contact-cards/masked-image.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// HEADER +#include "masked-image.h" + +// EXTERNAL INCLUDES +#include + +namespace MaskedImage +{ + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ +const char* const IMAGE_MASK ( DEMO_IMAGE_DIR "contact-cards-mask.png" ); +} // unnamed namespace + +Dali::Toolkit::Control Create( const std::string& imagePath ) +{ + Control maskedImage = ImageView::New(); + maskedImage.SetProperty( + Toolkit::ImageView::Property::IMAGE, + Property::Map().Add( Visual::Property::TYPE, Toolkit::Visual::Type::IMAGE ) + .Add( ImageVisual::Property::URL, imagePath ) + .Add( ImageVisual::Property::ALPHA_MASK_URL, IMAGE_MASK ) + ); + return maskedImage; +} + +} // namespace ClippedImage diff --git a/examples/contact-cards/masked-image.h b/examples/contact-cards/masked-image.h new file mode 100644 index 0000000..9fefc84 --- /dev/null +++ b/examples/contact-cards/masked-image.h @@ -0,0 +1,44 @@ +#ifndef MASKED_IMAGE_H +#define MASKED_IMAGE_H + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +/** + * @brief This namespace provides a helper function which creates an ImageView with a mask that matches the Circle geometry provided by ClippedImage. + * + * Using a mask yields much better quality than when using an image with a circle geometry. + * @see ClippedImage + */ +namespace MaskedImage +{ + +/** + * @brief Creates an image with a circular mask. + * + * @param[in] imagePath The path to the image to show. + * @return The ImageView with a mask control. + */ +Dali::Toolkit::Control Create( const std::string& imagePath ); + +} // namespace ClippedImage + +#endif // MASKED_IMAGE_H diff --git a/resources/images/contact-cards-mask.png b/resources/images/contact-cards-mask.png new file mode 100644 index 0000000..d2866c6 Binary files /dev/null and b/resources/images/contact-cards-mask.png differ