Merge "Match the arguments type in 'max' function" into devel/master
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Fri, 13 Jan 2017 11:53:48 +0000 (03:53 -0800)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Fri, 13 Jan 2017 11:53:48 +0000 (03:53 -0800)
22 files changed:
automated-tests/src/dali-toolkit/utc-Dali-Button.cpp
dali-toolkit/internal/controls/buttons/button-impl.cpp
dali-toolkit/internal/controls/buttons/button-impl.h
dali-toolkit/public-api/controls/buttons/button.h
plugins/dali-swig/.gitignore
plugins/dali-swig/Makefile.am
plugins/dali-swig/SWIG/dali-core.i
plugins/dali-swig/SWIG/dali.i
plugins/dali-swig/SWIG/events/application-event.i
plugins/dali-swig/SWIG/events/builder-event.i
plugins/dali-swig/SWIG/property-value.i [new file with mode: 0644]
plugins/dali-swig/examples/date-picker-using-json.cs [new file with mode: 0644]
plugins/dali-swig/examples/date-picker.cs [new file with mode: 0644]
plugins/dali-swig/examples/json-loader.cs [new file with mode: 0644]
plugins/dali-swig/examples/json/date-picker-template.json [new file with mode: 0644]
plugins/dali-swig/examples/json/date-picker.json [new file with mode: 0644]
plugins/dali-swig/examples/json/spin.json [new file with mode: 0644]
plugins/dali-swig/examples/spin-control.cs [deleted file]
plugins/dali-swig/manual/csharp/PropertyRangeManager.cs [new file with mode: 0644]
plugins/dali-swig/manual/csharp/ViewRegistry.cs [new file with mode: 0644]
plugins/dali-swig/manual/csharp/ViewRegistryHelper.cs [new file with mode: 0644]
plugins/dali-swig/views/spin.cs [new file with mode: 0644]

index a2bf49d..9452649 100644 (file)
@@ -59,6 +59,23 @@ static bool ButtonCallback( Button button )
   return false;
 }
 
+static std::string GetButtonText( Button button )
+{
+  Property::Value value = button.GetProperty( Toolkit::Button::Property::LABEL );
+
+  Property::Map *labelProperty = value.GetMap();
+
+  std::string textLabel;
+
+  if ( labelProperty )
+  {
+    Property::Value* value = labelProperty->Find( Toolkit::TextVisual::Property::TEXT );
+    value->Get( textLabel );
+  }
+
+  return textLabel;
+}
+
 struct CallbackFunctor
 {
   CallbackFunctor(bool* callbackFlag)
@@ -472,7 +489,7 @@ int UtcDaliButtonSetAnimationTimeP(void)
   END_TEST;
 }
 
-int UtcDaliButtonSetLabelStringP(void)
+int UtcDaliButtonSetLabelStringWithPropertyMapP(void)
 {
   ToolkitTestApplication application;
 
@@ -480,11 +497,28 @@ int UtcDaliButtonSetLabelStringP(void)
   button.SetProperty( Toolkit::Button::Property::LABEL,
                       Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
                                      .Add( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f )
+                                     .Add( Toolkit::TextVisual::Property::TEXT, "Button Label")
                      );
 
-  button.SetLabelText( "Button Label" );
+  DALI_TEST_EQUALS( GetButtonText( button ), "Button Label", TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliButtonSetLabelWithStringP(void)
+{
+  ToolkitTestApplication application;
+
+  Button button = PushButton::New();
+
+  // Set default point size for text visual as style sheet not available.
+  button.SetProperty( Toolkit::Button::Property::LABEL,
+                      Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
+                                     .Add( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f )
+                                     );
+
+  button.SetProperty( Toolkit::Button::Property::LABEL, "Button Label" );
 
-  DALI_TEST_EQUALS( button.GetLabelText(), "Button Label", TEST_LOCATION );
+  DALI_TEST_EQUALS( GetButtonText( button ), "Button Label", TEST_LOCATION );
   END_TEST;
 }
 
@@ -492,6 +526,9 @@ int UtcDaliButtonSetLabelPropertyP(void)
 {
   ToolkitTestApplication application;
 
+  tet_infoline(" UtcDaliButtonSetLabelPropertyP Set text label and then set again with new text");
+
+
   const std::string TEST_LABEL1 = "test label one";
   const std::string TEST_LABEL2 = "test label two";
 
@@ -500,13 +537,10 @@ int UtcDaliButtonSetLabelPropertyP(void)
   button.SetProperty( Toolkit::Button::Property::LABEL,
                         Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
                                        .Add( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f )
+                                       .Add( Toolkit::TextVisual::Property::TEXT, TEST_LABEL1 )
                      );
 
-  button.SetProperty( Button::Property::LABEL_TEXT, TEST_LABEL1 );
-
-  std::string labelText = button.GetProperty<std::string>( Button::Property::LABEL_TEXT );
-
-  DALI_TEST_EQUALS( labelText, TEST_LABEL1,  TEST_LOCATION );
+  DALI_TEST_EQUALS( GetButtonText( button ), TEST_LABEL1,  TEST_LOCATION );
 
   Property::Map propertyMap;
   propertyMap.Insert( Toolkit::Visual::Property::TYPE,  Toolkit::DevelVisual::TEXT );
@@ -515,9 +549,7 @@ int UtcDaliButtonSetLabelPropertyP(void)
   propertyMap.Insert( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f );
   button.SetProperty( Button::Property::LABEL, propertyMap );
 
-  labelText = button.GetProperty<std::string>( Button::Property::LABEL_TEXT );
-
-  DALI_TEST_EQUALS( labelText, TEST_LABEL2,  TEST_LOCATION );
+  DALI_TEST_EQUALS( GetButtonText( button ), TEST_LABEL2,  TEST_LOCATION );
 
   END_TEST;
 }
@@ -1238,3 +1270,38 @@ int UtcDaliButtonSetGetDepreciatedPropertiesWithURL(void)
 
 END_TEST;
 }
+
+int UtcDaliButtonSetLabelTextDeprecatedPropertyP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliButtonSetLabelTextDeprecatedPropertyP");
+
+  const std::string TEST_LABEL1 = "test label one";
+  const std::string TEST_LABEL2 = "test label two";
+
+  Button button = PushButton::New();
+
+  button.SetProperty( Toolkit::Button::Property::LABEL,
+                        Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
+                                       .Add( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f )
+                     );
+
+  button.SetProperty( Button::Property::LABEL_TEXT, TEST_LABEL1 );
+
+  std::string labelText = button.GetProperty<std::string>( Button::Property::LABEL_TEXT );
+
+  DALI_TEST_EQUALS( labelText, TEST_LABEL1,  TEST_LOCATION );
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Toolkit::Visual::Property::TYPE,  Toolkit::DevelVisual::TEXT );
+  propertyMap.Insert( Toolkit::TextVisual::Property::TEXT,  TEST_LABEL2 );
+  propertyMap.Insert( Toolkit::TextVisual::Property::TEXT_COLOR, Color::BLUE );
+  propertyMap.Insert( Toolkit::TextVisual::Property::POINT_SIZE, 15.0f );
+  button.SetProperty( Button::Property::LABEL, propertyMap );
+
+  labelText = button.GetProperty<std::string>( Button::Property::LABEL_TEXT );
+
+  DALI_TEST_EQUALS( labelText, TEST_LABEL2,  TEST_LOCATION );
+
+  END_TEST;
+}
index 0c7005b..ed9b2c8 100644 (file)
@@ -348,11 +348,7 @@ bool Button::IsSelected() const
 
 void Button::SetLabelText( const std::string& label )
 {
-  Property::Map labelProperty;
-  labelProperty.Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT)
-               .Add( Toolkit::TextVisual::Property::TEXT, label );
-
-  Self().SetProperty( Toolkit::Button::Property::LABEL, labelProperty );
+  Self().SetProperty( Toolkit::Button::Property::LABEL, label );
 }
 
 std::string Button::GetLabelText() const
@@ -372,7 +368,7 @@ std::string Button::GetLabelText() const
   return textLabel;
 }
 
