diff --git a/examples/simple-layout/custom-layout-impl.cpp b/examples/simple-layout/custom-layout-impl.cpp new file mode 100644 index 0000000..173dd35 --- /dev/null +++ b/examples/simple-layout/custom-layout-impl.cpp @@ -0,0 +1,105 @@ +/* + * 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. + */ + +// CLASS HEADER +#include "custom-layout-impl.h" + +// EXTERNAL INCLUDES +#include + +namespace Demo +{ + +namespace Internal +{ + +using Dali::Actor; +using Dali::Toolkit::MeasuredSize; + +CustomLayoutPtr CustomLayout::New() +{ + CustomLayoutPtr layout( new CustomLayout() ); + return layout; +} + +void CustomLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) +{ + auto accumulatedWidth = 0; + auto maxHeight = 0; + + // In this layout we will: + // Measuring the layout with the children in a horizontal configuration, one after another + // Set the required width to be the accumulated width of our children + // Set the required height to be the maximum height of any of our children + + for( unsigned int i=0; iGetMeasuredWidth(); + std::max( childLayout->GetMeasuredHeight().mValue, maxHeight ); + } + } + + // Finally, call this method to set the dimensions we would like + SetMeasuredDimensions( MeasuredSize( accumulatedWidth ), MeasuredSize( maxHeight ) ); +} + +void CustomLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) +{ + LayoutLength childTop( 0 ); + LayoutLength childLeft( 0 ); + + // We want to vertically align the children to the middle + auto height = bottom - top; + auto middle = height / 2; + + // Horizontally align the children to the middle of the space they are given too + auto width = right - left; + int count = GetChildCount(); + auto childIncrement = width / count; + auto center = childIncrement / 2; + + // Check layout direction + auto owner = GetOwner(); + auto actor = Actor::DownCast(owner); + const bool isLayoutRtl = actor ? actor.GetProperty< bool >( Actor::Property::LAYOUT_DIRECTION ) : false; + + for( int i = 0; i < count; i++) + { + auto itemIndex = isLayoutRtl ? count - 1 - i : i; // If RTL, then layout the last item first + + Dali::Toolkit::Internal::LayoutItemPtr childLayout = GetChildAt( itemIndex ); + if( childLayout != nullptr ) + { + auto childWidth = childLayout->GetMeasuredWidth(); + auto childHeight = childLayout->GetMeasuredHeight(); + + childTop = middle - (childHeight / 2); + + auto left = childLeft + center - childWidth / 2; + + childLayout->Layout( left, childTop, left + childWidth, childTop + childHeight ); + childLeft += childIncrement; + } + } +} + +} // namespace Internal + +} // namespace Demo diff --git a/examples/simple-layout/custom-layout-impl.h b/examples/simple-layout/custom-layout-impl.h new file mode 100644 index 0000000..6ff4e64 --- /dev/null +++ b/examples/simple-layout/custom-layout-impl.h @@ -0,0 +1,106 @@ +#ifndef DEMO_INTERNAL_CUSTOM_LAYOUT_H +#define DEMO_INTERNAL_CUSTOM_LAYOUT_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 + +// INTERNAL INCLUDES +#include "custom-layout.h" + +namespace Demo +{ + +namespace Internal +{ + +using Dali::Toolkit::MeasureSpec; +using Dali::Toolkit::LayoutLength; + +class CustomLayout; +using CustomLayoutPtr = Dali::IntrusivePtr< CustomLayout >; + +/** + * @brief The implementation of our custom layout. + * + * Here we will override the methods that we require to mimic a very simple horizontal layout. + */ +class CustomLayout final : public Dali::Toolkit::Internal::LayoutGroup +{ +public: + + /** + * @brief Create a new CustomLayout object. + * @return An intrusive pointer to the created CustomLayout object + */ + static CustomLayoutPtr New(); + + // Movable but not copyable + CustomLayout( const CustomLayout& other ) = delete; + CustomLayout& operator=( const CustomLayout& ) = delete; + CustomLayout( CustomLayout&& other ) = default; + CustomLayout& operator=( CustomLayout&& other ) = default; + +private: + + /** + * @brief Default Constructor + */ + CustomLayout() = default; + + /** + * Virtual Destructor + */ + virtual ~CustomLayout() = default; + + /** + * @copydoc LayoutItem::OnMeasure + * + * Overriding this method so that we can calculate the size we require using our children's sizes + */ + virtual void OnMeasure( MeasureSpec widthMeasureSpec, Dali::Toolkit::MeasureSpec heightMeasureSpec ) override; + + /** + * @copydoc LayoutItem::OnLayout + * + * Overriding this method so that we can layout our children as required. + */ + virtual void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) override; + +}; + +} // namespace Internal + +inline Internal::CustomLayout& GetImplementation( Demo::CustomLayout& handle ) +{ + DALI_ASSERT_ALWAYS( handle && "CustomLayout handle is empty" ); + Dali::BaseObject& object = handle.GetBaseObject(); + return static_cast( object ); +} + +inline const Internal::CustomLayout& GetImplementation( const Demo::CustomLayout& handle ) +{ + DALI_ASSERT_ALWAYS( handle && "CustomLayout handle is empty" ); + const Dali::BaseObject& object = handle.GetBaseObject(); + return static_cast( object ); +} + +} // namespace Demo + +#endif // DEMO_INTERNAL_CUSTOM_LAYOUT_H diff --git a/examples/simple-layout/custom-layout.cpp b/examples/simple-layout/custom-layout.cpp new file mode 100644 index 0000000..ef90709 --- /dev/null +++ b/examples/simple-layout/custom-layout.cpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +// CLASS HEADER +#include "custom-layout.h" + +// INTERNAL HEADERS +#include "custom-layout-impl.h" + +namespace Demo +{ + +CustomLayout CustomLayout::New() +{ + Internal::CustomLayoutPtr internal = Internal::CustomLayout::New(); + return CustomLayout( internal.Get() ); +} + +CustomLayout CustomLayout::DownCast( BaseHandle handle ) +{ + return CustomLayout( dynamic_cast< Demo::Internal::CustomLayout* >( handle.GetObjectPtr() ) ); +} + +CustomLayout::CustomLayout( Internal::CustomLayout* object ) +: Dali::Toolkit::LayoutGroup( object ) +{ +} + +} // namespace Demo diff --git a/examples/simple-layout/custom-layout.h b/examples/simple-layout/custom-layout.h new file mode 100644 index 0000000..a561501 --- /dev/null +++ b/examples/simple-layout/custom-layout.h @@ -0,0 +1,107 @@ +#ifndef DEMO_CUSTOM_LAYOUT_H +#define DEMO_CUSTOM_LAYOUT_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 + +namespace Demo +{ + +namespace Internal +{ +class CustomLayout; +} + +/** + * @brief This is the handle class to a very simple Custom Layout. + * + * This class lays out its children horizontally in a very simple manner. + */ +class CustomLayout : public Dali::Toolkit::LayoutGroup +{ +public: + + /** + * @brief Creates an uninitialized CustomLayout handle. + * + * Initialize it using CustomLayout::New(). + * Calling member functions with an uninitialized handle is not allowed. + */ + CustomLayout() = default; + + /** + * @brief Creates a CustomLayout object. + */ + static CustomLayout New(); + + + /** + * @brief Default destructor. + * + * This is non-virtual, since derived Handle types must not contain data or virtual methods + */ + ~CustomLayout() = default; + + /** + * @brief Copy constructor + */ + CustomLayout( const CustomLayout& ) = default; + + /** + * @brief Assigment operator + */ + CustomLayout& operator=( const CustomLayout& ) = default; + + /** + * @brief Move constructor + */ + CustomLayout( CustomLayout&& ) = default; + + /** + * @brief Movable assignment operator + */ + CustomLayout& operator=( CustomLayout&& ) = default; + + /** + * @brief Downcasts a handle to a CustomLayout handle. + * + * If handle points to a CustomLayout, the downcast produces a valid handle. + * If not, the returned handle is left uninitialized. + + * @param[in] handle to an object + * @return Handle to a CustomLayout or an uninitialized handle + */ + static CustomLayout DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /// @cond internal + /** + * @brief This constructor is used by CustomLayout::New() methods. + * + * @param[in] actor A pointer to a newly allocated Dali resource + */ + explicit CustomLayout( Internal::CustomLayout* body ); + /// @endcond +}; + +} // namespace Demo + +#endif // DEMO_CUSTOM_LAYOUT_H diff --git a/examples/simple-layout/simple-layout-example.cpp b/examples/simple-layout/simple-layout-example.cpp new file mode 100644 index 0000000..efa5351 --- /dev/null +++ b/examples/simple-layout/simple-layout-example.cpp @@ -0,0 +1,153 @@ +/* + * 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. + * + */ + +#include + +#include +#include +#include + +#include "custom-layout.h" + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ + +/// Child image filenames +const char* IMAGE_PATH[] = { + DEMO_IMAGE_DIR "application-icon-101.png", + DEMO_IMAGE_DIR "application-icon-102.png", + DEMO_IMAGE_DIR "application-icon-103.png", + DEMO_IMAGE_DIR "application-icon-104.png", +}; +const unsigned int NUMBER_OF_IMAGES = sizeof( IMAGE_PATH ) / sizeof( char* ); + +/** + * @brief Helper function to create ImageViews with given filename and size. + * @param[in] filename The filename of the image to use + * @param[in] size The size that the image should be loaded at + * @return The created ImageView + */ +ImageView CreateChildImageView( const char* filename, Size size ) +{ + ImageView imageView = ImageView::New(); + Property::Map imagePropertyMap; + imagePropertyMap[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::IMAGE; + imagePropertyMap[ Toolkit::ImageVisual::Property::URL ] = filename; + imagePropertyMap[ ImageVisual::Property::DESIRED_WIDTH ] = size.width; + imagePropertyMap[ ImageVisual::Property::DESIRED_HEIGHT ] = size.height; + imageView.SetProperty(Toolkit::ImageView::Property::IMAGE , imagePropertyMap ); + imageView.SetName("ImageView"); + imageView.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + imageView.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); + return imageView; +} + +} // unnamed namespace + +/** + * @brief Demonstrates how to create a very simple layout and apply that to any Control. + */ +class SimpleLayoutExample : public ConnectionTracker +{ +public: + + /** + * @brief Constructor. + * @param[in] application A reference to the Application class. + */ + SimpleLayoutExample( Application& application ) + : mApplication( application ) + { + // Connect to the Application's Init signal + mApplication.InitSignal().Connect( this, &SimpleLayoutExample::Create ); + } + +private: + + /** + * @brief Called to initialise the application content + * @param[in] application A reference to the Application class. + */ + void Create( Application& application ) + { + // Get a handle to the stage, change the background color and connect to the Touch & Key signals + Stage stage = Stage::GetCurrent(); + stage.SetBackgroundColor( Color::WHITE ); + stage.GetRootLayer().TouchSignal().Connect( this, &SimpleLayoutExample::OnTouch ); + stage.KeyEventSignal().Connect( this, &SimpleLayoutExample::OnKeyEvent ); + stage.KeepRendering(0.5f); // TODO: Should remove after bugfix, but currently required to ensure renders are done after resources are loaded + + + // Create a new control + Control control = Control::New(); + control.SetParentOrigin( ParentOrigin::CENTER ); + control.SetAnchorPoint( AnchorPoint::CENTER ); + stage.Add( control); + + // Set our Custom Layout on the control + auto layout = Demo::CustomLayout::New(); + DevelControl::SetLayout( control, layout ); + + // Add child image-views to the created control + for( auto i = 0u; i < NUMBER_OF_IMAGES; ++i ) + { + control.Add( CreateChildImageView( IMAGE_PATH[ i ], Size( 100.0f, 100.0f ) ) ); + } + } + + /** + * @brief Called when the stage is touched. + * + * We will use this to quit the application. + */ + bool OnTouch( Actor /* actor */, const TouchData& /* touch */ ) + { + mApplication.Quit(); + return true; + } + + /** + * @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(); + } + } + } + +private: + Application& mApplication; ///< A reference to the application object. +}; + +int DALI_EXPORT_API main( int argc, char **argv ) +{ + Application application = Application::New( &argc, &argv ); + SimpleLayoutExample test( application ); + application.MainLoop(); + return 0; +} diff --git a/packaging/com.samsung.dali-demo.spec b/packaging/com.samsung.dali-demo.spec index ac0d61c..1ea30bf 100755 --- a/packaging/com.samsung.dali-demo.spec +++ b/packaging/com.samsung.dali-demo.spec @@ -2,7 +2,7 @@ Name: com.samsung.dali-demo Summary: The OpenGLES Canvas Core Demo -Version: 1.3.27 +Version: 1.3.28 Release: 1 Group: System/Libraries License: Apache-2.0