Testing on target
=================
-To build for target, first build and install dali-core, dali-adaptor and dali-toolkit, then build dali-capi without --keep-packs option.
+To build for target, first build and install dali-core, dali-adaptor and dali-toolkit.
You will need to install libconfig-tiny-perl:
sub info(@);
our $repo = Git->repository();
-our $debug=1;
+our $debug=0;
our $pd_debug=0;
our $root;
our %info_data; # Hash containing all data from .info files
# execute coverage.sh, generating build/tizen/dali.info from lib, and
# *.dir/dali.info. Don't generate html
-`coverage.sh -n`;
+print `./coverage.sh -n`;
chdir "..";
$root = getcwd();
my @cmd=('--no-pager','diff','--no-ext-diff','-U0','--no-color');
my $status = $repo->command("status", "-s");
-if(scalar(@ARGV)) # REMOVE ME
-{
- # REMOVE ME - temp to get past modifying this script in place.
- push @cmd, @ARGV;
-}
-elsif( $status eq "" && !scalar(@ARGV))
+if( $status eq "" && !scalar(@ARGV))
{
# There are no changes in the index or working tree, and
# no diff arguments to append. Use the last patch instead.
//text is "c"
DALI_TEST_EQUALS( "c", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
+ // select all text
+ DevelTextEditor::SelectWholeText(editor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Copy the selected text using logical keys
+ application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+ application.ProcessEvent( GenerateKey( "ؤ", "c", "ؤ", KEY_C_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "c", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // select none
+ DevelTextEditor::SelectNone(editor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Paste the selected using logical keys
+ application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+ application.ProcessEvent( GenerateKey( "ر", "v", "ر", KEY_V_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "v", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ //text is "cc"
+ DALI_TEST_EQUALS( "cc", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
+
+ // select all using logical keys
+ application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+ application.ProcessEvent( GenerateKey( "ش", "a", "ش", KEY_A_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // cut text using logical keys
+ application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+ application.ProcessEvent( GenerateKey( "ء", "x", "ء", KEY_X_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "x", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ //text is ""
+ DALI_TEST_EQUALS( "", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
+
END_TEST;
}
END_TEST;
}
+
+int UtcDaliTextEditorScrolling(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextEditorScrolling ");
+
+ TextEditor textEditor = TextEditor::New();
+ DALI_TEST_CHECK( textEditor );
+
+ application.GetScene().Add( textEditor );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ application.SendNotification();
+ application.Render();
+
+ textEditor.SetProperty(TextEditor::Property::TEXT, "Tex1\nTex2\nTex3\nTex4\nTex5\nTex6\nTex7\nTex8");
+ textEditor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
+ textEditor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
+ textEditor.SetProperty(Actor::Property::SIZE, Vector2(60.0f, 160.0f));
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+
+
+ DevelTextEditor::ScrollBy(textEditor, Vector2(1.0f, 1.0f));
+
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get<float>(), 1.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+
+ DevelTextEditor::ScrollBy(textEditor, Vector2(0.0f, 1000.0f));
+
+ DALI_TEST_NOT_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get<float>(), 1.0f, 0.1f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+
+ textEditor.SetProperty(DevelTextEditor::Property::VERTICAL_SCROLL_POSITION , 0.0f);
+ textEditor.SetProperty(DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION , 0.0f);
+
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get<float>(), 0.0f, TEST_LOCATION );
+
+ END_TEST;
+}
GetImpl(textEditor).SelectNone();
}
+void ScrollBy(TextEditor textEditor, Vector2 scroll)
+{
+ GetImpl(textEditor).ScrollBy(scroll);
+}
+
} // namespace DevelTextEditor
} // namespace Toolkit
SELECTED_TEXT_END,
/**
+ * @brief The horizontal scroll position in pixels.
+ * @details Name "horizontalScrollPosition", type Property::FLOAT.
+ */
+ HORIZONTAL_SCROLL_POSITION,
+
+ /**
+ * @brief The vertical scroll position in pixels.
+ * @details Name "verticalScrollPosition", type Property::FLOAT.
+ */
+ VERTICAL_SCROLL_POSITION,
+
+ /**
* @brief The Editable state of control.
* @details Name "enableEditing", type Property::BOOLEAN.
*/
*/
DALI_TOOLKIT_API void SelectNone(TextEditor textEditor);
+/**
+ * @brief Scroll the TextEditor by specific amount.
+ *
+ * @param[in] textEditor The instance of TextEditor.
+ * @param[in] scroll amount (in pixels) of scrolling in horizontal & vectical directions.
+ */
+DALI_TOOLKIT_API void ScrollBy(TextEditor textEditor, Vector2 scroll);
+
} // namespace DevelTextEditor
} // namespace Toolkit
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "maxLength", INTEGER, MAX_LENGTH )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextStart", INTEGER, SELECTED_TEXT_START )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextEnd", INTEGER, SELECTED_TEXT_END )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "horizontalScrollPosition", FLOAT, HORIZONTAL_SCROLL_POSITION )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "verticalScrollPosition", INTEGER, VERTICAL_SCROLL_POSITION )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableEditing", BOOLEAN, ENABLE_EDITING )
DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextEditor, "selectedText", STRING, SELECTED_TEXT )
impl.SetEditable( editable );
break;
}
+ case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION:
+ {
+ float horizontalScroll = value.Get< float >();
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_SCROLL_POSITION %d\n", impl.mController.Get(), horizontalScroll );
+ if (horizontalScroll >= 0.0f)
+ {
+ impl.ScrollBy( Vector2(horizontalScroll - impl.GetHorizontalScrollPosition(), 0 ));
+ }
+ break;
+ }
+ case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION:
+ {
+ float verticalScroll = value.Get< float >();
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p VERTICAL_SCROLL_POSITION %d\n", impl.mController.Get(), verticalScroll );
+ if (verticalScroll >= 0.0f)
+ {
+ impl.ScrollBy( Vector2(0, verticalScroll - impl.GetVerticalScrollPosition() ));
+ }
+ break;
+ }
} // switch
} // texteditor
}
value = impl.IsEditable();
break;
}
+ case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION:
+ {
+ value = impl.GetHorizontalScrollPosition();
+ break;
+ }
+ case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION:
+ {
+ value = impl.GetVerticalScrollPosition();
+ break;
+ }
} //switch
}
}
}
+void TextEditor::ScrollBy(Vector2 scroll)
+{
+ if( mController && mController->IsShowingRealText() )
+ {
+ mController->ScrollBy(scroll);
+ }
+}
+
+float TextEditor::GetHorizontalScrollPosition()
+{
+ if( mController && mController->IsShowingRealText() )
+ {
+ return mController->GetHorizontalScrollPosition();
+ }
+ return 0;
+}
+
+float TextEditor::GetVerticalScrollPosition()
+{
+ if( mController && mController->IsShowingRealText() )
+ {
+ return mController->GetVerticalScrollPosition();
+ }
+ return 0;
+}
+
string TextEditor::GetSelectedText() const
{
string selectedText = "";
void SelectNone() override;
/**
+ * @copydoc Dali::Toolkit::DevelTextEditor::ScrollBy()
+ */
+ void ScrollBy(Vector2 Scroll);
+
+ /**
+ * @brief Get Horizontal scroll position of TextEditor.
+ *
+ * @return Horizontal scroll position (in pixels) of TextEditor.
+ */
+ float GetHorizontalScrollPosition();
+
+ /**
+ * @brief Get Vertical scroll position of TextEditor.
+ *
+ * @return Vertical scroll position (in pixels) of TextEditor.
+ */
+ float GetVerticalScrollPosition();
+
+ /**
* @copydoc Text::SelectableControlInterface::GetSelectedText()
*/
string GetSelectedText() const override;
int keyCode = keyEvent.GetKeyCode();
const std::string& keyString = keyEvent.GetKeyString();
const std::string keyName = keyEvent.GetKeyName();
+ // Key will produce same logical-key value when ctrl
+ // is down, regardless of language layout
+ const std::string logicalKey = keyEvent.GetLogicalKey();
const bool isNullKey = ( 0 == keyCode ) && ( keyString.empty() );
else if ( keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier())
{
bool consumed = false;
- if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME)
+ if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
{
// Ctrl-C or Ctrl+Insert to copy the selected text
controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::COPY );
consumed = true;
}
- else if (keyName == KEY_V_NAME)
+ else if (keyName == KEY_V_NAME || logicalKey == KEY_V_NAME)
{
// Ctrl-V to paste the copied text
controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::PASTE );
consumed = true;
}
- else if (keyName == KEY_X_NAME)
+ else if (keyName == KEY_X_NAME || logicalKey == KEY_X_NAME)
{
// Ctrl-X to cut the selected text
controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT );
consumed = true;
}
- else if (keyName == KEY_A_NAME)
+ else if (keyName == KEY_A_NAME || logicalKey == KEY_A_NAME)
{
// Ctrl-A to select All the text
controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::SELECT_ALL );
}
}
+void Controller::ScrollBy( Vector2 scroll )
+{
+ if( mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
+ {
+ const Vector2& layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
+ const Vector2 currentScroll = mImpl->mModel->mScrollPosition;
+
+ scroll.x = -scroll.x;
+ scroll.y = -scroll.y;
+
+ if( fabs(scroll.x) > Math::MACHINE_EPSILON_0 )
+ {
+ mImpl->mModel->mScrollPosition.x += scroll.x;
+ mImpl->ClampHorizontalScroll( layoutSize );
+ }
+
+ if( fabs(scroll.y) > Math::MACHINE_EPSILON_0 )
+ {
+ mImpl->mModel->mScrollPosition.y += scroll.y;
+ mImpl->ClampVerticalScroll( layoutSize );
+ }
+
+ if (mImpl->mModel->mScrollPosition != currentScroll)
+ {
+ mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mModel->mScrollPosition - currentScroll );
+ mImpl->RequestRelayout();
+ }
+ }
+}
+
+float Controller::GetHorizontalScrollPosition()
+{
+ if( mImpl->mEventData )
+ {
+ //scroll values are negative internally so we convert them to positive numbers
+ return -mImpl->mModel->mScrollPosition.x;
+ }
+ return 0;
+}
+
+float Controller::GetVerticalScrollPosition()
+{
+ if( mImpl->mEventData )
+ {
+ //scroll values are negative internally so we convert them to positive numbers
+ return -mImpl->mModel->mScrollPosition.y;
+ }
+ return 0;
+}
+
void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y )
{
EventHandler::DecorationEvent(*this, handleType, state, x, y);
virtual void SetEditable( bool editable );
/**
+ * @copydoc Dali::Toolkit::Internal::TextEditor::ScrollBy()
+ */
+ virtual void ScrollBy( Vector2 scroll );
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::TextEditor::GetHorizontalScrollPosition()
+ */
+ float GetHorizontalScrollPosition();
+
+ /**
+ * @copydoc Dali::Toolkit::Internal::TextEditor::GetVerticalScrollPosition()
+ */
+ float GetVerticalScrollPosition();
+
+ /**
* @brief Event received from input method context
*
* @param[in] inputMethodContext The input method context.
mPlacementActor(),
mPlayState( DevelImageVisual::PlayState::STOPPED ),
mEventCallback( nullptr ),
- mRendererAdded( false )
+ mRendererAdded( false ),
+ mCoreShutdown(false)
{
// the rasterized image is with pre-multiplied alpha format
mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
+
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.AddObserver(*this);
}
AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
{
- if( mEventCallback )
+ if( ! mCoreShutdown )
{
- mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.RemoveObserver(*this);
+
+ if( mEventCallback )
+ {
+ mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+ }
+
+ // Finalize animation task and disconnect the signal in the main thread
+ mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
+ mVectorAnimationTask->Finalize();
}
+}
- // Finalize animation task and disconnect the signal in the main thread
- mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
- mVectorAnimationTask->Finalize();
+void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed()
+{
+ // Core is shutting down. Don't talk to the plugin any more.
+ mCoreShutdown = true;
}
void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
void AnimatedVectorImageVisual::TriggerVectorRasterization()
{
- if( !mEventCallback )
+ if( !mEventCallback && !mCoreShutdown )
{
mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents );
- mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback );
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.RegisterEventCallback( mEventCallback );
Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing
}
}
#include <dali-toolkit/internal/visuals/visual-url.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
namespace Dali
{
* | url | STRING |
*
*/
-class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker
+class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver
{
public:
*/
void DoCreateInstancePropertyMap( Property::Map& map ) const override;
+protected: // From VectorAnimationManager::LifecycleObserver:
+ /**
+ * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed()
+ */
+ void VectorAnimationManagerDestroyed() override;
+
protected:
/**
DevelImageVisual::PlayState::Type mPlayState;
CallbackBase* mEventCallback; // Not owned
bool mRendererAdded;
+ bool mCoreShutdown;
};
} // namespace Internal
VectorAnimationManager::VectorAnimationManager()
: mEventCallbacks(),
+ mLifecycleObservers(),
mVectorAnimationThread( nullptr ),
mProcessorRegistered( false )
{
{
Adaptor::Get().UnregisterProcessor( *this );
}
+
+ for( auto observer : mLifecycleObservers )
+ {
+ observer->VectorAnimationManagerDestroyed();
+ }
+}
+
+void VectorAnimationManager::AddObserver( VectorAnimationManager::LifecycleObserver& observer )
+{
+ DALI_ASSERT_DEBUG( mLifecycleObservers.end() == std::find( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer));
+ mLifecycleObservers.push_back( &observer );
+}
+
+void VectorAnimationManager::RemoveObserver( VectorAnimationManager::LifecycleObserver& observer)
+{
+ auto iterator=std::find(mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer);
+ if( iterator != mLifecycleObservers.end() )
+ {
+ mLifecycleObservers.erase(iterator);
+ }
}
VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread()
class VectorAnimationManager: public Integration::Processor
{
public:
+ struct LifecycleObserver
+ {
+ virtual void VectorAnimationManagerDestroyed() = 0;
+ };
/**
* @brief Constructor.
~VectorAnimationManager() override;
/**
+ * Add a lifecycle observer
+ * @param[in] observer The object watching this one
+ */
+ void AddObserver( LifecycleObserver& observer );
+
+ /**
+ * Remove a lifecycle observer
+ * @param[in] observer The object watching this one
+ */
+ void RemoveObserver( LifecycleObserver& observer );
+
+ /**
* Get the vector animation thread.
* @return A raw pointer pointing to the vector animation thread.
*/
private:
std::vector< CallbackBase* > mEventCallbacks;
+ std::vector<LifecycleObserver*> mLifecycleObservers;
std::unique_ptr< VectorAnimationThread > mVectorAnimationThread;
bool mProcessorRegistered;
};