-void Button::MergeLabelProperties( const Property::Map& inMap, Property::Map& outMap )
+void Button::MergeWithExistingLabelProperties( const Property::Map& inMap, Property::Map& outMap )
 {
   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties with %d properties\n", inMap.Count() );
 
@@ -1224,13 +1220,32 @@ void Button::SetProperty( BaseObject* object, Property::Index index, const Prope
 
       case Toolkit::Button::Property::LABEL:
       {
-        // Get a Property::Map from the property if possible.
-        Property::Map* setPropertyMap = value.GetMap();
-        if( setPropertyMap )
+        Property::Map outTextVisualProperties;
+        std::string textString;
+
+        if ( value.Get( textString ) )
+        {
+          DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty Setting TextVisual with string[%s]\n", textString.c_str() );
+
+          Property::Map setPropertyMap;
+          setPropertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT)
+                        .Add( Toolkit::TextVisual::Property::TEXT, textString );
+
+          GetImplementation( button ).MergeWithExistingLabelProperties( setPropertyMap, outTextVisualProperties );
+        }
+        else
+        {
+          // Get a Property::Map from the property if possible.
+          Property::Map* setPropertyMap = value.GetMap();
+          if( setPropertyMap )
+          {
+            GetImplementation( button ).MergeWithExistingLabelProperties( *setPropertyMap, outTextVisualProperties );
+          }
+        }
+
+        if( !outTextVisualProperties.Empty() )
         {
-          Property::Map textVisualProperties;
-          GetImplementation( button ).MergeLabelProperties( *setPropertyMap, textVisualProperties );
-          GetImplementation( button ).CreateVisualsForComponent( index, textVisualProperties, DepthIndex::CONTENT );
+          GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT );
           GetImplementation( button ).RelayoutRequest();
         }
         break;
index a079cd5..e0b7d50 100644 (file)
@@ -149,13 +149,13 @@ public:
   std::string GetLabelText() const;
 
   /**
-   * @brief Produces a Property::Map of Text properties to create a Text Visual
+   * @brief Produces a Property::Map of Text properties to create a Text Visual, merging existing properties with supplied map
    * If the label does not exist yet, it is created.
    * The derived buttons are notified if any properties are changed.
    * @param[in] properties A Property::Map of key-value pairs of properties to set.
-   * @param[out] properties A Property::Map of text visual  properties to set.
+   * @param[out] properties A Property::Map of text visual properties to set after merging inMap with existing maps
    */
-  void MergeLabelProperties( const Property::Map& inMap, Property::Map& outMap );
+  void MergeWithExistingLabelProperties( const Property::Map& inMap, Property::Map& outMap );
 
   /**
    * Performs actions as requested using the action name.
index 3ccf2d4..e447554 100644 (file)
@@ -192,7 +192,7 @@ public:
       SELECTED_COLOR,
 
       /**
-       * @brief name "label", type Property::Map
+       * @brief name "label", type Property::Map or std::string
        * @SINCE_1_0.0
        */
       LABEL,
index 43660d7..2263391 100644 (file)
@@ -4,6 +4,5 @@ autom4te.cache/
 aclocal.m4
 config/
 config.*
-cpp/dali_wrap.cpp
-cpp/dali_wrap.h
+automatic/*
 configure
index 991c0ee..e1520bf 100755 (executable)
@@ -39,14 +39,16 @@ manual/cpp/callbackbase_wrap.o: $(BUILT_SOURCES)
        g++ -c -fpic $(CXXFLAGS) $(DALICORE_CFLAGS) $(DALIADAPTOR_CFLAGS) $(DALITOOLKIT_CFLAGS) manual/cpp/callbackbase_wrap.cpp -o manual/cpp/callbackbase_wrap.o
 
 NDali.dll: $(BUILT_SOURCES)
-       $(MCS) -nologo -target:library -out:NDali.dll automatic/csharp/*.cs manual/csharp/*.cs
+       $(MCS) -nologo -target:library -out:NDali.dll automatic/csharp/*.cs manual/csharp/*.cs views/*.cs
 
 check-local: examples/dali-test.exe \
              examples/hello-world.exe \
              examples/scroll-view.exe \
              examples/custom-control.exe \
-             examples/spin-control.exe \
+             examples/date-picker.exe \
              examples/control-dashboard.exe \
+             examples/date-picker-using-json.exe \
+             examples/json-loader.exe \
              examples/user-alphafunction.exe \
              examples/image-view.exe \
              examples/libNDalic.so examples/NDali.dll
index 5535ee9..73ce8cc 100755 (executable)
@@ -84,6 +84,7 @@
 %ignore *::AnchorPoint::DEFAULT;
 %ignore *::SetPositionInheritanceMode(PositionInheritanceMode);
 %ignore *::GetKeyValue(SizeType) const;
+%ignore *::TypeInfo::GetCreator() const;
 
 %rename(ParentOriginTop) Dali::ParentOrigin::TOP;
 %rename(ParentOriginBottom) Dali::ParentOrigin::BOTTOM;
@@ -209,6 +210,8 @@ typedef std::pair< Dali::Radian, Dali::Radian > AngleThresholdPair;
 %include <dali/public-api/object/handle.h>
 %include <dali/public-api/object/type-info.h>
 %include <dali/public-api/object/type-registry.h>
+%include <dali/devel-api/object/csharp-type-info.h>
+%include <dali/devel-api/object/csharp-type-registry.h>
 
 %include <dali/public-api/common/constants.h>
 %include <dali/public-api/actors/actor-enumerations.h>
index 1f5149b..e4da86b 100755 (executable)
@@ -53,6 +53,8 @@
 #include <dali/public-api/math/matrix3.h>
 #include <dali/public-api/math/viewport.h>
 #include <dali/public-api/object/property-key.h>
+#include <dali/devel-api/object/csharp-type-info.h>
+#include <dali/devel-api/object/csharp-type-registry.h>
 
 #include <dali/public-api/adaptor-framework/timer.h>
 #include <dali/public-api/adaptor-framework/window.h>
   return $null;
 %}
 
+
+
+
+// Type registry type maps
+%typemap(cstype) Dali::TypeInfo::CreateFunction "System.Delegate"
+%typemap(csin, pre ="System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate($csinput); ")
+  Dali::TypeInfo::CreateFunction "new System.Runtime.InteropServices.HandleRef(null, ip)" // null was this
+
+%typemap(cstype) Dali::CSharpTypeInfo::CreateFunction "System.Delegate"
+%typemap(csin, pre ="System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate($csinput); ")
+   Dali::CSharpTypeInfo::CreateFunction "new System.Runtime.InteropServices.HandleRef(null, ip)" // null was this
+
+
+
+%typemap(cstype) Dali::CSharpTypeInfo::SetPropertyFunction "System.Delegate"
+%typemap(csin, pre ="System.IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate($csinput); ")
+   Dali::CSharpTypeInfo::SetPropertyFunction "new System.Runtime.InteropServices.HandleRef(null, ip)" // null was this
+
+
+
+%typemap(cstype) Dali::CSharpTypeInfo::GetPropertyFunction "System.Delegate"
+%typemap(csin, pre ="System.IntPtr ip2 = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate($csinput); ")
+   Dali::CSharpTypeInfo::GetPropertyFunction "new System.Runtime.InteropServices.HandleRef(null, ip2)" // null was this
+
+
+
+
+
+
+
 #endif
 
+
+
+/**
+ * Extend the type registry to allow for registering of C# controls and custom properties
+ */
+%extend Dali::TypeRegistration {
+
+
+   static void RegisterControl( const std::string& controlName, Dali::CSharpTypeInfo::CreateFunction createFunc )
+   {
+     Dali::CSharpTypeRegistry::RegisterType( controlName, typeid( Dali::Toolkit::Control), createFunc );
+   };
+
+
+   static void RegisterProperty( const std::string& controlName,
+                    const std::string& propertyName,
+                    int index,
+                    Property::Type type,
+                    Dali::CSharpTypeInfo::SetPropertyFunction setFunc,
+                    Dali::CSharpTypeInfo::GetPropertyFunction getFunc )
+   {
+     Dali::CSharpTypeRegistry::RegisterProperty( controlName, propertyName, index, type, setFunc, getFunc );
+   };
+
+};
+
+
+
+
 %ignore operator<<;
 %ignore *::GetImplementation();
 %ignore *::GetImplementation(Dali::BaseHandle&);
@@ -219,7 +280,7 @@ using namespace Dali::Toolkit;
 
 %include alphafunction.i
 %include name-changed.i
-
+%include property-value.i
 %include dali-operator.i
 %include dali-core.i
 %include dali-adaptor.i
index bc81dec..3db23f4 100644 (file)
 
     public static Application NewApplication(string stylesheet, Application.WINDOW_MODE windowMode) {
 
+      // register all Views with the type registry, so that can be created / styled via JSON
+      ViewRegistryHelper.Initialize();
+
       Application ret = New(1, stylesheet, windowMode);
       if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
 
index db58063..268b7d7 100644 (file)
       }
     }
 
+    ///
+  public void LoadFromFile( string fileName )
+  {
+    try
+    {
+      string json = System.IO.File.ReadAllText( fileName );
+      if( json.Length > 0 )
+      {
+        LoadFromString( json );
+      }
+      else
+      {
+        throw new global::System.InvalidOperationException("Failed to load file " +fileName);
+
+      }
+    }
+    catch ( System.Exception e)
+    {
+      throw new global::System.InvalidOperationException("Failed to parse " +fileName);
+    }
+  }
+
+
     %}
     %enddef
 
