Howto:Canvas dialog examples: Difference between revisions

Jump to navigation Jump to search
m
cat: Canvas GUI
mNo edit summary
m (cat: Canvas GUI)
(6 intermediate revisions by 2 users not shown)
Line 2: Line 2:
At the moment it has 1:
At the moment it has 1:
* [[Extra EA-500/failure dialog|Extra500 Failure Dialog]]
* [[Extra EA-500/failure dialog|Extra500 Failure Dialog]]
[[File:Extra500-Failuredialog-fuel.png|500px|right|Extra 500 - failure dialog - Fuel]]


== Extra500 failure dialog ==
== Extra500 failure dialog ==
Line 8: Line 10:
We will look at the code and try to explain what is does.  
We will look at the code and try to explain what is does.  


The dialog is set-up like a normal nasal namespace:
* Setting up the namespace "Dialogs"
<nasal>
* Making a menu entry for the dialog
* Setting up a class and making one instance of it
* Setting up the Canvas
* What to do when opening the dialog like:
# Making the window (frame)
# Creating a canvas group related to that window frame
# Parsing (and displaying) .svg files
# Linking elements of the .svg file to the canvas group (giving them a name so we can change them)
# Initiate the listeners to make certain elements interactive
* Making the listeners and linking them to canvas/.svg elements (howto make clicking on it make it do something) 
 
=== Namespace and Menu entry ===
The dialog is set-up like a normal nasal namespace in the  -set file:
<syntaxhighlight lang="xml">
<nasal>
     <Dialogs>
     <Dialogs>
       <file>Aircraft/extra500/Dialogs/failuredialog.nas</file>
       <file>Aircraft/extra500/Dialogs/failuredialog.nas</file>
     </Dialogs>
     </Dialogs>
</nasal>.
</nasal>
</syntaxhighlight>


And called (opened) though a menu entry in /Dialogs/extra500-menu.xml just like any other classical menu entry.
And called (opened) though a menu entry in /Dialogs/extra500-menu.xml just like any other classical menu entry.
<item>
<syntaxhighlight lang="xml">
<item>
   <name>Failure-dialog</name>
   <name>Failure-dialog</name>
   <label>Failure Dialog</label>
   <label>Failure Dialog</label>
Line 25: Line 43:
       ]]></script>
       ]]></script>
   </binding>
   </binding>
</item>
</item>
</syntaxhighlight>


This means there needs to be a loaded Class called failuredialog with an internal function called openDialog.
This means there needs to be a loaded Class called "Failuredialog" in the namespace "Dialogs" with an internal function called "openDialog".


=== File structure ===
=== File structure ===
Line 39: Line 58:
  };
  };
  var Failuredialog = FailureClass.new();
  var Failuredialog = FailureClass.new();
Thus now we created Dialogs.Failuredialog and the internal functions as defined in the FailureClass Class. We are calling the internal function "new" at initialization.
All the internal functions can be called using Dialog.Failuredialog.<InternalFunctionName>


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.
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.
Line 45: Line 67:
With the last line of code above, we invoke the following:
With the last line of code above, we invoke the following:


new : func(){
<syntaxhighlight lang="javascript">
new : func(){
   var m = {parents:[FailureClass]};
   var m = {parents:[FailureClass]};
   m._title = 'Extra500 Failure Dialog';
   m._title = 'Extra500 Failure Dialog';
Line 53: Line 76:
   return m;
   return m;
  },
  },
</syntaxhighlight>


So we make the Class, set a title, make a canvas and even set a timer.
So we make the Class, set a title, make a canvas and even set a timer.
Line 59: Line 83:
=== openDialog ===
=== openDialog ===
The next function hold all the things we want to do if we open the window.
The next function hold all the things we want to do if we open the window.
We are making the window:  
We are making the (empty) window:  


  me._gfd = MyWindow.new([750,512],"dialog");
  me._gfd = MyWindow.new([750,512],"dialog");
Line 78: Line 102:
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 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.
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:
So for the menu we have the gear tab which has 3 elements:
* A colored field (of which we will change the color): me._gear
* 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 text field (which just sits there and does nothing, so we won't declare it)
Line 102: Line 126:


Which shows the menu page.
Which shows the menu page.
So we can show or hide whole pages (individual parsed .svg-s) with .show() and .hide() respectively.
We also initiate all listeners here:
me.setListeners(instance = me);
Which happens in the setListeners function.


=== Listeners: things are happening ===
=== Listeners: things are happening ===
Line 112: Line 141:


This one looks a bit more complicated, but the principle is the same. The function me._onGeneralClick just gets some arguments passed to it.
This one looks a bit more complicated, but the principle is the same. The function me._onGeneralClick just gets some arguments passed to it.
You can replace "click" with "wheel" or "drag" in your listener for mouse-wheel or mouse-dragging operation.
For "wheel" and "drag" you will need to pass on the amount you want to change like so:
me._fielddelay.addEventListener("wheel",func(e){me._onRandomDelayChange(e);});
and the function that is called:
_onRandomDelayChange : func(e){
  var delay = getprop("/extra500/failurescenarios/randommaxdelay") + e.deltaY;
  delay = math.clamp(delay,0,60);
  setprop("/extra500/failurescenarios/randommaxdelay",delay);
  me._welcome_update();
},


=== Operations ===
=== Operations ===
Line 122: Line 161:
Which makes the gear page visible. The opposite is .hide()
Which makes the gear page visible. The opposite is .hide()


=== Dialog design ===
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.
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.
In principle, all pages are parsed separately so they can be turned on and off easily. In general, when a tab is pressed, all pages are hidden (except for the menu) and the proper page shown. 
<syntaxhighlight lang="javascript">
_onGearClick : func() {
  me._menuReset();
  me._gear.setColorFill(COLORfd["menuse"]);
  me._frame.setColorFill(COLORfd["menuse"]);
  me._hideAll();
  me._svg_lmenu.show();
  me._gear_active.show();
  me._svg_gear.show();
  me._gearButtons_update();
},
</syntaxhighlight>
This happens when the GEAR tab in the menu is pressed. The menu is re-setted and then the gear tab is changed color to indicate it is selected.
All the other pages are hidden, the gear page is show and finally all gear-buttons are updated. The status of the buttons depends on fg-properties. They have no listeners, but are only updated when the page is show. This is a bit easier and saves a lot of listeners. The disadvantage is that the buttons (they change color when a pressed and a failure is initiated) are not updated automatically. Maybe not ideal for a 'front end'...
[[Category:Canvas GUI]]

Navigation menu