Howto:Canvas dialog examples: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
(new page)
 
mNo edit summary
Line 6: Line 6:
=== Introduction ===
=== Introduction ===
This dialog is the 'front end' of the extra500 failure system. It uses Canvas only and has several pages and interactive elements. All pages are .svg designed.
This dialog is the 'front end' of the extra500 failure system. It uses Canvas only and has several pages and interactive elements. All pages are .svg designed.
We will look at the code and try to explain what is does. It focuses on nasal - canvas interaction only.
We will look at the code and try to explain what is does.  
 
The dialog is set-up like a normal nasal namespace:
<nasal>
    <Dialogs>
      <file>Aircraft/extra500/Dialogs/failuredialog.nas</file>
    </Dialogs>
</nasal>.
 
And called (opened) though a menu entry in /Dialogs/extra500-menu.xml just like any other classical menu entry.
<item>
  <name>Failure-dialog</name>
  <label>Failure Dialog</label>
  <binding>
      <command>nasal</command>
      <script><![CDATA[
        Dialogs.Failuredialog.openDialog();
      ]]></script>
  </binding>
</item>
 
This means there needs to be a loaded Class called failuredialog with an internal function called openDialog.


=== File structure ===
=== File structure ===

Revision as of 17:59, 22 October 2017

This page is for Canvas dialog Examples and their explanations. At the moment it has 1:

Extra500 failure dialog

Introduction

This dialog is the 'front end' of the extra500 failure system. It uses Canvas only and has several pages and interactive elements. All pages are .svg designed. We will look at the code and try to explain what is does.

The dialog is set-up like a normal nasal namespace:

<nasal>
   <Dialogs>
     <file>Aircraft/extra500/Dialogs/failuredialog.nas</file>
   </Dialogs>
</nasal>.

And called (opened) though a menu entry in /Dialogs/extra500-menu.xml just like any other classical menu entry.

<item>
  <name>Failure-dialog</name>
  <label>Failure Dialog</label>
  <binding>
     <command>nasal</command>
     <script><![CDATA[
        Dialogs.Failuredialog.openDialog();
     ]]></script>
  </binding>
</item>

This means there needs to be a loaded Class called failuredialog with an internal function called openDialog.

File structure

The file is located in the /extra500/Dialog folder and is called failuredialog.nas After the license part, it starts up with defining a vector that basically holds all the colors of the .svg elements that are changed. The color definition, for instance "#00ff004a" is used in the .svg files directly and can be looked up in Inkscape or any other .svg file editor. The rest holds the definition of "FailureClass{}" and in the end of the file, one instance of this Class is invoked:

var FailureClass = {
...
...
};
var Failuredialog = FailureClass.new();

Other files used are the .svg files, which are located in the same folder. We will be looking at the MenuFaildialog.svg and GearFaildialog.svg files in this example.

FailureClass.new

With the last line of code above, we invoke the following:

new : func(){
 var m = {parents:[FailureClass]};
 m._title = 'Extra500 Failure Dialog';
 m._gfd 	= nil;
 m._canvas	= nil;
 m._timer 	= maketimer(1.0,m,FailureClass._timerf );
 return m;
},

So we make the Class, set a title, make a canvas and even set a timer. In principle nothing happens except in the background the Class is set up.

openDialog

The next function hold all the things we want to do if we open the window. We are making the window:

me._gfd = MyWindow.new([750,512],"dialog");
me._gfd._onClose = func(){Failuredialog._onClose();}
me._gfd.set('title',me._title);
me._canvas = me._gfd.createCanvas().set("background", canvas.style.getColor("bg_color"));
me._root = me._canvas.createGroup();

After this we pre-load all the .svg files. This is not necessary, but a design choice. It makes the switching between window tabs faster (as you don't need to load the .svg every time). Another design choice is that each page in the dialog has its own .svg file. This is not necessary, but we found it a bit more structured.

me._filename = "/Dialogs/MenuFaildialog.svg";
me._svg_menu = me._root.createChild('group');
canvas.parsesvg(me._svg_menu, me._filename);

The first line point to where the .svg is located, the second sets up a group and gives it a name. And finally the .svg is parsed (loaded) and linked to the group name. In this example we will only look at the "menu" and the "gear" tab. Their names are: me._svg_menu and me._svg_gear respectively.

In the next section all the elements from the individual .svg files are linked, declared and named. This is only necessary for elements which actually do something. Like you want to make it interactive (click on it) or change its color or hide it etc. etc.

So for the menu we have the gear tab which has 2 elements:

  • A colored field (of which we will change the color): me._gear
  • A text field (which just sits there and does nothing, so we won't declare it)
  • A field that indicates if there is an active failure on the gear: me._gear_active
me._gear = me._svg_menu.getElementById("field_gear");
me._gear_active = me._svg_menu.getElementById("gear_active").hide();

So the elements in the .svg file are declared and linked to their names. "field_gear" and "gear_active" are the element ID-s as set in Inkscape (Object - Object Properties). Note that the gear_active field is set invisible at startup by using .hide() at the end.

For the gear page, we do the same:

me._LHgear = me._svg_gear.getElementById("LHgear");
etc.

Here the .svg element "LHgear" of the parsed .svg file called me._svg_gear is linked to the name me._LHgear. This enables us to do all kind of things to it like hiding, showing, change color etc. This is both true for complete parsed .svg files as their elements

For instance, a bit further down in the file:

 me._svg_menu.show();

Which shows the menu page.

Listeners: things are happening

Now we can add (event-)listeners to the different elements in the setListeners function:

 me._gear.addEventListener("click",func(){me._onGearClick();});

Here we tell to execute the function me._onGearClick() when the element me._gear is clicked. We can do this for all declared elements:

me._LHgear.addEventListener("click",func(){me._onGeneralClick("/systems/gear/LMG-free",0,"LMG_jammed","gear");});

This one looks a bit more complicated, but the principle is the same. The function me._onGeneralClick just gets some arguments passed to it.

Operations

Let us look at some operations. For instance in the _onGearClick() function. One of the lines is:

me._gear.setColorFill(COLORfd["menuse"]);

Here we set the color of element me._gear to COLORfd["menuse"]. This is a defined in the vector at the beginning of the file and is color "#0055d432".

Another line is:

me._svg_gear.show();

Which makes the gear page visible. The opposite is .hide()

The structure of the dialog is pretty complicated, but is all just logical nasal stuff and has nothing to do with the canvas - nasal interaction.