aclocal.m4
config/
config.*
-cpp/dali_wrap.cpp
-cpp/dali_wrap.h
+automatic/*
configure
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
%ignore *::AnchorPoint::DEFAULT;
%ignore *::SetPositionInheritanceMode(PositionInheritanceMode);
%ignore *::GetKeyValue(SizeType) const;
+%ignore *::TypeInfo::GetCreator() const;
%rename(ParentOriginTop) Dali::ParentOrigin::TOP;
%rename(ParentOriginBottom) Dali::ParentOrigin::BOTTOM;
%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>
#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&);
%include alphafunction.i
%include name-changed.i
-
+%include property-value.i
%include dali-operator.i
%include dali-core.i
%include dali-adaptor.i
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();
}
}
+ ///
+ 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
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#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
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+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 ();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+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 ();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+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 ();
+ }
+ }
+}
--- /dev/null
+/*
+ * 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]
+ }
+ }]
+
+ }
+}
+
+}
+
--- /dev/null
+/*
+ * 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]
+ }
+ }]
+
+}]
+
+}
+
--- /dev/null
+/*
+ * 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
+ }
+
+ ]
+}
+++ /dev/null
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-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 ();
- }
- }
-}
--- /dev/null
+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
+ };
+
+
+
+}
+}
--- /dev/null
+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
--- /dev/null
+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);
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+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