visual-fitting-mode-example.cpp 9.12 KB
/*
 * Copyright (c) 2019 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 <dali/devel-api/object/handle-devel.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>

using namespace Dali;
using namespace Dali::Toolkit;

namespace
{
const char * const IMAGE_NAME = DEMO_IMAGE_DIR "gallery-medium-1.jpg"; ///< The image to use.
const Vector3 IMAGE_SIZE = Vector3( 300, 200, 0 ); ///< The size of the image-views.

const float BORDER_SIZE = 2.0f; ///< The size of the border.
const Property::Value BORDER ///< The border to use for each image-view.
{
  { Visual::Property::TYPE, Visual::BORDER },
  { BorderVisual::Property::COLOR, Color::RED },
  { BorderVisual::Property::SIZE, BORDER_SIZE }
};
const Extents LARGE_PADDING( 100.0f, 100.0f, 2.0f, 2.0f ); ///< The large padding extents.
const Extents BORDER_ONLY_PADDING( BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE ); ///< The border only padding extents.

const std::string INSTRUCTIONS_TEXT = "\n(Tap or Key Press To Change)"; ///< Instructions on how to change the padding mode.
const std::string LARGE_PADDING_TEXT( "Padding: Left/Right Large" + INSTRUCTIONS_TEXT ); ///< Label to shown when large padding enabled.
const std::string BORDER_ONLY_PADDING_TEXT( "Padding: Border Only" + INSTRUCTIONS_TEXT ); ///< Label to shown when border-only padding enabled.
const std::string FILL_LABEL( "FILL" );
const std::string FIT_KEEP_ASPECT_LABEL( "FIT\nKEEP ASPECT" );

const Property::Map TEXT_LABEL_PROPERTIES ///< All the properties of the Large Text Label shown in the example.
{
  { Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER },
  { Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER },
  { Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT },
  { Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT },
  { Control::Property::BACKGROUND,
    {
      { Toolkit::Visual::Property::TYPE, Visual::GRADIENT },
      { GradientVisual::Property::STOP_COLOR,  Property::Array{ Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f,
                                                                Vector4(   0.0f,  64.0f, 137.0f, 255.0f ) / 255.0f } },
      { GradientVisual::Property::START_POSITION, Vector2( 0.0f, -0.5f ) },
      { GradientVisual::Property::END_POSITION,   Vector2( 0.0f,  0.5f ) }
    }
  },
  { TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER },
  { TextLabel::Property::VERTICAL_ALIGNMENT, VerticalAlignment::CENTER },
  { TextLabel::Property::MULTI_LINE, true }
};

const Property::Map FILL_IMAGE_PROPERTIES ///< The basic properties of the Fill image view.
{
  { Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER },
  { Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER },
  { Actor::Property::SIZE, IMAGE_SIZE },
  { Control::Property::BACKGROUND, BORDER }
};

const Property::Map FIT_KEEP_ASPECT_RATIO_IMAGE_BASIC_PROPERTIES ///< The basic properties of the Fit Keep Aspect image view.
{
  { Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER },
  { Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER },
  { Actor::Property::SIZE, IMAGE_SIZE },
  { Control::Property::BACKGROUND, BORDER }
};

const Property::Map OVERLAY_LABEL_PROPERTIES ///< The image view overlay label properties
{
  { TextLabel::Property::TEXT_COLOR, Color::WHITE },
  { TextLabel::Property::OUTLINE, { { "color", Color::BLACK }, { "width", 1.0f } } },
  { TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER },
  { TextLabel::Property::VERTICAL_ALIGNMENT, VerticalAlignment::CENTER },
  { TextLabel::Property::MULTI_LINE, true },
};
} // unnamed namespace

/**
 * @brief This example shows how to use the Dali::Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE property.
 */
class VisualFittingModeController : public ConnectionTracker
{
public:

