New in version 0.9.8

Released one year ago

Please remember to uno clean your projects after upgrading Fuse.

Highlights

  • Build output directory changed from .build to build (see "New project build directory defaults")
  • Introducing foreign code blocks in Uno
  • Introducing ux:Include
  • Improved ux:Property support
  • V8 JavaScript engine is now used in local preview and all local builds
  • Lots of fixes and improvements to triggers and animators (See for instance WhileInteracting and Timeline)
  • Lots of new project properties for iOS
  • New APK launcher with improved error messages, and that prints relevant logcat from device
  • Fixed case where android platform 19 was not installed (which resulted in platform target 19 not found error)
  • Fixed several bugs related to spaces in paths or names
Introducing foreign code blocks

Uno methods marked with the [Foreign(Language.LANGAGE)] attribute, where LANGUAGE is ObjC or Java, can contain code written in the foreign language by specifying the body inside alpha braces, @{ ...@}, e.g.:

[Foreign(Language.Java)]
void Foo()
@{
    System.out.println("Hello, World");
@}

Foreign functions automatically convert the arguments and return value from their Uno representation to a corresponding foreign language representation. Primitive types (int, char, float, etc) are converted to the corresponding primitive type in the foreign language. Other types are automatically converted in both directions according to the following tables:

Uno Java
string String
Java.Object Object
object UnoObject
Uno Objective-C
string NSString*
ObjC.Object id
object id<UnoObject>

UXL macros such as Call (@{Type:Of(thing).Method(argTypes):Call(args)}), Set, and Get can be used to call back to Uno code from the foreign code block with reversed type conversions.

If the foreign method is an instance method, the foreign code block can additionally access the wrapped this object in the automatically added _this parameter.

To avoid having to use extension files at all in the common case, you can now specify [Require("Key", "Value")] as attributes on Uno classes and methods in place of specifying <Require Key="Value" /> in a separate extensions file.

The uObjC.Reference.h header, used by some for low-level Objective-C interop, has been renamed to uObjC.UnoObject.h. The classes in it have also been renamed: Uno_Reference is now UnoObject and Uno_{Strong,Weak,Unsafe}Reference are now {Strong,Weak,Unsafe}UnoObject.

Changes to project format

In relation to foreign code blocks, some additions has been made to the .unoproj file format.

Native source files can now be included using the file types CSource, CHeader, and Java. This replaces using the file type File and specifying <ProcessFile {Header,Source}File="filename" /> in an extensions file.

An include condition can be speficied to avoid including files on platforms where they are not supported:

"Includes": [
    "file.ext:FileType:CONDITION"
]

Useful pre-defined values for CONDITION include Android and iOS.

Improved extern code

Even before the introduction of foreign code, interop with native C/C++ libraries from Uno could be done using the extern keyword. This release improves upon that feature by introducing extern blocks:

int arg = 10;
extern (arg)
@{
    printf("%d", $ 0);
@}

When only access to method arguments is needed, the extern header can be omitted

void foo(int arg)
...
@{
    printf("%d", $ 0);
@}
Introducing ux:Include

The new UX syntax <ux:Include File="Foo.ux" /> will insert the contents of another UX file at the given location. This makes it easier to split large UX components into separate files.

Breaking change! UX markup files with no ux:Class on the root node no longer produce a class based on the file name. You have to explicitly set a class name on the file's root node (ux:Class="ClassName"). The UX compiler will politely tell you how to fix this in a compile-time error message.

Improved ux:Property support

Several bugs related to ux:Property has been fixed, both in preview and when running exported.

In addition, nodes marked with ux:Property no longer represents the default value, but just a definition of the property. You can still specify a default value the same way you set other properties in a ux:Class definition, e.g.:

<Panel ux:Class="MyPanel" ux:Name="self" Paint="#f00">
    <Brush ux:Property="Paint"/>
    <Rectangle Fill="{Property self.Paint}"/>
</Panel>

<MyPanel Paint="#00f" />

You can also use ux:Binding to set a complex object as default value:

