demo-theme.json
simple-image-wall.js
/shared/resources-location.cpp
+/build/tizen/documentation.list
+/debugfiles.list
+/debuglinks.list
+/debugsources.list
#Replace @DEMO_STYLE_IMAGE_DIR@ in following files
CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/demo-theme.json.in ${LOCAL_STYLE_DIR}/demo-theme.json )
+CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/contact-cards-example-theme.json.in ${LOCAL_STYLE_DIR}/contact-cards-example-theme.json )
CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-one.json.in ${LOCAL_STYLE_DIR}/style-example-theme-one.json )
CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-two.json.in ${LOCAL_STYLE_DIR}/style-example-theme-two.json )
CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-three.json.in ${LOCAL_STYLE_DIR}/style-example-theme-three.json )
<ui-application appid="progress-bar.example" exec="/usr/apps/com.samsung.dali-demo/bin/progress-bar.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
<label>Progress Bar</label>
</ui-application>
+ <ui-application appid="contact-cards.example" exec="/usr/apps/com.samsung.dali-demo/bin/contact-cards.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
+ <label>Contact Cards</label>
+ </ui-application>
</manifest>
demo.AddExample(Example("styling.example", DALI_DEMO_STR_TITLE_STYLING));
demo.AddExample(Example("sparkle.example", DALI_DEMO_STR_TITLE_SPARKLE));
demo.AddExample(Example("progress-bar.example", DALI_DEMO_STR_TITLE_PROGRESS_BAR));
+ demo.AddExample(Example("contact-cards.example", DALI_DEMO_STR_TITLE_CONTACT_CARDS));
demo.SortAlphabetically( true );
--- /dev/null
+Please use contact-cards-example.cpp as your start point.
+The ContactCardController class has a brief explanation regarding what this example does and all the classes used in this example.
--- /dev/null
+/*
+ * Copyright (c) 2016 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 "clipped-image.h"
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/dali-toolkit.h>
+
+namespace ClippedImage
+{
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+
+const char * const DELTA_PROPERTY_NAME( "uDelta" ); ///< Name of uniform used to mix the Circle and Quad geometries.
+
+/**
+ * @brief This vertex-shader mixes in the quad and circle geometry depending on the value of uDelta.
+ *
+ * uDelta is used to mix in the Circle and the Quad positions.
+ * If uDelta is 0.0f, then the circle position is adopted and if it is 1.0f, then the quad position is adopted.
+ */
+const char * VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute mediump vec2 aPositionCircle;\n
+ attribute mediump vec2 aPositionQuad;\n
+ uniform mediump float uDelta;
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump vec3 uSize;\n
+ \n
+ void main()\n
+ {\n
+ mediump vec4 vertexPosition = vec4(mix(aPositionCircle,aPositionQuad,uDelta), 0.0, 1.0);\n
+ vertexPosition.xyz *= uSize;\n
+ gl_Position = uMvpMatrix * vertexPosition;\n
+ }\n
+);
+
+/**
+ * @brief This fragment-shader does not output anything. It's for a control which is just going to clip as specified in the vertex shader.
+ */
+const char * FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ void main()\n
+ {\n
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n
+ }\n
+);
+
+/**
+ * @brief Creates the shader required for the clipped image
+ * @return A reference to a static handle to a shader object (only created when first called).
+ */
+Shader& CreateShader()
+{
+ // Only need to create it once
+ // The issue with using a static is that the shader will only get destroyed at application destruction.
+ // This is OK for a simple use cases such as this example, but for more polished applications, the shader creation/destruction needs to
+ // be managed by the application writer.
+ static Shader shader;
+
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ }
+
+ return shader;
+}
+
+/**
+ * @brief Creates the geometry required for the clipped image
+ * @return A reference to a static handle to a geometry object (only created when first called).
+ */
+Geometry& CreateGeometry()
+{
+ // Only need to create it once
+ // The issue with using a static is that the geometry will only get destroyed at application destruction.
+ // This is OK for a simple use cases such as this example, but for more polished applications, the geometry creation/destruction needs to
+ // be managed by the application writer.
+ static Geometry geometry;
+
+ if ( !geometry )
+ {
+ const int vertexCount = 34; // Needs to be 4n plus 2 where n is a positive integer above 4
+
+ // Create the circle geometry
+
+ // Radius is bound to actor's dimensions so this should not be increased.
+ // If a bigger circle is required then the actor size should be increased.
+ const float radius = 0.5f;
+ const Vector2 center = Vector2::ZERO;
+
+ // Create a buffer for vertex data
+ Vector2 circleBuffer[vertexCount];
+ int idx = 0;
+
+ // Center vertex for triangle fan
+ circleBuffer[ idx++ ] = center;
+
+ // Outer vertices of the circle
+ const int outerVertexCount = vertexCount - 1;
+
+ for ( int i = 0; i < outerVertexCount; ++i )
+ {
+ const float percent = ( i / static_cast< float >( outerVertexCount - 1 ) );
+ const float rad = percent * 2.0f * Math::PI;
+
+ // Vertex position
+ Vector2 outer;
+ outer.x = center.x + radius * cos( rad );
+ outer.y = center.y + radius * sin( rad );
+
+ circleBuffer[ idx++ ] = outer;
+ }
+
+ Property::Map circleVertexFormat;
+ circleVertexFormat["aPositionCircle"] = Property::VECTOR2;
+ PropertyBuffer circleVertices = PropertyBuffer::New( circleVertexFormat );
+ circleVertices.SetData( circleBuffer, vertexCount );
+
+ // Create the Quad Geometry
+ Vector2 quadBuffer[vertexCount];
+ idx = 0;
+ quadBuffer[ idx++ ] = center;
+
+ const size_t vertsPerSide = ( vertexCount - 2 ) / 4;
+ Vector2 outer( 0.5f, 0.0f );
+ quadBuffer[ idx++ ] = outer;
+ float incrementPerBuffer = 1.0f / static_cast< float >( vertsPerSide );
+
+ for( size_t i = 0; i < vertsPerSide && outer.y < 0.5f; ++i )
+ {
+ outer.y += incrementPerBuffer;
+ quadBuffer[ idx++ ] = outer;
+ }
+
+ for( size_t i = 0; i < vertsPerSide && outer.x > -0.5f; ++i )
+ {
+ outer.x -= incrementPerBuffer;
+ quadBuffer[ idx++ ] = outer;
+ }
+
+ for( size_t i = 0; i < vertsPerSide && outer.y > -0.5f; ++i )
+ {
+ outer.y -= incrementPerBuffer;
+ quadBuffer[ idx++ ] = outer;
+ }
+
+ for( size_t i = 0; i < vertsPerSide && outer.x < 0.5f; ++i )
+ {
+ outer.x += incrementPerBuffer;
+ quadBuffer[ idx++ ] = outer;
+ }
+
+ for( size_t i = 0; i < vertsPerSide && outer.y < 0.0f; ++i )
+ {
+ outer.y += incrementPerBuffer;
+ quadBuffer[ idx++ ] = outer;
+ }
+
+ Property::Map vertexFormat;
+ vertexFormat["aPositionQuad"] = Property::VECTOR2;
+ PropertyBuffer quadVertices2 = PropertyBuffer::New( vertexFormat );
+ quadVertices2.SetData( quadBuffer, vertexCount );
+
+ // Create the geometry object itself
+ geometry = Geometry::New();
+ geometry.AddVertexBuffer( circleVertices );
+ geometry.AddVertexBuffer( quadVertices2 );
+ geometry.SetType( Geometry::TRIANGLE_FAN );
+ }
+
+ return geometry;
+}
+
+} // unnamed namespace
+
+const float CIRCLE_GEOMETRY = 0.0f;
+const float QUAD_GEOMETRY = 1.0f;
+
+Dali::Toolkit::Control Create( const std::string& imagePath, Property::Index& propertyIndex )
+{
+ // Create a control which whose geometry will be morphed between a circle and a quad
+ Control clippedImage = Control::New();
+ clippedImage.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN );
+
+ // Create the required renderer and add to the clipped image control
+ Renderer renderer = Renderer::New( CreateGeometry(), CreateShader() );
+ renderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+ clippedImage.AddRenderer( renderer );
+
+ // Register the property on the clipped image control which will allow animations between a circle and a quad
+ propertyIndex = clippedImage.RegisterProperty( DELTA_PROPERTY_NAME, 0.0f );
+
+ // Add the actual image to the control
+ Control image = ImageView::New( imagePath );
+ image.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ image.SetParentOrigin( ParentOrigin::CENTER );
+ image.SetAnchorPoint( AnchorPoint::CENTER );
+ clippedImage.Add( image );
+
+ return clippedImage;
+}
+
+} // namespace ClippedImage
--- /dev/null
+#ifndef CLIPPED_IMAGE_H
+#define CLIPPED_IMAGE_H
+
+/*
+ * Copyright (c) 2016 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 <string>
+#include <dali-toolkit/public-api/controls/control.h>
+
+/**
+ * @brief This namespace provides a helper function to create a control that clips an image either as a quad or a circle.
+ *
+ * The CIRCLE_GEOMETRY and QUAD_GEOMETRY constants can be used to set or animate to the different clipping geometries.
+ */
+namespace ClippedImage
+{
+
+extern const float CIRCLE_GEOMETRY; ///< Setting or animating the returned propertyIndex in Create() to this value will provide a circle geometry on the image @see Create
+extern const float QUAD_GEOMETRY; ///< Setting or animating the returned propertyIndex in Create() to this value will provide a quad geometry on the image @see Create
+
+/**
+ * @brief Creates a clipping image whose geometry (i.e. clip area) can be morphed between a circle and a quad by animating the propertyIndex out parameter.
+ *
+ * The propertyIndex parameter can be set or animated to CIRCLE_GEOMETRY or QUAD_GEOMETRY depending on the type of clipping required.
+ * If set to a value between these two constants, then the resulting geometry will be somewhere in between a circle and a quad.
+ *
+ * @param[in] imagePath The path to the image to show.
+ * @param[out] propertyIndex Gets set with the property index which the caller can animate using the CIRCLE_GEOMETRY & QUAD_GEOMETRY values.
+ * @return The image-mesh control
+ */
+Dali::Toolkit::Control Create( const std::string& imagePath, Dali::Property::Index& propertyIndex );
+
+} // namespace ClippedImage
+
+#endif // CLIPPED_IMAGE_H
--- /dev/null
+#ifndef CONTACT_CARD_LAYOUT_INFO_H
+#define CONTACT_CARD_LAYOUT_INFO_H
+
+/*
+ * Copyright (c) 2016 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 <dali/public-api/math/vector2.h>
+
+/**
+ * @brief This is the common data that is used by all contact cards.
+ *
+ * In this context, "unfolded" means when all the details, including the name, address and image are shown.
+ * In this scenario, the control takes up most of the screen and a header is also shown.
+ *
+ * When the contact card is "folded", this means when only brief information is shown to the user, i.e. the image and name.
+ * In this scenario, the control is small and there should be several of these contact cards visible on the screen.
+ */
+struct ContactCardLayoutInfo
+{
+ Dali::Vector2 unfoldedPosition; ///< The position of the entire contact card when all details (unfolded) are shown
+ Dali::Vector2 unfoldedSize; ///< The size of the entire contact card when all details (unfolded) are shown
+ Dali::Vector2 foldedSize; ///< The size of each contact card when only the brief information is shown (folded)
+
+ Dali::Vector2 padding; ///< The default padding to use throughout
+
+ Dali::Vector2 headerSize; ///< The size of the header area (only shown when unfolded)
+ Dali::Vector2 headerFoldedPosition; ///< The position of the header area when folded - required for animation purposes only as it's actually clipped
+ Dali::Vector2 headerUnfoldedPosition; ///< The position of the header area when unfolded
+
+ Dali::Vector2 imageSize; ///< The size of the image
+ Dali::Vector2 imageFoldedPosition; ///< The position of the image when folded
+ Dali::Vector2 imageUnfoldedPosition; ///< The position of the image when unfolded
+
+ Dali::Vector2 textFoldedPosition; ///< The position of the text when folded
+ Dali::Vector2 textUnfoldedPosition; ///< The position of the text when unfolded
+};
+
+#endif // CONTACT_CARD_LAYOUT_INFO_H
+
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// CLASS HEADER
+#include "contact-card-layouter.h"
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/stage.h>
+
+// INTERNAL INCLUDES
+#include "contact-card.h"
+
+using namespace Dali;
+
+namespace
+{
+const float DEFAULT_PADDING = 25.0f;
+
+const float MINIMUM_ITEMS_PER_ROW_OR_COLUMN( 3.0f );
+
+const float HEADER_HEIGHT_TO_UNFOLDED_SIZE_RATIO( 0.1f );
+const Vector2 HEADER_FOLDED_POSITION_AS_RATIO_OF_SIZE( -0.05f, -1.5f );
+const Vector2 HEADER_UNFOLDED_POSITION( Vector2::ZERO );
+
+const float IMAGE_SIZE_AS_RATIO_TO_FOLDED_SIZE( 0.5f );
+const Vector2 IMAGE_FOLDED_POSITION_AS_RATIO_OF_SIZE( 0.5f, 0.25f );
+
+const float FOLDED_TEXT_POSITION_AS_RATIO_OF_IMAGE_SIZE( 1.01f );
+} // unnamed namespace
+
+ContactCardLayouter::ContactCardLayouter()
+: mContactCardLayoutInfo(),
+ mContactCards(),
+ mLastPosition(),
+ mPositionIncrementer(),
+ mItemsPerRow( 0 ),
+ mInitialized( false )
+{
+}
+
+ContactCardLayouter::~ContactCardLayouter()
+{
+ // Nothing to do as ContactCardContainer uses intrusive pointers so they will be automatically deleted
+}
+
+void ContactCardLayouter::AddContact( const std::string& contactName, const std::string& contactAddress, const std::string& imagePath )
+{
+ if( ! mInitialized )
+ {
+ // Set up the common layouting info shared between all contact cards when first called
+
+ mContactCardLayoutInfo.unfoldedPosition = mContactCardLayoutInfo.padding = Vector2( DEFAULT_PADDING, DEFAULT_PADDING );
+ mContactCardLayoutInfo.unfoldedSize = Stage::GetCurrent().GetSize() - mContactCardLayoutInfo.padding * ( MINIMUM_ITEMS_PER_ROW_OR_COLUMN - 1.0f );
+
+ // Calculate the size of the folded card (use the minimum of width/height as size)
+ mContactCardLayoutInfo.foldedSize = ( mContactCardLayoutInfo.unfoldedSize - ( mContactCardLayoutInfo.padding * ( MINIMUM_ITEMS_PER_ROW_OR_COLUMN - 1.0f ) ) ) / MINIMUM_ITEMS_PER_ROW_OR_COLUMN;
+ mContactCardLayoutInfo.foldedSize.width = mContactCardLayoutInfo.foldedSize.height = std::min( mContactCardLayoutInfo.foldedSize.width, mContactCardLayoutInfo.foldedSize.height );
+
+ // Set the size and positions of the header
+ mContactCardLayoutInfo.headerSize.width = mContactCardLayoutInfo.unfoldedSize.width;
+ mContactCardLayoutInfo.headerSize.height = mContactCardLayoutInfo.unfoldedSize.height * HEADER_HEIGHT_TO_UNFOLDED_SIZE_RATIO;
+ mContactCardLayoutInfo.headerFoldedPosition = mContactCardLayoutInfo.headerSize * HEADER_FOLDED_POSITION_AS_RATIO_OF_SIZE;
+ mContactCardLayoutInfo.headerUnfoldedPosition = HEADER_UNFOLDED_POSITION;
+
+ // Set the image size and positions
+ mContactCardLayoutInfo.imageSize = mContactCardLayoutInfo.foldedSize * IMAGE_SIZE_AS_RATIO_TO_FOLDED_SIZE;
+ mContactCardLayoutInfo.imageFoldedPosition = mContactCardLayoutInfo.imageSize * IMAGE_FOLDED_POSITION_AS_RATIO_OF_SIZE;
+ mContactCardLayoutInfo.imageUnfoldedPosition.x = mContactCardLayoutInfo.padding.width;
+ mContactCardLayoutInfo.imageUnfoldedPosition.y = mContactCardLayoutInfo.headerSize.height + mContactCardLayoutInfo.padding.height;
+
+ // Set the positions of the contact name
+ mContactCardLayoutInfo.textFoldedPosition.x = 0.0f;
+ mContactCardLayoutInfo.textFoldedPosition.y = mContactCardLayoutInfo.imageFoldedPosition.x + mContactCardLayoutInfo.imageSize.height * FOLDED_TEXT_POSITION_AS_RATIO_OF_IMAGE_SIZE;
+ mContactCardLayoutInfo.textUnfoldedPosition.x = mContactCardLayoutInfo.padding.width;
+ mContactCardLayoutInfo.textUnfoldedPosition.y = mContactCardLayoutInfo.imageUnfoldedPosition.y + mContactCardLayoutInfo.imageSize.height + mContactCardLayoutInfo.padding.height;
+
+ // Figure out the positions of the contact cards
+ mItemsPerRow = ( mContactCardLayoutInfo.unfoldedSize.width + mContactCardLayoutInfo.padding.width ) / ( mContactCardLayoutInfo.foldedSize.width + mContactCardLayoutInfo.padding.width );
+ mLastPosition = mContactCardLayoutInfo.unfoldedPosition;
+ mPositionIncrementer.x = mContactCardLayoutInfo.foldedSize.width + mContactCardLayoutInfo.padding.width;
+ mPositionIncrementer.y = mContactCardLayoutInfo.foldedSize.height + mContactCardLayoutInfo.padding.height;
+
+ mInitialized = true;
+ }
+
+ // Create a new contact card and add to our container
+ mContactCards.push_back( new ContactCard( mContactCardLayoutInfo, contactName, contactAddress, imagePath, NextCardPosition() ) );
+}
+
+const Vector2& ContactCardLayouter::NextCardPosition()
+{
+ size_t currentNumOfCards = mContactCards.size();
+
+ if( currentNumOfCards )
+ {
+ if( currentNumOfCards % mItemsPerRow )
+ {
+ mLastPosition.x += mPositionIncrementer.x;
+ }
+ else // go to the next row
+ {
+ mLastPosition.x = mContactCardLayoutInfo.unfoldedPosition.x;
+ mLastPosition.y += mPositionIncrementer.y;
+ }
+ }
+ return mLastPosition;
+}
--- /dev/null
+#ifndef CONTACT_CARD_LAYOUTER_H
+#define CONTACT_CARD_LAYOUTER_H
+
+/*
+ * Copyright (c) 2016 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 <vector>
+#include <string>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include "contact-card-layout-info.h"
+
+class ContactCard;
+
+/**
+ * @brief This class lays out contact cards on the screen appropriately.
+ *
+ * The contact cards are added to the stage directly and it uses the stage size to figure out exactly how to layout them.
+ * It supports a minimum of 3 items on each row or column.
+ *
+ * Relayouting is not supported.
+ */
+class ContactCardLayouter
+{
+public:
+
+ /**
+ * @brief Constructor.
+ */
+ ContactCardLayouter();
+
+ /**
+ * @brief Destructor.
+ */
+ ~ContactCardLayouter();
+
+ /**
+ * @brief Creates a contact card with the given information.
+ * @param[in] contactName The name of the contact to display.
+ * @param[in] contactAddress The address of the contact to display.
+ * @param[in] imagePath The path to the image to display.
+ */
+ void AddContact( const std::string& contactName, const std::string& contactAddress, const std::string& imagePath );
+
+private:
+
+ /**
+ * @brief Calculates the next position of the contact card that's about to be added to our container.
+ * @return A reference to the next position.
+ */
+ const Dali::Vector2& NextCardPosition();
+
+ ContactCardLayoutInfo mContactCardLayoutInfo; ///< The common layouting information used by all contact cards. Set up when AddContact is first called.
+
+ typedef Dali::IntrusivePtr< ContactCard > ContactCardPtr; ///< Better than raw pointers as these are ref counted and the memory is released when the count reduces to 0.
+ typedef std::vector< ContactCardPtr > ContactCardContainer;
+ ContactCardContainer mContactCards; ///< Contains all the contact cards.
+
+ Dali::Vector2 mLastPosition; ///< The last position a contact card was added.
+ Dali::Vector2 mPositionIncrementer; ///< Calculated once when AddContact is first called.
+ size_t mItemsPerRow; ///< Calculated once when AddContact is first called and stores the number of items we have in a row.
+
+ bool mInitialized; ///< Whether initialization has taken place or not.
+};
+
+
+
+#endif // CONTACT_CARD_LAYOUTER_H
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+// CLASS HEADER
+#include "contact-card.h"
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/dali-toolkit.h>
+
+// INTERNAL INCLUDES
+#include "contact-card-layout-info.h"
+#include "clipped-image.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+/*
+ * The constants below are used to create the following Unfold Animation.
+ *
+ * 0ms 50 100 150 200 250 300 350 400 Total Animation time in Milliseconds
+ * | | | | | | | | |
+ * o-----------------------------------o | X Position Animation ( 0ms To 360ms)
+ * | o-----------------------------------o Y Position Animation (40ms To 400ms)
+ * o-----------------------------------o | Width Animation ( 0ms To 360ms)
+ * | o-----------------------------------o Height Animation (40ms To 400ms)
+ * o-------o | | | | | | | Fade out Name Text Animation ( 0ms To 80ms)
+ * | o-------o | | | | | Fade in Details Text Animation (80ms To 160ms)
+ * o---------------o | | | | | Fade out other cards Animation ( 0ms To 160ms)
+ * o---------------------------------------o Mesh Morph Animation ( 0ms To 400ms)
+ */
+const TimePeriod TIME_PERIOD_UNFOLD_X( 0.0f, 0.36f ); ///< Start at 0ms, duration 360ms
+const TimePeriod TIME_PERIOD_UNFOLD_Y( 0.04f, 0.36f ); ///< Start at 40ms, duration 360ms
+const TimePeriod TIME_PERIOD_UNFOLD_WIDTH( 0.0f, 0.36f ); ///< Start at 0ms, duration 360ms
+const TimePeriod TIME_PERIOD_UNFOLD_HEIGHT( 0.04f, 0.36f ); ///< Start at 40ms, duration 360ms
+const TimePeriod TIME_PERIOD_UNFOLD_NAME_OPACITY( 0.0f, 0.08f ); ///< Start at 0ms, duration 80ms
+const TimePeriod TIME_PERIOD_UNFOLD_DETAIL_OPACITY( 0.08f, 0.08f ); ///< Start at 80ms, duration 80ms
+const TimePeriod TIME_PERIOD_UNFOLD_SIBLING_OPACITY( 0.0f, 0.08f ); ///< Start at 0ms, duration 80ms
+const TimePeriod TIME_PERIOD_UNFOLD_MESH_MORPH( 0.0f, 0.4f ); ///< Start at 0ms, duration 400ms
+
+/*
+ * The constants below are used to create the following Fold Animation:
+ *
+ * 0ms 50 100 150 200 250 300 350 400 Total Animation time in Milliseconds
+ * | | | | | | | | |
+ * | |o---------------------------------o X Position Animation ( 64ms To 400ms)
+ * o---------------------------------o| | Y Position Animation ( 0ms To 336ms)
+ * | |o---------------------------------o Width Animation ( 64ms To 400ms)
+ * o---------------------------------o| | Height Animation ( 0ms To 336ms)
+ * | o-------o | | | | | Fade in Name Text animation ( 80ms To 160ms)
+ * o-------o | | | | | | | Fade out Details Text animation ( 0ms To 80ms)
+ * | | | | | | | o-------o Fade in other cards animation (320ms To 400ms)
+ * o---------------------------------------o Morph Animation ( 0ms To 400ms)
+ */
+const TimePeriod TIME_PERIOD_FOLD_X( 0.064f, 0.336f ); ///< Start at 64ms, duration 336ms
+const TimePeriod TIME_PERIOD_FOLD_Y( 0.0f, 0.336f ); ///< Start at 0ms, duration 336ms
+const TimePeriod TIME_PERIOD_FOLD_WIDTH( 0.064f, 0.336f ); ///< Start at 64ms, duration 336ms
+const TimePeriod TIME_PERIOD_FOLD_HEIGHT( 0.0f, 0.336f ); ///< Start at 0ms, duration 336ms
+const TimePeriod TIME_PERIOD_FOLD_NAME_OPACITY( 0.08f, 0.08f ); ///< Start at 80ms, duration 80ms
+const TimePeriod TIME_PERIOD_FOLD_DETAIL_OPACITY( 0.0f, 0.08f ); ///< Start at 0ms, duration 80ms
+const TimePeriod TIME_PERIOD_FOLD_SIBLING_OPACITY( 0.32f, 0.08f ); ///< Start at 320ms, duration 80ms
+const TimePeriod TIME_PERIOD_FOLD_MESH_MORPH( 0.0f, 0.4f ); ///< Start at 0ms, duration 400ms
+
+AlphaFunction ALPHA_FUNCTION_UNFOLD( AlphaFunction::DEFAULT ); ///< Alpha function used for the Unfold Animation
+AlphaFunction ALPHA_FUNCTION_FOLD( AlphaFunction::EASE_IN_OUT ); ///< Alpha function used for the Fold Animation
+
+const Vector4 HEADER_COLOR( 231.0f/255.0f, 231.0f/255.0f, 231.0f/255.0f, 1.0f ); ///< The color of the header
+
+} // unnamed namespace
+
+ContactCard::ContactCard(
+ const ContactCardLayoutInfo& contactCardLayoutInfo,
+ const std::string& contactName,
+ const std::string& contactAddress,
+ const std::string& imagePath,
+ const Vector2& position )
+: mTapDetector(),
+ mContactCard(),
+ mHeader(),
+ mClippedImage(),
+ mNameText(),
+ mDetailText(),
+ mSlotDelegate( this ),
+ mContactCardLayoutInfo( contactCardLayoutInfo ),
+ foldedPosition( position ),
+ mClippedImagePropertyIndex( Property::INVALID_INDEX ),
+ mFolded( true )
+{
+ // Create a control which will be used for the background and to clip the contents
+ mContactCard = Control::New();
+ mContactCard.SetProperty( Control::Property::BACKGROUND,
+ Property::Map().Add( Visual::Property::TYPE, Visual::COLOR )
+ .Add( ColorVisual::Property::MIX_COLOR, Color::WHITE ) );
+ mContactCard.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN );
+ mContactCard.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ mContactCard.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ mContactCard.SetPosition( foldedPosition.x, foldedPosition.y );
+ mContactCard.SetSize( mContactCardLayoutInfo.foldedSize );
+ Stage::GetCurrent().Add( mContactCard );
+
+ // Create the header which will be shown only when the contact is unfolded
+ mHeader = Control::New();
+ mHeader.SetSize( mContactCardLayoutInfo.headerSize );
+ mHeader.SetProperty( Control::Property::BACKGROUND,
+ Property::Map().Add( Visual::Property::TYPE, Visual::COLOR )
+ .Add( ColorVisual::Property::MIX_COLOR, HEADER_COLOR ) );
+ mHeader.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ mHeader.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ mHeader.SetPosition( mContactCardLayoutInfo.headerFoldedPosition.x, mContactCardLayoutInfo.headerFoldedPosition.y );
+
+ // Create a clipped image (whose clipping can be animated)
+ mClippedImage = ClippedImage::Create( imagePath, mClippedImagePropertyIndex );
+ mClippedImage.SetSize( mContactCardLayoutInfo.imageSize );
+ mClippedImage.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ mClippedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ mClippedImage.SetPosition( mContactCardLayoutInfo.imageFoldedPosition.x, mContactCardLayoutInfo.imageFoldedPosition.y );
+ mContactCard.Add( mClippedImage );
+
+ // Add the text label for just the name
+ mNameText = TextLabel::New( contactName );
+ mNameText.SetStyleName( "ContactNameTextLabel" );
+ mNameText.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ mNameText.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ mNameText.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
+ mNameText.SetPosition( mContactCardLayoutInfo.textFoldedPosition.x, mContactCardLayoutInfo.textFoldedPosition.y );
+ mContactCard.Add( mNameText );
+
+ // Create the detail text-label
+ std::string detailString( contactName );
+ detailString += "\n\n";
+ detailString += contactAddress;
+
+ mDetailText = TextLabel::New( detailString );
+ mDetailText.SetStyleName( "ContactDetailTextLabel" );
+ mDetailText.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ mDetailText.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ mDetailText.SetPosition( mContactCardLayoutInfo.textFoldedPosition.x, mContactCardLayoutInfo.textFoldedPosition.y );
+ mDetailText.SetSize( Vector2( mContactCardLayoutInfo.unfoldedSize.width - mContactCardLayoutInfo.textFoldedPosition.x * 2.0f, 0.0f ) );
+ mDetailText.SetOpacity( 0.0f );
+
+ // Attach tap detection to the overall clip control
+ mTapDetector = TapGestureDetector::New();
+ mTapDetector.Attach( mContactCard );
+ mTapDetector.DetectedSignal().Connect( mSlotDelegate, &ContactCard::OnTap );
+}
+
+ContactCard::~ContactCard()
+{
+ if( mContactCard )
+ {
+ mContactCard.Unparent();
+ }
+}
+
+void ContactCard::OnTap( Actor actor, const TapGesture& gesture )
+{
+ if( mFolded )
+ {
+ mContactCard.Add( mHeader );
+ mContactCard.Add( mDetailText );
+
+ // 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // Fade out all the siblings
+ Actor parent = actor.GetParent();
+ for( size_t i = 0; i < parent.GetChildCount(); ++i )
+ {
+ Actor sibling = parent.GetChildAt( i );
+ if( sibling != actor )
+ {
+ animation.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();
+ }
+ else
+ {
+ 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // 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 );
+
+ // Slowly fade in all the siblings
+ Actor parent = actor.GetParent();
+ for( size_t i = 0; i < parent.GetChildCount(); ++i )
+ {
+ Actor sibling = parent.GetChildAt( i );
+ if( sibling != actor )
+ {
+ animation.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();
+ }
+
+ mFolded = !mFolded;
+}
+
+void ContactCard::OnAnimationFinished( Dali::Animation& animation )
+{
+ if( mFolded )
+ {
+ mHeader.Unparent();
+ mDetailText.Unparent();
+ }
+ else
+ {
+ mNameText.Unparent();
+ }
+}
--- /dev/null
+#ifndef CONTACT_CARD_H
+#define CONTACT_CARD_H
+
+/*
+ * Copyright (c) 2016 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 <string>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/events/tap-gesture-detector.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali-toolkit/public-api/controls/control.h>
+
+class ContactCardLayoutInfo;
+
+/**
+ * @brief Creates and sets up animations for a contact card
+ *
+ * Each contact card has two states, folded and unfolded.
+ * In this context, "unfolded" means when all the details, including the name, address and image are shown.
+ * In this scenario, the control takes up most of the screen.
+ *
+ * When the contact card is "folded", this means when only brief information is shown to the user, i.e. the image and name.
+ * In this scenario, the control is small and there should be several of these contact cards visible on the screen.
+ *
+ * The contact card creates several controls that it requires to appropriately display itself in both of these states.
+ */
+class ContactCard : public Dali::RefObject
+{
+public:
+
+ /**
+ * @brief Constructor.
+ *
+ * This will create all the controls and add them to the stage so should only be called after the init-signal from the Application has been received.
+ *
+ * @param[in] contactCardLayoutInfo Reference to the common data used by all contact cards.
+ * @param[in] contactName The name of the contact to display.
+ * @param[in] contactAddress The address of the contact to display.
+ * @param[in] imagePath The path to the image to display.
+ * @param[in] position The unique folded position of this particular contact-card.
+ */
+ ContactCard( const ContactCardLayoutInfo& contactCardLayoutInfo, const std::string& contactName, const std::string& contactAddress, const std::string& imagePath, const Dali::Vector2& position );
+
+private:
+
+ /**
+ * @brief Private Destructor. Will only be deleted when ref-count goes to 0.
+ *
+ * Unparent the created contact card (i.e. remove from stage).
+ */
+ ~ContactCard();
+
+ /**
+ * @brief Called when this contact card is tapped.
+ * @param[in] actor The tapped actor.
+ * @param[in] gesture The tap gesture.
+ */
+ void OnTap( Dali::Actor actor, const Dali::TapGesture& gesture );
+
+ /**
+ * @brief Called when the animation finishes.
+ * @param[in] animation The animation which has just finished.
+ */
+ void OnAnimationFinished( Dali::Animation& animation );
+
+ 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 mNameText; ///< The text shown when folded.
+ Dali::Toolkit::Control mDetailText; ///< The text shown when unfolded.
+
+ 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.
+ const Dali::Vector2 foldedPosition; ///< The unique position of this card when it is folded.
+ Dali::Property::Index mClippedImagePropertyIndex; ///< Index used to animate the clipping of mClippedImage.
+ bool mFolded; ///< Whether the contact card is folded or not.
+};
+
+#endif // CONTACT_CARD_H
--- /dev/null
+/*
+ * Copyright (c) 2016 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 <vector>
+#include <dali/public-api/adaptor-framework/application.h>
+#include <dali/public-api/adaptor-framework/key.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/events/key-event.h>
+
+// INTERNAL INCLUDES
+#include "contact-card-layouter.h"
+#include "contact-data.h"
+
+using namespace Dali;
+
+namespace
+{
+const Vector4 STAGE_COLOR( 211.0f / 255.0f, 211.0f / 255.0f, 211.0f / 255.0f, 1.0f ); ///< The color of the stage
+const char * const THEME_PATH( DEMO_STYLE_DIR "contact-cards-example-theme.json" ); ///< The theme used for this example
+} // unnamed namespace
+
+/**
+ * @brief Creates several contact cards that animate between a folded and unfolded state.
+ *
+ * This demonstrates how different animations can start and stop at different times within the same Animation function.
+ * Additionally, this also shows how to morph between two different geometries.
+ *
+ * ContactCardLayouter: This class is used to lay out the different contact cards on the screen.
+ * This takes stage size into account but does not support relayouting.
+ * ContactCard: This class represents each contact card on the screen.
+ * Two animations are set up in this class which animate several properties with multiple start and stop times.
+ * An overview of the two animations can be found in contact-card.cpp.
+ * ContactCardLayoutInfo: This is a structure to store common layout information and is created by the ContactCardLayouter and used by each ContactCard.
+ * ContactData: This namespace contains a table which has the contact information we use to populate the contact cards.
+ * ClippedImage: This namespace provides a helper function which creates an ImageView which is added to a control that has clipping.
+ * 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.
+ */
+class ContactCardController : public ConnectionTracker // Inherit from ConnectionTracker so that our signals can be automatically disconnected upon our destruction.
+{
+public:
+
+ /**
+ * @brief Constructor.
+ * @param[in] application A reference to the Application class.
+ */
+ ContactCardController( Application& application )
+ : mApplication( application )
+ {
+ // Connect to the Application's Init signal
+ mApplication.InitSignal().Connect( this, &ContactCardController::Create );
+ }
+
+private:
+
+ /**
+ * @brief Called to initialise the application content
+ * @param[in] application A reference to the Application class.
+ */
+ void Create( Application& application )
+ {
+ // Hide the indicator bar
+ application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
+
+ // Set the stage background color and connect to the stage's key signal to allow Back and Escape to exit.
+ Stage stage = Stage::GetCurrent();
+ stage.SetBackgroundColor( STAGE_COLOR );
+ stage.KeyEventSignal().Connect( this, &ContactCardController::OnKeyEvent );
+
+ // Add all the contacts to the layouter
+ for( size_t i = 0; i < ContactData::TABLE_SIZE; ++i )
+ {
+ mContactCardLayouter.AddContact( ContactData::TABLE[ i ].name, ContactData::TABLE[ i ].address, ContactData::TABLE[ i ].imagePath );
+ }
+ }
+
+ /**
+ * @brief Called when any key event is received
+ *
+ * Will use this to quit the application if Back or the Escape key is received
+ * @param[in] event The key event information
+ */
+ void OnKeyEvent( const KeyEvent& event )
+ {
+ if( event.state == KeyEvent::Down )
+ {
+ if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
+ {
+ mApplication.Quit();
+ }
+ }
+ }
+
+ Application& mApplication; ///< Reference to the application class.
+ ContactCardLayouter mContactCardLayouter; ///< The contact card layouter.
+};
+
+int DALI_EXPORT_API main( int argc, char **argv )
+{
+ Application application = Application::New( &argc, &argv, THEME_PATH );
+ ContactCardController contactCardController( application );
+ application.MainLoop();
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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 "contact-data.h"
+
+namespace ContactData
+{
+
+const Item TABLE[] =
+{
+ { "Shelia Ramos", "19 Wormley Ct\nWinters Way\nWaltham Abbey\nEN9 3HW", DEMO_IMAGE_DIR "gallery-small-19.jpg" },
+ { "Walter Jensen", "32 Upper Fant Rd\nMaidstone\nME16 8DN", DEMO_IMAGE_DIR "gallery-small-2.jpg" },
+ { "Randal Parks", "8 Rymill St\nLondon\nE16 2JF", DEMO_IMAGE_DIR "gallery-small-3.jpg" },
+ { "Tasha Cooper", "2 Kyles View\nColintraive\nPA22 3AS", DEMO_IMAGE_DIR "gallery-small-4.jpg" },
+ { "Domingo Lynch", "Red Lion Farm\nWatlington\nOX49 5LG", DEMO_IMAGE_DIR "gallery-small-5.jpg" },
+ { "Dan Haynes", "239 Whitefield Dr\nLiverpool\nL32 0RD", DEMO_IMAGE_DIR "gallery-small-6.jpg" },
+ { "Leslie Wong", "1 Tullyvar Rd\nAughnacloy\nBT69 6BQ", DEMO_IMAGE_DIR "gallery-small-7.jpg" },
+ { "Mable Hodges", "5 Mortimer Rd\nGrazeley\nReading\nRG7 1LA", DEMO_IMAGE_DIR "gallery-small-8.jpg" },
+ { "Kristi Riley", "10 Jura Dr\nOld Kilpatrick\nGlasgow\nG60 5EH", DEMO_IMAGE_DIR "gallery-small-17.jpg" },
+ { "Terry Clark", "142 Raeberry St\nGlasgow\nG20 6EA", DEMO_IMAGE_DIR "gallery-small-18.jpg" },
+ { "Horace Bailey", "11 Assembly St\nNormanton\nWF6 2DB", DEMO_IMAGE_DIR "gallery-small-11.jpg" },
+ { "Suzanne Delgado", "6 Grange Rd\nDownpatrick\nBT30 7DB", DEMO_IMAGE_DIR "gallery-small-12.jpg" },
+ { "Jamie Bennett", "117 Potter St\nNorthwood\nHA6 1QF", DEMO_IMAGE_DIR "gallery-small-13.jpg" },
+ { "Emmett Yates", "18 Renfrew Way\nBletchley\nMilton Keynes\nMK3 7NY", DEMO_IMAGE_DIR "gallery-small-14.jpg" },
+ { "Glen Vaughn", "5 Hasman Terrace\nCove Bay\nAberdeen\nAB12 3GD", DEMO_IMAGE_DIR "gallery-small-15.jpg" },
+};
+const size_t TABLE_SIZE = sizeof( TABLE ) / sizeof( TABLE[ 0 ] );
+
+} // namespace ContactData
--- /dev/null
+#ifndef CONTACT_DATA_H
+#define CONTACT_DATA_H
+
+/*
+ * Copyright (c) 2016 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 <cstddef>
+
+namespace ContactData
+{
+
+/**
+ * @brief The information for an individual contact.
+ */
+struct Item
+{
+ const char * const name; ///< The name of the contact.
+ const char * const address; ///< The address of the contact.
+ const char * const imagePath; ///< The path to the image that represents the contact.
+};
+
+extern const Item TABLE[]; ///< The table that has the information for all the contacts.
+extern const size_t TABLE_SIZE; ///< The size of TABLE. Can use this to iterate through TABLE.
+
+} // namespace ContactData
+
+#endif // CONTACT_DATA_H
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "ঝুৰ্"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "অঁপইতা "
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "ঘনক পৰিৱৰ্তনীয় প্ৰভাৱ"
msgstr "Tasten"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
-msgstr "Farbverlauf "
+msgstr "Farbverlauf"
+
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "Kontakt"
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "Würfel Übergangseffekt"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "Colour Gradient"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "Contact Cards"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "Cube Effect"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "Color Gradient"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "Contact Cards"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "Cube Effect"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "Gradiente de color"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "Contactos"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "Transición cubos"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "Liukuväri"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "Yhteystietokortit"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "Kuutioefekti"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "색상 그라디언트"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "접촉"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "입방체 전환"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "വർണ്ണ ഗ്രേഡിയന്റ്"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "ബന്ധങ്ങൾ"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "സമചതുരക്കട്ട സംക്രമണ ഇഫക്ട്"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "رنگ میلان"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "لوگ"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "کیوب منتقلی"
msgid "DALI_DEMO_STR_TITLE_COLOR_GRADIENT"
msgstr "颜色梯度"
+msgid "DALI_DEMO_STR_TITLE_CONTACT_CARDS"
+msgstr "往来"
+
msgid "DALI_DEMO_STR_TITLE_CUBE_TRANSITION"
msgstr "方块切换效果"
demo-theme.json
+contact-cards-example-theme.json
style-example-theme-three.json
style-example-theme-two.json
style-example-theme-one.json
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+{
+ "styles":
+ {
+ "ContactNameTextLabel":
+ {
+ "textColor": [ 0, 0, 0, 1 ],
+ "horizontalAlignment": "CENTER",
+ "pointSize": 14
+ },
+
+ "ContactDetailTextLabel":
+ {
+ "textColor": [ 0, 0, 0, 1 ],
+ "multiLine": true,
+ "pointSize": 20
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+{
+ "styles":
+ {
+ "ContactNameTextLabel":
+ {
+ "textColor": [ 0, 0, 0, 1 ],
+ "horizontalAlignment": "CENTER",
+ "pointSize": 7
+ },
+
+ "ContactDetailTextLabel":
+ {
+ "textColor": [ 0, 0, 0, 1 ],
+ "multiLine": true,
+ "pointSize": 13
+ }
+ }
+}
#define DALI_DEMO_STR_TITLE_BUBBLES dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BUBBLES")
#define DALI_DEMO_STR_TITLE_BUTTONS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_BUTTONS")
#define DALI_DEMO_STR_TITLE_COLOR_GRADIENT dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_COLOR_GRADIENT")
+#define DALI_DEMO_STR_TITLE_CONTACT_CARDS dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CONTACT_CARDS")
#define DALI_DEMO_STR_TITLE_CUBE_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_CUBE_TRANSITION")
#define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION")
#define DALI_DEMO_STR_TITLE_EFFECTS_VIEW dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_EFFECTS_VIEW")
#define DALI_DEMO_STR_TITLE_BUBBLES "Bubbles"
#define DALI_DEMO_STR_TITLE_BUTTONS "Buttons"
#define DALI_DEMO_STR_TITLE_COLOR_GRADIENT "Color Gradient"
+#define DALI_DEMO_STR_TITLE_CONTACT_CARDS "Contact Cards"
#define DALI_DEMO_STR_TITLE_CUBE_TRANSITION "Cube Effect"
#define DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION "Dissolve Effect"
#define DALI_DEMO_STR_TITLE_EFFECTS_VIEW "Effects View"