diff --git a/plugins/dali-swig/SWIG/property-value.i b/plugins/dali-swig/SWIG/property-value.i
new file mode 100644 (file)
index 0000000..290b4a1
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ *
+ */
+
+#if defined(SWIGCSHARP)
+
+
+ %typemap(cscode) Dali::Property::Value %{
+
+    // Extension to property value class that allows us to create a
+    // PropertyValue from a C# object, e.g. int, float, string
+    static public Property.Value CreateFromObject( System.Object obj)
+    {
+      System.Type type = obj.GetType ();
+
+        Property.Value value;
+
+        if ( type.Equals (typeof(int)) )
+        {
+          System.Console.WriteLine (" got an int property value ");
+          value = new Property.Value ((int) obj );
+        }
+        if ( type.Equals (typeof(System.Int32)) )
+        {
+          System.Console.WriteLine (" got an int property value ");
+          value = new Property.Value ((int) obj );
+        }
+        else if ( type.Equals (typeof(bool)) )
+        {
+          System.Console.WriteLine (" got an bool property value ");
+          value = new Property.Value ((bool) obj );
+        }
+        else if ( type.Equals (typeof(float)) )
+        {
+          System.Console.WriteLine (" got an float property value ");
+          value = new Property.Value ((float) obj );
+        }
+        else if ( type.Equals (typeof(string)) )
+        {
+          System.Console.WriteLine (" got a string property value ");
+          value = new Property.Value ((string) obj );
+        }
+        else if ( type.Equals (typeof(Vector2)) )
+        {
+          System.Console.WriteLine (" got an Vector2 property value ");
+          value = new Property.Value ((Vector2) obj );
+        }
+        else if ( type.Equals (typeof(Vector3)) )
+        {
+          System.Console.WriteLine (" got an Vector3 property value ");
+          value = new Property.Value ((Vector3) obj );
+        }
+        else if ( type.Equals (typeof(Vector4)) )
+        {
+          System.Console.WriteLine (" got an Vector4 property value ");
+
+          value = new Property.Value ((Vector4) obj );
+        }
+        else if ( type.Equals (typeof(Position)) )
+        {
+          System.Console.WriteLine (" got an Position property value ");
+          value = new Property.Value ((Position) obj );
+        }
+        else if ( type.Equals (typeof(Size)) )
+        {
+          System.Console.WriteLine (" got an Size property value ");
+          value = new Property.Value ((Size) obj );
+        }
+        else if ( type.Equals (typeof(Color)) )
+        {
+          System.Console.WriteLine (" got an Color property value ");
+          value = new Property.Value ((Color) obj );
+        }
+        else
+        {
+           throw new global::System.InvalidOperationException("Unimplemented type for Property Value");
+        }
+        return  value;
+    }
+
+
+ %}
+
+
+
+
+#endif
\ No newline at end of file
diff --git a/plugins/dali-swig/examples/date-picker-using-json.cs b/plugins/dali-swig/examples/date-picker-using-json.cs
new file mode 100644 (file)
index 0000000..dbc388c
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Dali;
+
+namespace MyCSharpExample
+{
+    // A spin control (for continously changing values when users can easily predict a set of values)
+
+    class Example
+    {
+        private Dali.Application _application;
+        private Spin _spinYear;  // spin control for year
+        private Spin _spinMonth; // spin control for month
+        private Spin _spinDay;   // spin control for day
+        private Builder _builder; // DALi Builder
+
+        public Example(Dali.Application application)
+        {
+            _application = application;
+            _application.Initialized += Initialize;
+        }
+
+        public void Initialize(object source, NUIApplicationInitEventArgs e)
+        {
+
+            Stage stage = Stage.GetCurrent();
+            stage.BackgroundColor = Color.White;
+
+            // load date JSON template...
+
+            _builder = new Builder ();
+
+            // Optional constant to see logging information coming out
+            // of DALi JSON parser (builder)
+            Property.Map constants = new  Property.Map();
+            constants.Insert( "CONFIG_SCRIPT_LOG_LEVEL",  new Property.Value( "Verbose") );
+            _builder.AddConstants( constants );
+
+            _builder.LoadFromFile( "./json/date-picker.json" );
+
+            // create the date-picker from the template in the json file
+            BaseHandle handle =  _builder.Create( "date-picker");
+
+            Actor actorTree =  Actor.DownCast( handle );
+
+            stage.Add( actorTree );
+
+            Actor year  = actorTree.FindChildByName("Year");
+            Actor month  =  actorTree.FindChildByName("Month" );
+            Actor day  = actorTree.FindChildByName("Day");
+
+            // need to get the actual C# View associated with the actor,
+            _spinYear = (Spin ) ViewRegistry.GetCustomViewFromActor( year );
+            _spinMonth = (Spin ) ViewRegistry.GetCustomViewFromActor( month );
+            _spinDay = (Spin ) ViewRegistry.GetCustomViewFromActor( day );
+
+            _spinYear.Value = 2099;
+            _spinMonth.Value = 5;
+            _spinDay.Value = 23;
+
+
+            _spinYear.SetKeyboardFocusable(true);
+            _spinMonth.SetKeyboardFocusable(true);
+            _spinDay.SetKeyboardFocusable(true);
+
+
+            FocusManager keyboardFocusManager = FocusManager.Instance;
+            keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChange;
+            keyboardFocusManager.FocusedActorEnterKeyPressed += OnFocusedActorEnterKeyPressed;
+
+        }
+
+        private Actor OnKeyboardPreFocusChange(object source, FocusManager.PreFocusChangeEventArgs e)
+        {
+            Actor nextFocusActor = e.Proposed;
+
+            // When nothing has been focused initially, focus the text field in the first spin
+            if (!e.Current && !e.Proposed)
+            {
+                nextFocusActor = _spinYear.SpinText;
+            }
+            else if(e.Direction == View.KeyboardFocus.Direction.LEFT)
+            {
+                // Move the focus to the spin in the left of the current focused spin
+                if(e.Current == _spinMonth.SpinText)
+                {
+                    nextFocusActor = _spinYear.SpinText;
+                }
+                else if(e.Current == _spinDay.SpinText)
+                {
+                    nextFocusActor = _spinMonth.SpinText;
+                }
+            }
+            else if(e.Direction == View.KeyboardFocus.Direction.RIGHT)
+            {
+                // Move the focus to the spin in the right of the current focused spin
+                if(e.Current == _spinYear.SpinText)
+                {
+                    nextFocusActor = _spinMonth.SpinText;
+                }
+                else if(e.Current == _spinMonth.SpinText)
+                {
+                    nextFocusActor = _spinDay.SpinText;
+                }
+            }
+
+            return nextFocusActor;
+        }
+
+        private void OnFocusedActorEnterKeyPressed(object source, FocusManager.FocusedActorEnterKeyEventArgs e)
+        {
+            // Make the text field in the current focused spin to take the key input
+            KeyInputFocusManager manager = KeyInputFocusManager.Get();
+
+            if (e.Actor == _spinYear.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinYear.SpinText)
+                {
+                    manager.SetFocus(_spinYear.SpinText);
+                }
+            }
+            else if (e.Actor == _spinMonth.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinMonth.SpinText)
+                {
+                    manager.SetFocus(_spinMonth.SpinText);
+                }
+            }
+            else if (e.Actor == _spinDay.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinDay.SpinText)
+                {
+                    manager.SetFocus(_spinDay.SpinText);
+                }
+            }
+        }
+
+        public void MainLoop()
+        {
+            _application.MainLoop ();
+        }
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main(string[] args)
+        {
+            Example example = new Example(Application.NewApplication());
+            example.MainLoop ();
+        }
+    }
+}
diff --git a/plugins/dali-swig/examples/date-picker.cs b/plugins/dali-swig/examples/date-picker.cs
new file mode 100644 (file)
index 0000000..c9701cf
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Dali;
+
+namespace MyCSharpExample
+{
+    // A spin control (for continously changing values when users can easily predict a set of values)
+
+    class Example
+    {
+        private Dali.Application _application;
+        private FlexContainer _container;   // Flex container to hold spin controls
+        private Spin _spinYear;  // spin control for year
+        private Spin _spinMonth; // spin control for month
+        private Spin _spinDay;   // spin control for day
+
+        public Example(Dali.Application application)
+        {
+            _application = application;
+            _application.Initialized += Initialize;
+        }
+
+        public void Initialize(object source, NUIApplicationInitEventArgs e)
+        {
+
+            Stage stage = Stage.GetCurrent();
+            stage.BackgroundColor = Color.White;
+
+            // Create a container for the spins
+            _container = new FlexContainer();
+
+            _container.ParentOrigin = NDalic.ParentOriginCenter;
+            _container.AnchorPoint = NDalic.AnchorPointCenter;
+            _container.FlexDirection = (int)FlexContainer.FlexDirectionType.ROW;
+            _container.Size = new Vector3(480.0f, 150.0f, 0.0f);
+
+            stage.Add(_container);
+
+            // Create a Spin control for year
+            _spinYear = new Spin();
+            _spinYear.ParentOrigin = NDalic.ParentOriginCenter;
+            _spinYear.AnchorPoint = NDalic.AnchorPointCenter;
+            _spinYear.Flex = 0.3f;
+            _spinYear.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
+            _container.Add(_spinYear);
+
+            _spinYear.MinValue = 1900;
+            _spinYear.MaxValue = 2100;
+            _spinYear.Value = 2016;
+            _spinYear.Step = 1;
+            _spinYear.MaxTextLength = 4;
+            _spinYear.TextPointSize = 26;
+            _spinYear.TextColor = Color.White;
+            _spinYear.SetKeyboardFocusable(true);
+            _spinYear.Name = "_spinYear";
+
+            // Create a Spin control for month
+            _spinMonth = new Spin();
+            _spinMonth.ParentOrigin = NDalic.ParentOriginCenter;
+            _spinMonth.AnchorPoint = NDalic.AnchorPointCenter;
+            _spinMonth.Flex = 0.3f;
+            _spinMonth.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
+            _container.Add(_spinMonth);
+
+            _spinMonth.MinValue = 1;
+            _spinMonth.MaxValue = 12;
+            _spinMonth.Value = 10;
+            _spinMonth.Step = 1;
+            _spinMonth.MaxTextLength = 2;
+            _spinMonth.TextPointSize = 26;
+            _spinMonth.TextColor = Color.White;
+            _spinMonth.SetKeyboardFocusable(true);
+            _spinMonth.Name = "_spinMonth";
+
+            // Create a Spin control for day
+            _spinDay = new Spin();
+            _spinDay.ParentOrigin = NDalic.ParentOriginCenter;
+            _spinDay.AnchorPoint = NDalic.AnchorPointCenter;
+            _spinDay.Flex = 0.3f;
+            _spinDay.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
+            _container.Add(_spinDay);
+
+            _spinDay.MinValue = 1;
+            _spinDay.MaxValue = 31;
+            _spinDay.Value = 26;
+            _spinDay.Step = 1;
+            _spinDay.MaxTextLength = 2;
+            _spinDay.TextPointSize = 26;
+            _spinDay.TextColor = Color.White;
+            _spinDay.SetKeyboardFocusable(true);
+            _spinDay.Name = "_spinDay";
+
+            FocusManager keyboardFocusManager = FocusManager.Instance;
+            keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChange;
+            keyboardFocusManager.FocusedActorEnterKeyPressed += OnFocusedActorEnterKeyPressed;
+
+        }
+
+        private Actor OnKeyboardPreFocusChange(object source, FocusManager.PreFocusChangeEventArgs e)
+        {
+            Actor nextFocusActor = e.Proposed;
+
+            // When nothing has been focused initially, focus the text field in the first spin
+            if (!e.Current && !e.Proposed)
+            {
+                nextFocusActor = _spinYear.SpinText;
+            }
+            else if(e.Direction == View.KeyboardFocus.Direction.LEFT)
+            {
+                // Move the focus to the spin in the left of the current focused spin
+                if(e.Current == _spinMonth.SpinText)
+                {
+                    nextFocusActor = _spinYear.SpinText;
+                }
+                else if(e.Current == _spinDay.SpinText)
+                {
+                    nextFocusActor = _spinMonth.SpinText;
+                }
+            }
+            else if(e.Direction == View.KeyboardFocus.Direction.RIGHT)
+            {
+                // Move the focus to the spin in the right of the current focused spin
+                if(e.Current == _spinYear.SpinText)
+                {
+                    nextFocusActor = _spinMonth.SpinText;
+                }
+                else if(e.Current == _spinMonth.SpinText)
+                {
+                    nextFocusActor = _spinDay.SpinText;
+                }
+            }
+
+            return nextFocusActor;
+        }
+
+        private void OnFocusedActorEnterKeyPressed(object source, FocusManager.FocusedActorEnterKeyEventArgs e)
+        {
+            // Make the text field in the current focused spin to take the key input
+            KeyInputFocusManager manager = KeyInputFocusManager.Get();
+
+            if (e.Actor == _spinYear.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinYear.SpinText)
+                {
+                    manager.SetFocus(_spinYear.SpinText);
+                }
+            }
+            else if (e.Actor == _spinMonth.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinMonth.SpinText)
+                {
+                    manager.SetFocus(_spinMonth.SpinText);
+                }
+            }
+            else if (e.Actor == _spinDay.SpinText)
+            {
+                if (manager.GetCurrentFocusControl() != _spinDay.SpinText)
+                {
+                    manager.SetFocus(_spinDay.SpinText);
+                }
+            }
+        }
+
+        public void MainLoop()
+        {
+            _application.MainLoop ();
+        }
+
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main(string[] args)
+        {
+            Example example = new Example(Application.NewApplication());
+            example.MainLoop ();
+        }
+    }
+}
diff --git a/plugins/dali-swig/examples/json-loader.cs b/plugins/dali-swig/examples/json-loader.cs
new file mode 100644 (file)
index 0000000..388b077
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Dali;
+
+namespace MyExampleApp
+{
+  class Example
+  {
+    private Dali.Application _application;
+    private Builder _builder;
+    private string _jsonFileName;
+
+    public Example(Dali.Application application, string fileName)
+    {
+      _application = application;
+      _jsonFileName = fileName;
+      _application.Initialized += Initialize;
+    }
+
+    public void Initialize(object source, NUIApplicationInitEventArgs e)
+    {
+        if( _jsonFileName.Length == 0)
+        {
+          Console.WriteLine("Please specify JSON file to load");
+          return;
+        }
+
+        _builder = new Builder ();
+
+        Property.Map constants = new  Property.Map();
+
+        //  In dali-demo we have some JSON files that can be loaded, but they need 3 different macros defining.
+        // The JSON folder is typically installed into dali-env/opt/share/com.samsung.dali-demo/res:
+        //
+        //string demoDirectory = ".../dali-env/opt/share/com.samsung.dali-demo/res";
+        //constants.Insert( "DEMO_IMAGE_DIR" ,  new Property.Value( demoDirectory+"/images") );
+        //constants.Insert( "DEMO_MODEL_DIR" ,  new Property.Value( demoDirectory+"/models") );
+        //constants.Insert( "DEMO_SCRIPT_DIR",  new Property.Value( demoDirectory+"/scripts") );
+        constants.Insert( "CONFIG_SCRIPT_LOG_LEVEL",  new Property.Value( "Verbose") );
+
+         _builder.AddConstants( constants );
+
+
+        Stage stage = Stage.GetCurrent();
+        stage.BackgroundColor = Color.White;
+
+        _builder.LoadFromFile( _jsonFileName );
+
+        _builder.AddActors( stage.GetRootLayer() );
+
+    }
+
+
+    public void MainLoop()
+    {
+      _application.MainLoop ();
+    }
+
+    /// <summary>
+    /// The main entry point for the application.
+    /// </summary>
+    [STAThread]
+    static void Main(string[] args)
+    {
+      string fileName= "";
+
+      if( args.Length > 0)
+      {
+          fileName = args[0];
+      }
+
+      Console.WriteLine("arguments = " + args.Length);
+      Example example = new Example(Application.NewApplication(), fileName);
+      example.MainLoop ();
+    }
+  }
+}
diff --git a/plugins/dali-swig/examples/json/date-picker-template.json b/plugins/dali-swig/examples/json/date-picker-template.json
new file mode 100644 (file)
index 0000000..dd01d8f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+{
+  // Data picker loaded directly on to the stage
+  //
+  "templates": {
+    "date-picker":
+    {
+      "type":"FlexContainer",
+      "name":"exampleDatePicker",
+      "parentOrigin": "CENTER",
+      "anchorPoint": "CENTER",
+      "flexDirection":"ROW",
+      "size":[480.0, 150, 0 ],
+      "actors": [
+      {
+
+        "type": "Spin",
+        "name": "Year",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "Value":2017,
+        "MinValue":1900,
+        "MaxValue":2100,
+        "Step":1,
+        "TextColor":[0.0,0.0,1.0,1.0],
+        "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+      },
+      {
+
+        "type": "Spin",
+        "name": "Month",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "parentOrigin": "CENTER",
+        "Value":10,
+        "Step":1,
+        "MinValue":1,
+        "MaxValue":12,
+        "TextColor":[1.0,1.0,1.0,1.0],
+        "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+
+      },
+      {
+
+        "type": "Spin",
+        "name": "Day",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "Value":1,
+        "MinValue":1,
+        "MaxValue":31,
+        "TextColor":[1.0,0.0,0.0,1.0],
+         "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+      }]
+
+    }
+}
+
+}
+
diff --git a/plugins/dali-swig/examples/json/date-picker.json b/plugins/dali-swig/examples/json/date-picker.json
new file mode 100644 (file)
index 0000000..3126aa3
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+{
+  // Data picker loaded directly on to the stage
+  //
+  "stage": [{
+
+      "type":"FlexContainer",
+      "name":"exampleDatePicker",
+      "parentOrigin": "CENTER",
+      "anchorPoint": "CENTER",
+      "flexDirection":"ROW",
+      "size":[480.0, 150, 0 ],
+      "actors": [
+      {
+
+        "type": "Spin",
+        "name": "Year",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "MinValue":1900,
+        "MaxValue":2100,
+        "Value":2017,
+        "Step":1,
+        "TextColor":[0.0,0.0,1.0,1.0],
+        "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+      },
+      {
+
+        "type": "Spin",
+        "name": "Month",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "parentOrigin": "CENTER",
+        "Step":1,
+        "MinValue":1,
+        "MaxValue":12,
+        "Value":10,
+        "TextColor":[1.0,1.0,1.0,1.0],
+        "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+
+      },
+      {
+
+        "type": "Spin",
+        "name": "Day",
+        "parentOrigin": "CENTER",
+        "anchorPoint": "CENTER",
+        "MinValue":1,
+        "MaxValue":31,
+        "Value":1,
+        "TextColor":[1.0,0.0,0.0,1.0],
+         "properties": { // properties registered dynamically
+            "flex":0.3,
+            "flexMargin": [5.0,0.0,5.0,0.0]
+        }
+      }]
+
+}]
+
+}
+
diff --git a/plugins/dali-swig/examples/json/spin.json b/plugins/dali-swig/examples/json/spin.json
new file mode 100644 (file)
index 0000000..df9b10c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+{
+  // a tree of actors
+  "stage": [
+    // You can add an array of  Actors / Views here
+    // Lets add a spin to the stage
+    {
+      "type":"Spin",
+      "parentOrigin":"CENTER",
+      "size":[120,120,0]
+      // now lets use the C# app json-loader.exe to load it
+    }
+
+  ]
+}
diff --git a/plugins/dali-swig/examples/spin-control.cs b/plugins/dali-swig/examples/spin-control.cs
deleted file mode 100755 (executable)
index f385852..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * 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.
- *
- */
-
-using System;
-using System.Runtime.InteropServices;
-using Dali;
-
-namespace MyCSharpExample
-{
-    // A spin control (for continously changing values when users can easily predict a set of values)
-    class Spin : CustomView
-    {
-        private VisualBase _arrowVisual;
-        private TextField _textField;
-        private int _arrowVisualPropertyIndex;
-        private string _arrowImage;
-        private int _currentValue;
-        private int _minValue;
-        private int _maxValue;
-        private int _singleStep;
-        private bool _wrappingEnabled;
-        private string _fontFamily;
-        private string _fontStyle;
-        private int _pointSize;
-        private Color _textColor;
-        private Color _textBackgroundColor;
-        private int _maxTextLength;
-
-        public Spin() : base(ViewWrapperImpl.CustomViewBehaviour.REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | ViewWrapperImpl.CustomViewBehaviour.DISABLE_STYLE_CHANGE_SIGNALS)
-        {
-        }
-
-        public override void OnInitialize()
-        {
-            // Initialize the properties
-            _arrowImage = "./images/arrow.png";
-            _textBackgroundColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
-            _currentValue = 0;
-            _minValue = 0;
-            _maxValue = 0;
-            _singleStep = 1;
-            _maxTextLength = 0;
-
-            // Create image visual for the arrow keys
-            _arrowVisualPropertyIndex = RegisterProperty("ArrowImage", new Dali.Property.Value(_arrowImage), Dali.Property.AccessMode.READ_WRITE);
-            _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
-            RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
-
-            // Create a text field
-            _textField = new TextField();
-            _textField.ParentOrigin = NDalic.ParentOriginCenter;
-            _textField.AnchorPoint = NDalic.AnchorPointCenter;
-            _textField.WidthResizePolicy = "SIZE_RELATIVE_TO_PARENT";
-            _textField.HeightResizePolicy = "SIZE_RELATIVE_TO_PARENT";
-            _textField.SizeModeFactor = new Vector3( 1.0f, 0.45f, 1.0f );
-            _textField.PlaceholderText = "----";
-            _textField.BackgroundColor = _textBackgroundColor;
-            _textField.HorizontalAlignment = "Center";
-            _textField.VerticalAlignment = "Center";
-            _textField.SetKeyboardFocusable(true);
-            _textField.Name = "_textField";
-
-            this.Add(_textField);
-
-            _textField.KeyInputFocusGained += TextFieldKeyInputFocusGained;
-            _textField.KeyInputFocusLost += TextFieldKeyInputFocusLost;
-        }
-
-        public override Vector3 GetNaturalSize()
-        {
-            return new Vector3(150.0f, 150.0f, 0.0f);
-        }
-
-        public void TextFieldKeyInputFocusGained(object source, KeyInputFocusGainedEventArgs e)
-        {
-            // Make sure when the current spin that takes input focus also takes the keyboard focus
-            // For example, when you tap the spin directly
-            FocusManager.Instance.SetCurrentFocusActor(_textField);
-        }
-
-        public void TextFieldKeyInputFocusLost(object source, KeyInputFocusLostEventArgs e)
-        {
-            int previousValue = _currentValue;
-
-            // If the input value is invalid, change it back to the previous valid value
-            if(int.TryParse(_textField.Text, out _currentValue))
-            {
-                if (_currentValue < _minValue || _currentValue > _maxValue)
-                {
-                    _currentValue = previousValue;
-                }
-            }
-            else
-            {
-                _currentValue = previousValue;
-            }
-
-            // Otherwise take the new value
-            this.Value = _currentValue;
-        }
-
-        public override Actor GetNextKeyboardFocusableActor(Actor currentFocusedActor, View.KeyboardFocus.Direction direction, bool loopEnabled)
-        {
-            // Respond to Up/Down keys to change the value while keeping the current spin focused
-            Actor nextFocusedActor = currentFocusedActor;
-            if (direction == View.KeyboardFocus.Direction.UP)
-            {
-                this.Value += this.Step;
-                nextFocusedActor = _textField;
-            }
-            else if (direction == View.KeyboardFocus.Direction.DOWN)
-            {
-                this.Value -= this.Step;
-                nextFocusedActor = _textField;
-            }
-            else
-            {
-                // Return a native empty handle as nothing can be focused in the left or right
-                nextFocusedActor = new Actor();
-                nextFocusedActor.Reset();
-            }
-
-            return nextFocusedActor;
-        }
-
-        // Value property of type int:
-        public int Value
-        {
-            get
-            {
-                return _currentValue;
-            }
-            set
-            {
-                _currentValue = value;
-
-                // Make sure no invalid value is accepted
-                if (_currentValue < _minValue)
-                {
-                    _currentValue = _minValue;
-                }
-
-                if (_currentValue > _maxValue)
-                {
-                    _currentValue = _maxValue;
-                }
-
-                _textField.Text = _currentValue.ToString();
-            }
-        }
-
-        // MinValue property of type int:
-        public int MinValue
-        {
-            get
-            {
-                return _minValue;
-            }
-            set
-            {
-              _minValue = value;
-            }
-        }
-
-        // MaxValue property of type int:
-        public int MaxValue
-        {
-            get
-            {
-                return _maxValue;
-            }
-            set
-            {
-              _maxValue = value;
-            }
-        }
-
-        // Step property of type int:
-        public int Step
-        {
-            get
-            {
-                return _singleStep;
-            }
-            set
-            {
-              _singleStep = value;
-            }
-        }
-
-        // WrappingEnabled property of type bool:
-        public bool WrappingEnabled
-        {
-            get
-            {
-                return _wrappingEnabled;
-            }
-            set
-            {
-              _wrappingEnabled = value;
-            }
-        }
-
-        // TextPointSize property of type int:
-        public int TextPointSize
-        {
-            get
-            {
-                return _pointSize;
-            }
-            set
-            {
-              _pointSize = value;
-              _textField.PointSize = _pointSize;
-            }
-        }
-
-        // TextColor property of type Color:
-        public Color TextColor
-        {
-            get
-            {
-                return _textColor;
-            }
-            set
-            {
-              _textColor = value;
-              _textField.TextColor = _textColor;
-            }
-        }
-
-        // MaxTextLength property of type int:
-        public int MaxTextLength
-        {
-            get
-            {
-                return _maxTextLength;
-            }
-            set
-            {
-                _maxTextLength = value;
-                _textField.MaxLength = _maxTextLength;
-            }
-        }
-
-        public TextField SpinText
-        {
-            get
-            {
-                return _textField;
-            }
-            set
-            {
-                _textField = value;
-            }
-        }
-
-        // Indicator property of type string:
-        public string IndicatorImage
-        {
-            get
-            {
-                return _arrowImage;
-            }
-            set
-            {
-              _arrowImage = value;
-              _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
-              RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
-            }
-        }
-    }
-
-    class Example
-    {
-        private Dali.Application _application;
-        private FlexContainer _container;
-        private Spin _spinYear;
-        private Spin _spinMonth;
-        private Spin _spinDay;
-
-        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
-        delegate void CallbackDelegate();
-
-        public Example(Dali.Application application)
-        {
-            _application = application;
-            _application.Initialized += Initialize;
-        }
-
-        public void Initialize(object source, NUIApplicationInitEventArgs e)
-        {
-            Stage stage = Stage.GetCurrent();
-            stage.BackgroundColor = Color.White;
-
-            // Create a container for the spins
-            _container = new FlexContainer();
-
-            _container.ParentOrigin = NDalic.ParentOriginCenter;
-            _container.AnchorPoint = NDalic.AnchorPointCenter;
-            _container.FlexDirection = (int)FlexContainer.FlexDirectionType.ROW;
-            _container.Size = new Vector3(480.0f, 150.0f, 0.0f);
-
-            stage.Add(_container);
-
-            // Create a Spin control for year
-            _spinYear = new Spin();
-            _spinYear.ParentOrigin = NDalic.ParentOriginCenter;
-            _spinYear.AnchorPoint = NDalic.AnchorPointCenter;
-            _spinYear.Flex = 0.3f;
-            _spinYear.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
-            _container.Add(_spinYear);
-
-            _spinYear.MinValue = 1900;
-            _spinYear.MaxValue = 2100;
-            _spinYear.Value = 2016;
-            _spinYear.Step = 1;
-            _spinYear.MaxTextLength = 4;
-            _spinYear.TextPointSize = 26;
-            _spinYear.TextColor = Color.White;
-            _spinYear.SetKeyboardFocusable(true);
-            _spinYear.Name = "_spinYear";
-
-            // Create a Spin control for month
-            _spinMonth = new Spin();
-            _spinMonth.ParentOrigin = NDalic.ParentOriginCenter;
-            _spinMonth.AnchorPoint = NDalic.AnchorPointCenter;
-            _spinMonth.Flex = 0.3f;
-            _spinMonth.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
-            _container.Add(_spinMonth);
-
-            _spinMonth.MinValue = 1;
-            _spinMonth.MaxValue = 12;
-            _spinMonth.Value = 10;
-            _spinMonth.Step = 1;
-            _spinMonth.MaxTextLength = 2;
-            _spinMonth.TextPointSize = 26;
-            _spinMonth.TextColor = Color.White;
-            _spinMonth.SetKeyboardFocusable(true);
-            _spinMonth.Name = "_spinMonth";
-
-            // Create a Spin control for day
-            _spinDay = new Spin();
-            _spinDay.ParentOrigin = NDalic.ParentOriginCenter;
-            _spinDay.AnchorPoint = NDalic.AnchorPointCenter;
-            _spinDay.Flex = 0.3f;
-            _spinDay.FlexMargin = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
-            _container.Add(_spinDay);
-
-            _spinDay.MinValue = 1;
-            _spinDay.MaxValue = 31;
-            _spinDay.Value = 26;
-            _spinDay.Step = 1;
-            _spinDay.MaxTextLength = 2;
-            _spinDay.TextPointSize = 26;
-            _spinDay.TextColor = Color.White;
-            _spinDay.SetKeyboardFocusable(true);
-            _spinDay.Name = "_spinDay";
-
-            FocusManager keyboardFocusManager = FocusManager.Instance;
-            keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChange;
-            keyboardFocusManager.FocusedActorEnterKeyPressed += OnFocusedActorEnterKeyPressed;
-
-        }
-
-        private Actor OnKeyboardPreFocusChange(object source, FocusManager.PreFocusChangeEventArgs e)
-        {
-            Actor nextFocusActor = e.Proposed;
-
-            // When nothing has been focused initially, focus the text field in the first spin
-            if (!e.Current && !e.Proposed)
-            {
-                nextFocusActor = _spinYear.SpinText;
-            }
-            else if(e.Direction == View.KeyboardFocus.Direction.LEFT)
-            {
-                // Move the focus to the spin in the left of the current focused spin
-                if(e.Current == _spinMonth.SpinText)
-                {
-                    nextFocusActor = _spinYear.SpinText;
-                }
-                else if(e.Current == _spinDay.SpinText)
-                {
-                    nextFocusActor = _spinMonth.SpinText;
-                }
-            }
-            else if(e.Direction == View.KeyboardFocus.Direction.RIGHT)
-            {
-                // Move the focus to the spin in the right of the current focused spin
-                if(e.Current == _spinYear.SpinText)
-                {
-                    nextFocusActor = _spinMonth.SpinText;
-                }
-                else if(e.Current == _spinMonth.SpinText)
-                {
-                    nextFocusActor = _spinDay.SpinText;
-                }
-            }
-
-            return nextFocusActor;
-        }
-
-        private void OnFocusedActorEnterKeyPressed(object source, FocusManager.FocusedActorEnterKeyEventArgs e)
-        {
-            // Make the text field in the current focused spin to take the key input
-            KeyInputFocusManager manager = KeyInputFocusManager.Get();
-
-            if (e.Actor == _spinYear.SpinText)
-            {
-                if (manager.GetCurrentFocusControl() != _spinYear.SpinText)
-                {
-                    manager.SetFocus(_spinYear.SpinText);
-                }
-            }
-            else if (e.Actor == _spinMonth.SpinText)
-            {
-                if (manager.GetCurrentFocusControl() != _spinMonth.SpinText)
-                {
-                    manager.SetFocus(_spinMonth.SpinText);
-                }
-            }
-            else if (e.Actor == _spinDay.SpinText)
-            {
-                if (manager.GetCurrentFocusControl() != _spinDay.SpinText)
-                {
-                    manager.SetFocus(_spinDay.SpinText);
-                }
-            }
-        }
-
-        public void MainLoop()
-        {
-            _application.MainLoop ();
-        }
-
-        /// <summary>
-        /// The main entry point for the application.
-        /// </summary>
-        [STAThread]
-        static void Main(string[] args)
-        {
-            Example example = new Example(Application.NewApplication());
-            example.MainLoop ();
-        }
-    }
-}
diff --git a/plugins/dali-swig/manual/csharp/PropertyRangeManager.cs b/plugins/dali-swig/manual/csharp/PropertyRangeManager.cs
new file mode 100644 (file)
index 0000000..7e6c4d4
--- /dev/null
@@ -0,0 +1,138 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace Dali
+{
+  /// <summary>
+  /// Helper class for calculating what property indexes should be assigned to C# View (view) classes.
+  /// </summary>
+  public class PropertyRangeManager
+  {
+    private Dictionary<String, PropertyRange > _propertyRange;
+
+    /// <summary>
+    /// Initializes a new instance of the <see cref="Dali.PropertyRangeManager"/> class.
+    /// </summary>
+    public PropertyRangeManager ()
+    {
+      _propertyRange = new Dictionary<String, PropertyRange > ();
+    }
+
+    /// <summary>
+    /// Only called if a View has scriptable properties
+    /// </summary>
+    private PropertyRange RegisterView( string viewName, System.Type viewType )
+    {
+      PropertyRange range;
+
+      if ( _propertyRange.TryGetValue (viewName, out range) )
+      {
+        // already registered
+        return range;
+      }
+
+      // Find out the event and animatable start indexes for the type
+      range = new PropertyRange();
+
+      GetPropertyStartRange( viewType, ref range);
+
+      // add it to our dictionary
+      _propertyRange.Add( viewName, range );
+
+      return range;
+
+     }
+
+    /// <summary>
+    /// Gets the index of the property.
+    /// Each property has to have unique index for this view type
+    /// </summary>
+    /// <returns>The property index.</returns>
+    /// <param name="viewName">View name</param>
+    /// <param name="viewType">View type</param>
+    /// <param name="type">Type.</param>
+    public int GetPropertyIndex( string viewName, System.Type viewType, ScriptableProperty.ScriptableType type )
+    {
+
+      PropertyRange range;
+
+      if (!  _propertyRange.TryGetValue (viewName, out range) )
+      {
+         // view not found, register it now
+          range = RegisterView( viewName, viewType);
+      }
+
+      int index =  range.GetNextFreePropertyIndex ( type );
+
+      // update the dictionary
+      _propertyRange[viewName]=range;
+
+      return index;
+
+    }
+
+    ///<summary>
+    /// We calculate the start property indices, based on the type and it's class  heirachy, e.g. DateView (70,000)- > Spin (60,000) -> View (50,000)
+    /// </summary>
+    private void GetPropertyStartRange( System.Type viewType, ref PropertyRange range )
+    {
+      const int maxCountPerDerivation = 1000; // For child and animtable properties we use a gap of 1000 between each
+      // views property range in the heirachy
+
+      // custom views start there property index, at view_PROPERTY_END_INDEX
+      // we add 1000, just incase View class (our C# custom view base) starts using scriptable properties
+      int startEventPropertyIndex = (int)View.PropertyRange.CONTROL_PROPERTY_END_INDEX+maxCountPerDerivation;
+
+      // for animatable properties current range starts at ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX,
+      // we add 1000, just incase View class starts using animatable properties
+      int startAnimatablePropertyIndex = (int)Dali.PropertyRanges.ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX +maxCountPerDerivation;
+
+      while ( viewType.BaseType.Name != "CustomView" )   // custom view is our C# view base class. we don't go any deeper.
+      {
+        // for every base class increase property start index
+        startEventPropertyIndex += (int)Dali.PropertyRanges.DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION; // DALi uses 10,000
+        startAnimatablePropertyIndex += maxCountPerDerivation;
+
+        //Console.WriteLine ("getStartPropertyIndex =  " + viewType.Name +"current index " + startEventPropertyIndex);
+        viewType = viewType.BaseType;
+      }
+
+      range.startEventIndex = startEventPropertyIndex;
+      range.lastUsedEventIndex = startEventPropertyIndex;
+
+      range.startAnimationIndex = startAnimatablePropertyIndex;
+      range.lastUsedAnimationIndex = startAnimatablePropertyIndex;
+
+    }
+
+
+    public struct PropertyRange
+    {
+
+      public int GetNextFreePropertyIndex( ScriptableProperty.ScriptableType type)
+      {
+        if ( type == ScriptableProperty.ScriptableType.Default )
+        {
+           lastUsedEventIndex++;
+           return lastUsedEventIndex;
+        }
+        else
+        {
+          lastUsedAnimationIndex++;
+          return lastUsedAnimationIndex ;
+        }
+      }
+
+
+      public int startEventIndex;    /// start of the property range
+      public int lastUsedEventIndex;    /// last used of the property index
+
+      public int startAnimationIndex;  /// start of the property range
+      public int lastUsedAnimationIndex; /// last used of the property index
+    };
+
+
+
+}
+}
diff --git a/plugins/dali-swig/manual/csharp/ViewRegistry.cs b/plugins/dali-swig/manual/csharp/ViewRegistry.cs
new file mode 100644 (file)
index 0000000..29ece3a
--- /dev/null
@@ -0,0 +1,507 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+namespace Dali
+{
+  /// <summary>
+  /// Add this attribute to any property belonging to a View (control) you want to be scriptable from JSON
+  /// </summary>
+  /// <remarks>
+  /// Example:
+  ///
+  /// class MyView : public CustomView
+  /// {
+  ///  [ScriptableProperty()]
+  ///  public int MyProperty
+  ///  {
+  ///   get
+  ///   {
+  ///     return _myProperty;
+  ///   }
+  ///   set
+  ///   {
+  ///    _myProperty = value;
+  ///   }
+  ///  }
+  /// }
+  ///
+  /// Internally the following occurs for property registration ( this only occurs once per Type, not per Instance):
+  ///
+  /// - The controls static constructor should call ViewRegistry.Register()  (only called once for the lifecycle of the app)
+  /// - Within Register() the code will introspect the Controls properties, looking for the ScriptableProperty() attribute
+  /// - For every property with the ScriptableProperty() attribute, TypeRegistration.RegisterProperty is called.
+  /// - TypeRegistration.RegisterProperty calls in to DALi C++ Code Dali::CSharpTypeRegistry::RegisterProperty()
+  /// - DALi C++ now knows the existance of the property and will try calling SetProperty, if it finds the property in a JSON file (loaded using builder).
+  ///
+  ///  The DALi C# example
+  ///
+  ///  class MyView : public CustomView
+  ///  {
+  ///
+  ///    [ScriptableProperty()]
+  ///    public double Hours
+  ///    {
+  ///     get { return seconds / 3600; }
+  ///     set { seconds = value * 3600; }
+  ///    }
+  ///  }
+  ///
+  ///  Equivalent code in DALi C++:
+  ///  in MyControl.h
+  ///  class MyControl : public Control
+  ///  {
+  ///      struct Property
+  ///      {
+  ///         enum
+  ///        {
+  ///              HOURS =  Control::CONTROL_PROPERTY_END_INDEX + 1
+  ///        }
+  ///     }
+  ///
+  ///
+  /// in MyControl-impl.cpp
+  ///
+  /// DALI_TYPE_REGISTRATION_BEGIN( Toolkit::MyControl, Toolkit::Control, Create );
+  /// DALI_PROPERTY_REGISTRATION( Toolkit, MyControl, "Hours",  INTEGER, DISABLED                     )
+  /// DALI_TYPE_REGISTRATION_END()
+  /// </remarks>
+  ///
+  ///
+  public class ScriptableProperty : System.Attribute
+  {
+    public enum ScriptableType
+    {
+      Default,    // Read Writable, non-animatable property, event thread only
+    //  Animatable // Animatable property, Currently disabled, UK
+    }
+    public readonly ScriptableType type;
+
+    public ScriptableProperty(ScriptableType type = ScriptableType.Default )
+    {
+      this.type = type;
+    }
+  }
+
+  /// <summary>
+  /// View Registry singleton.
+  /// Used for registering controls and any scriptable properties they have ( see ScriptableProperty )
+  ///
+  /// Internal Design from C# to C++
+  ///
+  /// - Each custom C# view should have it's static constructor called before any JSON file is loaded.
+  /// Static constructors for a class will only run once ( they are run per control type, not per instance).
+  /// Example of running a static constructor:
+  ///      System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (typeof(Spin).TypeHandle);
+  /// Inside the static constructor the control should register it's type with the ViewRegistry
+  /// e.g.
+  ///
+  ///  static Spin()
+  ///  {
+  ///     ViewRegistry.Instance.RegisterControl("Spin", CreateInstance, typeof(Spin) );
+  ///  }
+  ///
+  ///  The control should also provide a CreateInstance function, which gets passed to the ViewRegistry
+  ///  // Eventually it will be called if DALi Builderfinds a Spin control in a JSON file
+  ///  static CustomView CreateInstance()
+  ///  {
+  ///    return new Spin();
+  ///  }
+  ///
+  ///
+  ///
+  /// The DALi C++ equivalent of this is
+  ///
+  ///  TypeRegistration mType( typeid(Toolkit::Spin), typeid(Toolkit::Control), CreateInstance );
+  ///
+  ///
+  ///
+  /// </summary>
+  public sealed class ViewRegistry
+  {
+    /// <summary>
+    /// ViewRegistry is a singleton
+    /// </summary>
+    private static ViewRegistry instance = null;
+
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    delegate IntPtr CreateControlDelegate( IntPtr cPtrControlName );
+
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    delegate IntPtr GetPropertyDelegate( IntPtr controlPtr, IntPtr propertyName );
+
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    delegate void SetPropertyDelegate( IntPtr controlPtr, IntPtr propertyName, IntPtr propertyValue );
+
+    private CreateControlDelegate _createCallback;
+    private SetPropertyDelegate _setPropertyCallback;
+    private GetPropertyDelegate _getPropertyCallback;
+    private PropertyRangeManager _propertyRangeManager;
+
+    /// <summary>
+    /// Given a C++ custom control the dictionary allows us to find what CustomView it belongs to
+    /// </summary>
+    private Dictionary<IntPtr, Dali.CustomView> _controlMap;
+
+    ///<summary>
+    // Maps the name of a custom view to a create instance function
+    /// E.g. given a string "Spin", we can get a function used to create the Spin View.
+    ///</summary>
+    private Dictionary<String, Func< CustomView > > _constructorMap;
+
+    /// <summary>
+    /// Lookup table to match C# types to DALi types, used for the automatic property registration
+    /// </summary>
+    private static readonly Dictionary<string, Dali.Property.Type> _daliPropertyTypeLookup
+    = new Dictionary< string, Dali.Property.Type  >
+    {
+      { "float",   Property.Type.FLOAT },
+      { "int",     Property.Type.INTEGER },
+      { "Int32",   Property.Type.INTEGER },
+      { "Boolean", Property.Type.BOOLEAN },
+      { "string",  Property.Type.STRING },
+      { "Vector2", Property.Type.VECTOR2 },
+      { "Vector3", Property.Type.VECTOR3 },
+      { "Vector4", Property.Type.VECTOR4 },
+      { "Size",    Property.Type.VECTOR2 },
+      { "Position",Property.Type.VECTOR3 },
+      { "Color",   Property.Type.VECTOR4 },
+    //  { "Matrix3", Property.Type.MATRIX3 }, commented out until we need to use Matrices from JSON
+    //  { "Matrix",  Property.Type.MATRIX },
+    };
+
+
+    public ViewRegistry()
+    {
+      _createCallback = new CreateControlDelegate( CreateControl );
+      _getPropertyCallback = new GetPropertyDelegate (GetProperty);
+      _setPropertyCallback  = new SetPropertyDelegate (SetProperty);
+
+      _controlMap = new Dictionary<IntPtr, CustomView>();
+      _constructorMap = new Dictionary<string, Func<CustomView>>();
+      _propertyRangeManager = new PropertyRangeManager();
+
+    }
+
+    private Dali.Property.Type GetDaliPropertyType( string cSharpTypeName )
+    {
+      Dali.Property.Type daliType;
+      if ( _daliPropertyTypeLookup.TryGetValue (cSharpTypeName, out daliType) )
+      {
+        //Console.WriteLine("mapped "+ cSharpTypeName + " to dAli type " +daliType );
+        return daliType;
+      }
+      else
+      {
+       // Console.WriteLine("Failed to find a mapping between C# property" + cSharpTypeName +" and DALi type");
+        return Property.Type.NONE;
+      }
+    }
+
+    /// <summary>
+    /// Called directly from DALi C++ type registry to create a control (View)  uses no marshalling.
+    /// </summary>
+    /// <returns>Pointer to the Control (Views) handle </returns>
+    /// <param name="cPtrControlName"> C pointer to the Control (View) name</param>
+    private static IntPtr CreateControl( IntPtr cPtrControlName )
+    {
+      string controlName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (cPtrControlName);
+      // Console.WriteLine ("Create controlled called from C++ create a " + controlName);
+
+      Func< CustomView > controlConstructor;
+
+      // find the control constructor
+      if ( Instance._constructorMap.TryGetValue (controlName, out controlConstructor) )
+      {
+        // Create the control
+        CustomView newControl = controlConstructor ();
+
+        // Store the mapping between this instance of the custom control and native part
+        // We store a pointer to the RefObject for the control
+        IntPtr cPtr = newControl.GetPtrfromActor();
+        RefObject refObj = newControl.GetObjectPtr ();
+        IntPtr refCptr = (IntPtr) RefObject.getCPtr(refObj);
+
+        //Console.WriteLine ("________Storing ref object cptr in control map Hex: {0:X}", refCptr);
+        Instance._controlMap.Add (refCptr , newControl );
+
+        return cPtr;  // return pointer to handle
+      }
+      else
+      {
+        throw new global::System.InvalidOperationException("C# View not registererd with ViewRegistry"+ controlName );
+        return IntPtr.Zero;
+      }
+    }
+
+    private static IntPtr GetProperty( IntPtr controlPtr, IntPtr propertyName )
+    {
+      string name = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (propertyName);
+      return Instance.GetPropertyValue ( controlPtr, name);
+    }
+
+    private static void SetProperty(  IntPtr controlPtr, IntPtr propertyName, IntPtr propertyValue )
+    {
+      string name = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (propertyName);
+      //Console.WriteLine ( SetControlProperty  called for:" + name );
+      Instance.SetPropertyValue ( controlPtr, name, propertyValue);
+
+    }
+
+    public static ViewRegistry Instance
+    {
+      get
+      {
+        if (instance==null)
+        {
+          instance = new ViewRegistry();
+        }
+        return instance;
+      }
+    }
+
+    public static CustomView GetCustomViewFromActor( Actor actor )
+    {
+      // we store a dictionary of ref-obects (C++ land) to custom views (C# land)
+      Dali.CustomView view;
+
+      RefObject refObj = actor.GetObjectPtr ();
+      IntPtr refObjectPtr = (IntPtr) RefObject.getCPtr(refObj);
+
+      if ( Instance._controlMap.TryGetValue ( refObjectPtr, out view) )
+      {
+
+        // call the get property function
+
+        return view;
+      }
+      else
+      {
+        return null;
+      }
+    }
+
+
+    /// <summary>
+    /// Function which registers a view and all it's scriptable properties with DALi's type registry.
+    /// Means the View can be created / configured from a JSON script.
+    ///
+    /// The function uses introspection to scan a Views C# properties, then selects the ones with
+    ///[ScriptableProperty] attribute to be registered.
+    /// Example of a Spin view registering itself
+    ///   static Spin()
+    /// {
+    ///   ViewRegistry registers control type with DALi type registery
+    ///   also uses introspection to find any properties that need to be registered with type registry
+    ///   ViewRegistry.Instance.Register("Spin", CreateInstance, typeof(Spin) );
+    /// }
+    ///
+    /// </summary>
+    public void Register(string viewName, Func< CustomView > createFunction, System.Type viewType )
+    {
+      // add the mapping between the view name and it's create function
+      _constructorMap.Add (viewName, createFunction);
+
+      // Call into DALi C++ to register the control with the type registry
+      TypeRegistration.RegisterControl( viewName, _createCallback );
+
+      // Cycle through each property in the class
+      foreach (System.Reflection.PropertyInfo propertyInfo in viewType.GetProperties())
+      {
+
+        if ( propertyInfo.CanRead )
+        {
+
+          System.Attribute[] attrs = System.Attribute.GetCustomAttributes(propertyInfo);
+          foreach (System.Attribute attr in attrs)
+          {
+            // If the Scriptable attribute exists, then register it with the type registry.
+            if (attr is ScriptableProperty)
+            {
+              //Console.WriteLine ("Got a DALi JSON scriptable property = " + propertyInfo.Name +", of type " + propertyInfo.PropertyType.Name);
+
+              // first get the attribute type, ( default, or animatable)
+              ScriptableProperty scriptableProp = attr as ScriptableProperty;
+
+              // we get the start property index, based on the type and it's heirachy, e.g. DateView (70,000)-> Spin (60,000) -> View (50,000)
+              int propertyIndex =  _propertyRangeManager.GetPropertyIndex( viewName, viewType, scriptableProp.type );
+
+              // get the enum for the property type... E.g. registering a string property returns Dali.PropertyType.String
+              Dali.Property.Type propertyType = GetDaliPropertyType( propertyInfo.PropertyType.Name );
+
+              // Example   RegisterProperty("spin","maxValue", 50001, FLOAT, set, get );
+              // Native call to register the property
+              TypeRegistration.RegisterProperty (viewName, propertyInfo.Name , propertyIndex, propertyType, _setPropertyCallback, _getPropertyCallback);
+            }
+          }
+          // Console.WriteLine ("property name = " + propertyInfo.Name);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Get a property value from a View
+    ///
+    /// </summary>
+    private IntPtr GetPropertyValue ( IntPtr controlPtr, string propertyName)
+    {
+      // Get the C# control that maps to the C++ control
+      Dali.CustomView view;
+
+      BaseHandle baseHandle = new BaseHandle (controlPtr, false);
+
+      RefObject refObj = baseHandle.GetObjectPtr ();
+
+      IntPtr refObjectPtr = (IntPtr) RefObject.getCPtr(refObj);
+
+      if ( _controlMap.TryGetValue ( refObjectPtr, out view) )
+      {
+
+        // call the get property function
+        System.Object val = view.GetType ().GetProperty (propertyName).GetAccessors () [0].Invoke (view, null);
+
+        Property.Value value = Property.Value.CreateFromObject (val);
+
+        return (IntPtr)Property.Value.getCPtr (value);
+      }
+      else
+      {
+        return IntPtr.Zero;
+      }
+    }
+
+    /// <summary>
+    /// Set a property value on a View
+    ///
+    /// </summary>
+    private void SetPropertyValue ( IntPtr controlPtr, string propertyName, IntPtr propertyValuePtr)
+    {
+      // Get the C# control that maps to the C++ control
+      Dali.CustomView view;
+
+      //Console.WriteLine ("SetPropertyValue   refObjectPtr = {0:X}", controlPtr);
+
+      Property.Value propValue = new Property.Value (propertyValuePtr, false);
+
+      if ( _controlMap.TryGetValue ( controlPtr, out view) )
+      {
+
+        System.Reflection.PropertyInfo propertyInfo = view.GetType().GetProperty(propertyName);
+
+        // We know the property name, we know it's type, we just need to convert from a DALi property value to native C# type
+        System.Type type = propertyInfo.PropertyType;
+        bool ok = false;
+
+        if ( type.Equals (typeof(Int32)) )
+        {
+          int value = 0;
+          ok = propValue.Get( ref value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(bool)) )
+        {
+          bool value = false;
+          ok = propValue.Get( ref value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(float)) )
+        {
+          float value = 0;
+          ok = propValue.Get( ref value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(string)) )
+        {
+          string value = "";
+          ok = propValue.Get( out value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(Vector2)) )
+        {
+          Vector2 value = new Vector2 ();
+          ok = propValue.Get( value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(Vector3)) )
+        {
+          Vector3 value = new Vector3 ();
+          ok = propValue.Get( value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(Vector4)) )
+        {
+          Vector4 value = new Vector4 ();
+          ok = propValue.Get( value );
+
+          if ( ok )
+          {
+           propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(Position)) )
+        {
+          Position value = new Position ();
+          ok = propValue.Get( value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, value);
+          }
+        }
+        else if ( type.Equals (typeof(Size)) )
+        {
+          // DALi sizes are Vector3
+          Vector3 value = new Vector3();
+          ok = propValue.Get( value );
+          if ( ok )
+          {
+            propertyInfo.SetValue(view, new Size(value.X,value.Y));
+          };
+        }
+        else if ( type.Equals (typeof(Color)) )
+        {
+          // Colors are stored as Vector4's in DALi
+          Vector4 value = new Vector4();
+          ok = propValue.Get( value );
+          if ( ok )
+          {
+            propertyInfo.SetValue (view, (Color)value);
+          };
+        }
+        else
+        {
+          throw new global::System.InvalidOperationException("SetPropertyValue Unimplemented type for Property Value");
+        }
+        if ( !ok )
+        {
+          throw new global::System.InvalidOperationException("SetPropertyValue propValue.Get failed");
+        }
+      }
+      else
+      {
+        throw new global::System.InvalidOperationException("failed to find the control to write a property to: cptr = " + controlPtr);
+      }
+
+    }
+
+  }
+
+
+}
\ No newline at end of file
diff --git a/plugins/dali-swig/manual/csharp/ViewRegistryHelper.cs b/plugins/dali-swig/manual/csharp/ViewRegistryHelper.cs
new file mode 100644 (file)
index 0000000..8e9e19a
--- /dev/null
@@ -0,0 +1,15 @@
+using System;
+
+// include all custom views here which will be
+namespace Dali
+{
+  public class ViewRegistryHelper
+  {
+    static public void Initialize()
+    {
+       // Register all views with the type registry
+       System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (typeof(Dali.Spin).TypeHandle);
+    }
+  }
+}
+
diff --git a/plugins/dali-swig/views/spin.cs b/plugins/dali-swig/views/spin.cs
new file mode 100644 (file)
index 0000000..06a0210
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using Dali;
+
+// A spin control (for continously changing values when users can easily predict a set of values)
+
+namespace Dali
+{
+public class Spin : CustomView
+  {
+    private VisualBase _arrowVisual;
+    private TextField _textField;
+    private int _arrowVisualPropertyIndex;
+    private string _arrowImage;
+    private int _currentValue;
+    private int _minValue;
+    private int _maxValue;
+    private int _singleStep;
+    private bool _wrappingEnabled;
+    private string _fontFamily;
+    private string _fontStyle;
+    private int _pointSize;
+    private Color _textColor;
+    private Color _textBackgroundColor;
+    private int _maxTextLength;
+
+    // Called by DALi Builder if it finds a Spin control in a JSON file
+    static CustomView CreateInstance()
+    {
+      return new Spin();
+    }
+
+    // static constructor registers the control type (only runs once)
+    static Spin()
+    {
+      // ViewRegistry registers control type with DALi type registery
+      // also uses introspection to find any properties that need to be registered with type registry
+      ViewRegistry.Instance.Register("Spin", CreateInstance, typeof(Spin) );
+    }
+    public Spin() : base(ViewWrapperImpl.CustomViewBehaviour.REQUIRES_KEYBOARD_NAVIGATION_SUPPORT | ViewWrapperImpl.CustomViewBehaviour.DISABLE_STYLE_CHANGE_SIGNALS)
+    {
+
+    }
+
+    public override void OnInitialize()
+    {
+      // Initialize the propertiesControl
+      _arrowImage = "./images/arrow.png";
+      _textBackgroundColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
+      _currentValue = 0;
+      _minValue = 0;
+      _maxValue = 0;
+      _singleStep = 1;
+      _maxTextLength = 0;
+
+      // Create image visual for the arrow keys
+      _arrowVisualPropertyIndex = RegisterProperty("ArrowImage", new Dali.Property.Value(_arrowImage), Dali.Property.AccessMode.READ_WRITE);
+      _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
+      RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
+
+      // Create a text field
+      _textField = new TextField();
+      _textField.ParentOrigin = NDalic.ParentOriginCenter;
+      _textField.AnchorPoint = NDalic.AnchorPointCenter;
+      _textField.WidthResizePolicy = "SIZE_RELATIVE_TO_PARENT";
+      _textField.HeightResizePolicy = "SIZE_RELATIVE_TO_PARENT";
+      _textField.SizeModeFactor = new Vector3( 1.0f, 0.45f, 1.0f );
+      _textField.PlaceholderText = "----";
+      _textField.BackgroundColor = _textBackgroundColor;
+      _textField.HorizontalAlignment = "Center";
+      _textField.VerticalAlignment = "Center";
+      _textField.SetKeyboardFocusable(true);
+      _textField.Name = "_textField";
+
+      this.Add(_textField);
+
+      _textField.KeyInputFocusGained += TextFieldKeyInputFocusGained;
+      _textField.KeyInputFocusLost += TextFieldKeyInputFocusLost;
+    }
+
+    public override Vector3 GetNaturalSize()
+    {
+      return new Vector3(150.0f, 150.0f, 0.0f);
+    }
+
+    public void TextFieldKeyInputFocusGained(object source, KeyInputFocusGainedEventArgs e)
+    {
+      // Make sure when the current spin that takes input focus also takes the keyboard focus
+      // For example, when you tap the spin directly
+      FocusManager.Instance.SetCurrentFocusActor(_textField);
+    }
+
+    public void TextFieldKeyInputFocusLost(object source, KeyInputFocusLostEventArgs e)
+    {
+      int previousValue = _currentValue;
+
+      // If the input value is invalid, change it back to the previous valid value
+      if(int.TryParse(_textField.Text, out _currentValue))
+      {
+        if (_currentValue < _minValue || _currentValue > _maxValue)
+        {
+          _currentValue = previousValue;
+        }
+      }
+      else
+      {
+        _currentValue = previousValue;
+      }
+
+      // Otherwise take the new value
+      this.Value = _currentValue;
+    }
+
+    public override Actor GetNextKeyboardFocusableActor(Actor currentFocusedActor, View.KeyboardFocus.Direction direction, bool loopEnabled)
+    {
+      // Respond to Up/Down keys to change the value while keeping the current spin focused
+      Actor nextFocusedActor = currentFocusedActor;
+      if (direction == View.KeyboardFocus.Direction.UP)
+      {
+        this.Value += this.Step;
+        nextFocusedActor = _textField;
+      }
+      else if (direction == View.KeyboardFocus.Direction.DOWN)
+      {
+        this.Value -= this.Step;
+        nextFocusedActor = _textField;
+      }
+      else
+      {
+        // Return a native empty handle as nothing can be focused in the left or right
+        nextFocusedActor = new Actor();
+        nextFocusedActor.Reset();
+      }
+
+      return nextFocusedActor;
+    }
+
+
+    [ScriptableProperty()]
+    public int Value
+    {
+      get
+      {
+        return _currentValue;
+      }
+      set
+      {
+
+        Console.WriteLine ("Value set to "  + value );
+        _currentValue = value;
+
+        // Make sure no invalid value is accepted
+        if (_currentValue < _minValue)
+        {
+          _currentValue = _minValue;
+        }
+
+        if (_currentValue > _maxValue)
+        {
+          _currentValue = _maxValue;
+        }
+
+        _textField.Text = _currentValue.ToString();
+      }
+    }
+    // MinValue property of type int:
+    [ScriptableProperty()]
+    public int MinValue
+    {
+      get
+      {
+        return _minValue;
+      }
+      set
+      {
+        _minValue = value;
+      }
+    }
+
+    // MaxValue property of type int:
+    [ScriptableProperty()]
+    public int MaxValue
+    {
+      get
+      {
+        return _maxValue;
+      }
+      set
+      {
+        _maxValue = value;
+      }
+    }
+
+    // Step property of type int:
+    [ScriptableProperty()]
+    public int Step
+    {
+      get
+      {
+        return _singleStep;
+      }
+      set
+      {
+        _singleStep = value;
+      }
+    }
+
+    // WrappingEnabled property of type bool:
+    [ScriptableProperty()]
+    public bool WrappingEnabled
+    {
+      get
+      {
+        return _wrappingEnabled;
+      }
+      set
+      {
+        _wrappingEnabled = value;
+      }
+    }
+
+    // TextPointSize property of type int:
+    [ScriptableProperty()]
+    public int TextPointSize
+    {
+      get
+      {
+        return _pointSize;
+      }
+      set
+      {
+        _pointSize = value;
+        _textField.PointSize = _pointSize;
+      }
+    }
+
+    // TextColor property of type Color:
+    [ScriptableProperty()]
+    public Color TextColor
+    {
+      get
+      {
+        return _textColor;
+      }
+      set
+      {
+          Console.WriteLine ("TextColor set to "  + value.R + "," + value.G + ","+ value.B);
+
+        _textColor = value;
+        _textField.TextColor = _textColor;
+      }
+    }
+
+    // MaxTextLength property of type int:
+    [ScriptableProperty()]
+    public int MaxTextLength
+    {
+      get
+      {
+        return _maxTextLength;
+      }
+      set
+      {
+        _maxTextLength = value;
+        _textField.MaxLength = _maxTextLength;
+      }
+    }
+
+    public TextField SpinText
+    {
+      get
+      {
+        return _textField;
+      }
+      set
+      {
+        _textField = value;
+      }
+    }
+
+    // Indicator property of type string:
+    public string IndicatorImage
+    {
+      get
+      {
+        return _arrowImage;
+      }
+      set
+      {
+        _arrowImage = value;
+        _arrowVisual =  VisualFactory.Get().CreateVisual( _arrowImage, new Uint16Pair(150, 150) );
+        RegisterVisual( _arrowVisualPropertyIndex, _arrowVisual );
+      }
+  }
+}
+}
\ No newline at end of file