<Panel ux:Class="MyPanel" ux:Name="self" >
    <Brush ux:Property="Paint"/>

    <LinearGradient ux:Binding="Paint">
        <GradientStop Offset="0" Color="#f00" />
        <GradientStop Offset="1" Color="#0f0" />
    </LinearGradient>

    <Rectangle Fill="{Property self.Paint}"/>
</Panel>

Note that for {Property self.Paint} to work, the declared property type has to exactly match the type where it is used (Brush).

V8 all the things!

We now use V8 as JavaScript engine on both OS X and Windows for local preview builds, DotNet builds, CMake builds, and MSVC builds. The V8 library has also been updated to version 4.8.271.9.

One of the benefits of using V8 is the debugger, which can be enabled using the -DDEBUG_V8 build flag. See the debugging guide for more information on how to use it.

New default build directories

All builds are now placed within the "build/" subfolder of your project by default, instead of ".build/" for builds and ".preview/" for preview. Remember to update your .gitignores!

The reason for this is that the old build directory starting with a . gets hidden by default in OS X, causing some confusion. E.g. when you want to open the build output in another program that doesn't support showing hidden files, the non-dotted directory is now much easier to find.

If this cause trouble, you can pass --out-dir to uno build to override, or configure your project using these old settings:

"BuildDirectory": ".build",
"CacheDirectory": ".cache",
"OutputDirectory": "$(BuildDirectory)/@(Target)-@(Configuration)"

This will, however, not have an effect on fuse preview.

Changes to Timeline element
  • Timeline will now use a backwards animation when playing backwards
  • TriggerAnimation.CrossFadeDuration (via Trigger.CrossFadeDuration) allows changin the duration of the cross-fade between forward/backward animations on direction switches
  • Timeline is now "active" at Progress=0. This allows animators to have an effect even at this progress -- on other triggers the animators are essentially removed when the Progress==0.
  • Timeline.PlayMode added with the option of Wrap to loop the timeline
  • Progress at rooting time can now be set using the Timeline.InitialProgress property
  • Timeline.Progress is now a two-way bindable value
  • Pulse.Target is now an IPulseTrigger allowing more items to be pulsed, such as Timeline
Changes to Cycle element
  • The properties Cycle.IsZeroCrossing and Cycle.IsOneCrossing have been made internal (they were not meant to be public)
  • The new property Cycle.ProgressOffset allows specifying the offset instead of taking the auto-calculated one. This may result in jerky animations on starting/stopping a trigger.
  • The new property Cycle.Easing allows an easing funtion to be applied to the progress. This disables the auto-calculated ProgressOffset and may reuslt in jerky starting/stopping.
Other API changes and improvements
  • A new trigger called WhileInteracting has been added. This trigger is active while the user is swiping in a SwipeGesture or scrolling in a ScrollView.
  • IsInteracting has been moved up from Control to Element
  • Swipe.IsActiveChanged is now of type ValueChangedHandler<bool>. SetValue renamed to SetIsActive. 2-way data binding enabled.
  • The swipe length of a SwipeNavigate element can now be taken from another element using the new LengthNode property
  • SwipeNavigate now has an optional property MaxPages that limits how many pages can be swiped with a single gesture
  • The method you've probably never heard about LayoutParams.Clone() has been split into TrueClone() and DeriveClone(). Contact @mortoray to find out which new method is suitable for you (The answer might surprise you!)
  • DrawContext.Current has been removed, calls to draw with DefaultShading must now specify the DrawContext meta-property
  • Video.ValueChanged has been removed, use Video.ProgressChanged instead
  • Stroke.StrokeAlignment has been renamed to Stroke.Alignment
  • Element now has an Aspect property, specifying the aspect for BoxSizing="FillAspect".

    This sizes the element based the avaialble size provided to it from its parent. The size of the content of this element is not considered in the sizing. For instance, this creates a square panel that is 20% the width of its parent:

      <Panel Width="20%" Aspect="1" BoxSizing="FillAspect"/>
    
  • DockPanel now support children specifying sizes (using %) relative to the entire container. This is a change from previously where such specifying a relative size on a child of a DockPanel would be equal to setting the property to 0.

    Note this also applies to items with Dock="Fill" (which is default). So if you previously used that to size relative to the remaining space you will have to wrap that in a Panel first to establish the new relative basis. For example:

      <DockPanel>
          ...
          <Panel Width="50%">...
    

    Becomes

      <DockPanel>
          <Panel><Panel Width="50%">...
    
