Missing Class and File semantics

Hi,

Thanks for putting Fusetools together, I think it’s great.

If I may add my 2cents, it might miss some class and files semantics as projects go slightly bigger than the examples. Examples which I think are great by the way. Let me try to explain myself.

I have tried the Signup Concept and the Rotating Slide Bar examples, and am now trying to merge both (because I want to build on these two samples). I have started with a page control as such:

     <PageControl>
        <Page ux:Name="LoginPage">
            <LoginPanel />
        </Page>
        <Page ux:Name="HomePage">
             <HomePanel />
        </Page>
    </PageControl>

I think what is missing in Fuse is the fundamentals as to “What is a class?” and “How classes in projects files relate?”.

In my new project, I have merged the two project files, and renamed the Signup main view to LoginView. On the click of the “Signup” button, I’m trying to display the other “Page” from the Rotating Slide Bar example. Projet which I’ll gladly attach, but above this, I get these error messages:

MainView.ux(1): E8001: You cannot ux:Include the file 'LoginView.ux' because it's root node is marked with ux:Class. You can instantiate the class with <LoginPanel /> instead. LoginView.ux(57): E8001: 'HomePage' declared in MainView.ux(202) is a member 'MainView' and cannot be accessed from 'LoginPanel'. To make this work, consider making 'LoginPanel' an ux:InnerClass of 'MainView'. RotatingSidebar: E0000: Object reference not set to an instance of an object Build ended fuse: Failed to compile project

Ok, I created a class in its own file but what could be possibly wrong with doing this? It seems like a great practice. Now, having no ux:Class makes it impossible to reach from another file?!?

I tried to include it making it an inner class:

<ux:Include File="LoginView.ux" />

It compiles, but the runtime gives the following error message:

Preview detected an unhandled exception: Outracks.Simulator.Runtime.VariableNotBound: Element '5#' was referenced before it was initialized at Outracks.Simulator.Runtime.Environment.GetValue (Outracks.Simulator.Bytecode.Variable variable) [0x00000] in <filename unknown>:0 at Outracks.Simulator.Runtime.Environment.GetValue (Outracks.Simulator.Bytecode.Variable variable) [0x00000] in <filename unknown>:0

The thought I have after seing these is the following. After some 20 years of doing Java software development, I have started looking at many other platforms. There’s one thing that Java is quite solid at, and it’s large size projects. I have to admit that the concept of class/inner class/files is well rounded up there and it’s worth being being inspired from.

In fuse, I wish these rules were clearer. If I instantiate a class at the root level of a file, I should be able to use it in another. Or why should I have to declare a class as us:InnerClass, a class defined within another is inner (or what else could it be I’m wondering). I should be able to navigate to the class of panel, regardless in which file is was defined…

That said, what you give have done is great but the classes/object instantiation aspect of fusetools needs some love.

Cheers, keep up the solid work.

Hi!

There is nothing wrong with putting a ux:Class in its own file. The error is saying that you cannot use ux:Include on a file wich has a ux:Class definition as its root node and that is because ux:Include basically just copies the text of a file inline.

This is not needed when you have the ux:Class definition because it will be available globally.

The following is completly valid (and considered good practice).

Foo.ux:

<Panel ux:Class="FooClass" />

MainView.ux

<App Theme="Basic">
    <FooClass />
</App>

There are of course cases where this is not sufficient. In the case where your ux:Class definition tries to access a name outside of its own scope. Like in the following case:

Foo.ux:

<Panel ux:Class="FooClass">
    <Clicked>
        <Change mainPanel.Color="#f00" /> <!-- mainPanel is a part of MainView.ux -->
    </Clicked>
</Panel>

MainView.ux

<App Theme="Basic">
    <Panel ux:Name="mainPanel">
        <FooClass />
    </Panel>
</App>

In this case, FooClass won’t have access to mainPanel, since it is defined as a ux:Class.

However, you can change this to ux:InnerClass, which means that this class has access to the scope it is defined in. This also means that ux:InnerClass definitions can only be instantiated inside the scope they are defined in.

This is where <ux:Include/> comes in. If you define a ux:InnerClass in its own file, it doesn’t know what scope it is defined in. To make this case work, you can ux:Include the file in the scope you want the ux:InnerClass to be defined in:

Foo.ux:

<Panel ux:InnerClass="FooClass">
    <Clicked>
        <Change mainPanel.Color="#f00" />
    </Clicked>
</Panel>

MainView.ux

<App Theme="Basic">
    <Panel ux:Name="mainPanel">
        <ux:Include File="Foo.ux" /><!-- this is just makes the definition of FooClass available in MainView -->
        <FooClass /><!-- we also have to create the instance the above is just the inner class definition -->
    </Panel>
</App>

I hope this makes things a bit clarer.

Thanks. I’m working more at this. Cheers.

Would be nice if this was an attribute on the component that holds the ux:InnerClass

<FooClass  ux:IncludeFile="Foo.ux" />

@tim: no, not really. The code above is somewhat outdated, too.

We now have Dependencies for dependency injection, and InnerClass is not a recommended best practice any more.