  /**
   * @brief Constructor.
   * @param[in]  application A reference to the Application class.
   */
  VisualFittingModeController( Application& application )
  : mApplication( application ),
    mLargePadding( true )
  {
    // Connect to the Application's Init signal
    mApplication.InitSignal().Connect( this, &VisualFittingModeController::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
    Stage stage = Stage::GetCurrent();
    stage.SetBackgroundColor( Color::WHITE );

    // Text Label filling the entire screen, with a background
    mTextLabel = DevelHandle::New< TextLabel >( TEXT_LABEL_PROPERTIES );
    stage.Add( mTextLabel );

    // We want to change the padding when tapping
    mTapDetector = TapGestureDetector::New();
    mTapDetector.Attach( mTextLabel );
    mTapDetector.DetectedSignal().Connect( this, &VisualFittingModeController::OnTap );

    // Create an ImageView with the default behaviour, i.e. image fills to control size
    mFillImage = ImageView::New( IMAGE_NAME );
    DevelHandle::SetProperties( mFillImage, FILL_IMAGE_PROPERTIES );
    stage.Add( mFillImage );

    // Create an ImageView that Keeps the aspect ratio while fitting within the given size
    mFitKeepAspectRatioImage = DevelHandle::New< ImageView >( FIT_KEEP_ASPECT_RATIO_IMAGE_BASIC_PROPERTIES );
    mFitKeepAspectRatioImage.SetProperty( ImageView::Property::IMAGE,
                                          Property::Map
                                          {
                                            { Visual::Property::TYPE, Visual::IMAGE },
                                            { ImageVisual::Property::URL, IMAGE_NAME },
                                            { DevelVisual::Property::VISUAL_FITTING_MODE, DevelVisual::FIT_KEEP_ASPECT_RATIO }
                                          } );
    stage.Add( mFitKeepAspectRatioImage );

    // Create an overlay label for fill image
    Actor fillLabel = TextLabel::New( FILL_LABEL );
    DevelHandle::SetProperties( fillLabel, FILL_IMAGE_PROPERTIES );
    DevelHandle::SetProperties( fillLabel, OVERLAY_LABEL_PROPERTIES );
    stage.Add( fillLabel );

    // Create an overlay label for the Fit/Keep Aspect image
    Actor fitLabel = TextLabel::New( FIT_KEEP_ASPECT_LABEL );
    DevelHandle::SetProperties( fitLabel, FIT_KEEP_ASPECT_RATIO_IMAGE_BASIC_PROPERTIES );
    DevelHandle::SetProperties( fitLabel, OVERLAY_LABEL_PROPERTIES );
    stage.Add( fitLabel );

    // Respond to key events, exit if ESC/Back, change the padding if anything else
    stage.KeyEventSignal().Connect( this, &VisualFittingModeController::OnKeyEvent );

    // Set the initial padding
    ChangePadding();
  }

  /**
   * @brief Changes the padding of both image-views to show how the VisualFittingMode is applied.
   */
  void ChangePadding()
  {
    mLargePadding = !mLargePadding;

    const Extents padding( mLargePadding ? LARGE_PADDING : BORDER_ONLY_PADDING );
    mFitKeepAspectRatioImage.SetProperty( Control::Property::PADDING, padding );
    mFillImage.SetProperty( Control::Property::PADDING, padding );

    mTextLabel.SetProperty( TextLabel::Property::TEXT, mLargePadding ? LARGE_PADDING_TEXT : BORDER_ONLY_PADDING_TEXT );
  }

  /**
   * @brief Called when the main text-label is tapped.
   *
   * We just want to change the padding when this happens.
   */
  void OnTap( Actor /* actor */, const TapGesture& /* tap */ )
  {
    ChangePadding();
  }

  /**
   * @brief Called when any key event is received
   *
   * Will use this to quit the application if we receive the Back or the Escape key & change
   * the padding if any other key.
   * @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();
      }
      else
      {
        ChangePadding();
      }
    }
  }

private:
  Application&  mApplication; ///< Reference to the application class.
  Actor mFillImage; ///< An image-view that fills to the control size.
  Actor mFitKeepAspectRatioImage; ///< An image-view that fits within the given size & keeps the aspect ratio.
  Actor mTextLabel; ///< A text label to show the current padding mode.
  TapGestureDetector mTapDetector; ///< A tap detector to change the padding mode.
  bool mLargePadding; ///< If true, the large padding values are used. When false, only the border padding is applied.
};

int DALI_EXPORT_API main( int argc, char **argv )
{
  Application application = Application::New( &argc, &argv );
  VisualFittingModeController visualFittingModeController( application );
  application.MainLoop();
  return 0;
}