Changes to the layout system
  • DefaultLayout no longer does two-pass sizing, only the maximum size of the first pass will be used to report its size. The previous two-pass was not numerically stable (each pass could produce larger and larger results, thus making 2 passes no better than 1)
  • StackLayout no longer does two-pass sizing by default. While there are scenarios where it can be required it doesn't come up often and it has a significant cost associated with it. If an element of your StackPanel (possibly the background) no longer has the correct size you can enable the two-pass mode with Mode="TwoPass".
  • In some situations if a Width and Height were specified on an element the Max/Min values would be ignored, thus allowing the element to violate those constraints. This has been fixed.
  • Node.GetMarginSize has a new signature float2 GetMarginSize(LayoutParams lp). The previous avilableSize is the Size property of that object, and the HasX and HasY property can be used to check for their existence.
  • Node.ArrangeMarginBox has a new signature float2 ArrangeMarginBox(float2 position, LayoutParams lp) as does OnArrangeMarginBox. This matches the change made to GetMarginSize.
  • The layout engine no longer does a second pass when enforcing Min/Max properties, it simply constrains the size. Elements that need to adapt based on the max/min must do so during the initial sizing request, as Image and Text now do. The LayoutParams has the maximum and minimum information inside it.
  • SizeFlags is removed, the user of LayoutParams removes the need for it

Layout now also makes a couple of assumptions:

  • SnapToPixels is expected to work only if all parent nodes/elements have this enabled as well. (At the moment it may still work without, but this is expected to change)
  • The arrangement of a node may not be dependent on its position, but only its size. So a 100x100 element has the exact same arrange at 50,75 as it does at 5,7. This is to support an optimal layout system of panels where the position may not be known before the size.
Improved iOS build customization

A few new iOS-specific attributes has been added to the project format:

"iOS": {
    "BundleIdentifier": "com.uno.$(Name)",
    "BundleName": "$(Title)",
    "DeploymentTarget": "7.0",
     "PList": {
        "MKDirectionsApplicationSupportedModes": [
            "MKDirectionsModeCar",
            "MKDirectionsModeBus",
        ],
        "UIRequiresPersistentWiFi": true,
        "UIRequiredDeviceCapabilities": [
            "camera-flash"
        ]
    },
},

The following plist property keys are currently supported: UIRequiredDeviceCapabilities, MKDirectionsApplicationSupportedModes, NSHealthShareUsageDescription, NSHealthUpdateUsageDescription, UIApplicationExitsOnSuspend, UIFileSharingEnabled, UINewsstandApp, UIPrerenderedIcon, UIRequiresPersistentWiFi, UISupportedExternalAccessoryProtocols, UIViewControllerBasedStatusBarAppearance, and UIViewEdgeAntialiasing.

A new UXL element called Xcode.EmbeddedFramework has been added for adding embedded frameworks to the generated Xcode project.

Absolute paths to frameworks in Xcode.Framework elements are now allowed. This means that the following ways to include frameworks are accepted:

<Require Xcode.Framework="some.framework" /> <!-- relative to SDKROOT/System/Library/Frameworks/ as before -->
<Require Xcode.Framework="/path/to/some.framework" /> <!-- absolute path -->
<Require Xcode.Framework="@('some.framework':Path)" /> <!-- relative to UXL file -->

The .framework extension is optional and will be added automatically if omitted.

Improved Android support

Uno projects can now be opened in Android Studio, making it easier to debug native code on device. Type uno build android --debug to launch Android Studio directly from the command line. Tested using Android Studio version 1.5 which can be downloaded from here: http://developer.android.com/tools/studio/index.html

  • New project structure

    In order to support Android Studio, we had to adapt to the new "Gradle" project structure, involving moving files around in the generated project. AndroidManifest.xml for example, can be found under @(Project.Name)/app/src/main instead of in the root output directory. Java source files are written to @(Project.Name)/app/src/main/java instead of src. Use the @(Java.SourceDirectory) macro to refer to the java source directory.

  • New APK launcher

    Some Windows users has been getting stuck on "Uninstalling APK" when trying to deploy APKs. This is usually because "Developer Mode" isn't enabled on the device, missing USB drivers, or the device is not properly connected. The new APK launcher is now able to print a better error message and terminate, instead of getting stuck.

    The new launcher will also print logcat output from the device while app is running.

    See uno launch-apk -h for more. You can pass launch-apk options through uno build android -a"OPTIONS".

  • Added ADB wrapper

    You can use uno adb [args] if you need to run adb from the Android SDK without adding "platform-tools" to PATH.

  • Added Android SDK Manager wrapper

    You can use uno android if you need to open the Android SDK Manager.

  • Improved "space support", so Android users can enjoy...

    • ...projects containing spaces in the name
    • ...projects containing spaces in the path
    • ...Android SDK and NDK installed in a location containing spaces in the path
  • New Uno project settings for SDK configuration

    If you have specific requirements regarding SDK, you can now control those with the following properties:

      "Android": {
        "NDK": {
          "PlatformVersion": null     // default: 9
        },
        "SDK": {
          "BuildToolsVersion": null,  // default: 23.0.0
          "CompileVersion": null,     // default: 19
          "MinVersion": null,         // default: 10
          "TargetVersion": null       // default: 19
        }
      },
    

    We do however recommend to keep null for automatic detection of settings based on the current SDK installed on the build machine (fuse install android).

  • Fixed a problem causing mkdir to sometimes fail on Windows

  • Updated native compilers to GCC 4.9
Uno command line interface changes
  • The following targets were renamed, but you can still use the old name:

    New name Old name
    MSVC MSVC12
    DotNet DotNetExe
  • The --debug argument is supported by the following targets:

    Build target Action
    Android Opens Android Studio
    CMake Opens Xcode (OS X only)
    iOS Opens Xcode (OS X only)
    MSVC Opens Visual Studio 2013 (Windows only)

    If the project is already open in an IDE/debugger, we won't open any additional windows. You can use --debug as often as you want without being worried about getting spammed by new windows.

    --debug will disable the native compile step in Uno, and enable native debugging, so that you can build and debug from the IDE. Otherwise --debug is short hand for --run-args=debug, and will pass debug as an argument to the run script. This may fail without error if used on an unsupported build target.

  • Specify target without --target

    For example, to build for Android:

      uno build android
    
  • Added new shorthand arguments:

    • -N -> --no-native (Disable native compile step)
    • -S -> --no-strip (Disable removal of unused code)
    • -d -> --debug (Open IDE for debugging)
  • C++ debugging flags can be passed on the command line:

    • -DDEBUG_UNSAFE (Enable asserts in unsafe code)
    • -DDEBUG_ARC1..4 (Print debug info from memory manager)
    • -DDEBUG_DUMPS (Dumps object graphs to disk for analysis)
UXL changes
  • New macro operators

    Macro Input Output
    @(FOO:EscapeSpace) foo bar foo\ bar
    @(FOO:QuoteSpace) foo bar "foo bar"
  • Tolerant XML syntax

    The UXL parser is able to handle attributes and inner text containing non-encoded XML entities. Quotes are optional on simple attribute values, such as numbers and booleans. For example, this is now accepted by the parser:

      <Define UNIX />
      <Set Foo=1 Condition="FOO && BAR" />
      <Expression>a < b</Expression>
      <Expression>a < b</Expression>
    

    Instead of, compared to strict XML:

      <Define UNIX="UNIX" />
      <Set Foo="1" Condition="FOO && BAR" />
      <Expression><![DATA[a < b]]></Expression>
      <Expression>a < b</Expression>