Howto:Adding a canvas to a GUI dialog: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
mNo edit summary
Line 9: Line 9:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<canvas>
<canvas>
              <name>fgplot</name>
  <name>fgplot</name>
              <valign>fill</valign>
  <valign>fill</valign>
              <halign>fill</halign>
  <halign>fill</halign>
              <stretch>true</stretch>
  <stretch>true</stretch>
              <pref-width>600</pref-width>
  <pref-width>600</pref-width>
              <pref-height>400</pref-height>
  <pref-height>400</pref-height>
<nasal>       
  <nasal>       
<!--  
  <!--  
    this is the Canvas-specific Nasal section where you can run your own Nasal code  
      this is the Canvas-specific Nasal section where you can run your own Nasal code  
    to access the canvas region
      to access the canvas region
-->
  -->
<load><![CDATA[
    <load>
 
      <![CDATA[
# you can add your canvas-specific code here
     
var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas :
              # you can add your canvas-specific code here
              var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas :


print("Hello world from the embedded canvas section!\n");
              print("Hello world from the embedded canvas section!\n");


]]></load>
      ]]>
</nasal>
    </load>
  </nasal>
</canvas>
</canvas>
</syntaxhighlight>
</syntaxhighlight>
Line 59: Line 61:
     <empty><stretch>true</stretch></empty>
     <empty><stretch>true</stretch></empty>


<canvas>
    <canvas>
              <name>fgplot</name>
      <name>fgplot</name>
              <valign>fill</valign>
      <valign>fill</valign>
              <halign>fill</halign>
      <halign>fill</halign>
              <stretch>true</stretch>
      <stretch>true</stretch>
              <pref-width>600</pref-width>
      <pref-width>600</pref-width>
              <pref-height>400</pref-height>
      <pref-height>400</pref-height>
<nasal>       
      <nasal>       
<!--  
      <!--
    this is the Nasal/canvas section where you can run your own Nasal code  
          this is the Nasal/canvas section where you can run your own Nasal code  
    to access the canvas section  
          to access the canvas section  
-->
      -->
<load><![CDATA[
        <load>
# you can add your canvas-specific code here
          <![CDATA[
var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas:
                  # you can add your canvas-specific code here
 
                  var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas:
var root = my_canvas.createGroup();
var text = root.createChild("text")
.setText("Hello world from FGPlot v. 0.1 !")
.setTranslation(10, 30)
.setAlignment("left-top")
.setFontSize(20)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.set("max-width", 380)
.setColor(1,0,0);


                  var root = my_canvas.createGroup();
                  var text = root.createChild("text")
                                  .setText("Hello world from FGPlot v. 0.1 !")
                                  .setTranslation(10, 30)
                                  .setAlignment("left-top")
                                  .setFontSize(20)
                                  .setFont("LiberationFonts/LiberationSans-Regular.ttf")
                                  .set("max-width", 380)
                                  .setColor(1,0,0);


var graph = root.createChild("group");


var x_axis = graph.createChild("path", "x-axis")
                  var graph = root.createChild("group");
.moveTo(10, 150)
.lineTo(380, 150)
.setColor(1,0,0)
.setStrokeLineWidth(3);


var y_axis = graph.createChild("path", "y-axis")
                  var x_axis = graph.createChild("path", "x-axis")
.moveTo(10, 30)
                                    .moveTo(10, 150)
.lineTo(10, 250)
                                    .lineTo(380, 150)
.setColor(1,0,0)
                                    .setColor(1,0,0)
.setStrokeLineWidth(3);
                                    .setStrokeLineWidth(3);


var plot = graph.createChild("path", "data")
                  var y_axis = graph.createChild("path", "y-axis")
.setStrokeLineWidth(2)
                                    .moveTo(10, 30)
.setColor(0,0,1)
                                    .lineTo(10, 250)
.moveTo(10,150); # origin
                                    .setColor(1,0,0)
                                    .setStrokeLineWidth(3);


var samples = [ # absolute coordinates
                  var plot = graph.createChild("path", "data")
[50, 150], [100,140], [200,110], [270, 55]
                                  .setStrokeLineWidth(2)
];
                                  .setColor(0,0,1)
                                  .moveTo(10,150); # origin


foreach(var set; samples) {
                  var samples = [ # absolute coordinates
plot.lineTo( set[0], set[1] );
                                  [50, 150], [100,140], [200,110], [270, 55]
}
                                ];


]]>
                  foreach(var set; samples) {
</load>
                                              plot.lineTo( set[0], set[1] );
</nasal>
                  }
</canvas>
          ]]>
        </load>
      </nasal>
    </canvas>


     <button>
     <button>

Revision as of 03:49, 12 January 2014

Note: This tutorial describes features only available in FlightGear >= 2.8 ! (also note that the Canvas/PUI support described here will eventually be phased out, once PUI is finally retired, probably some time after the 3.0 release)

Using the combination of Nasal scripting, GUI dialogs and embedded canvas regions for 2D rendering, you can create standalone "FlightGear applications" in the form of self-contained dialogs that you can easily share with fellow FlightGear users. This can for example be used to create a plotting application like FGPlot, which would look to FlightGear like a conventional dialog.

To create a new canvas dialog, you can just open an existing dialog from $FG_ROOT/gui/dialogs (e.e.g copy a simple dialog like the exit/about dialog), and then customize it according to your needs - i.e. by naming it "fgplot.xml", remove any stuff that you don't need, then add a new canvas widget to the dialog, like this:

<canvas>
  <name>fgplot</name>
  <valign>fill</valign>
  <halign>fill</halign>
  <stretch>true</stretch>
  <pref-width>600</pref-width>
  <pref-height>400</pref-height>
  <nasal>      
  <!-- 
       this is the Canvas-specific Nasal section where you can run your own Nasal code 
       to access the canvas region
  -->
    <load>
      <![CDATA[
      
               # you can add your canvas-specific code here
               var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas :

               print("Hello world from the embedded canvas section!\n");

      ]]>
    </load>
  </nasal>
</canvas>

You can then use Nasal to animate your canvas and draw graphics etc.

FGPlot

Here's a complete fgplot.xml example for $FG_ROOT/gui/dialogs, open it through the Nasal console, by running gui.showDialog("fgplot");

Stub

(Note: As of 07/2013, FGPlot has significantly progressed since the early days of the prototype - see the FGPlot article for details and screen shots)

<?xml version="1.0"?>
<PropertyList>
  <name>fgplot</name>
  <modal>false</modal>
  <layout>vbox</layout>

  <text>
    <label>FGPlot</label>
  </text>

  <group>
    <layout>hbox</layout>
    <halign>fill</halign>
    <default-padding>10</default-padding>
    <empty><stretch>true</stretch></empty>

    <empty><stretch>true</stretch></empty>

    <canvas>
      <name>fgplot</name>
      <valign>fill</valign>
      <halign>fill</halign>
      <stretch>true</stretch>
      <pref-width>600</pref-width>
      <pref-height>400</pref-height>
      <nasal>      
      <!--
           this is the Nasal/canvas section where you can run your own Nasal code 
           to access the canvas section 
      -->
        <load>
          <![CDATA[
                   # you can add your canvas-specific code here
                   var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas:

                   var root = my_canvas.createGroup();
                   var text = root.createChild("text")
                                  .setText("Hello world from FGPlot v. 0.1 !")
                                  .setTranslation(10, 30)
                                  .setAlignment("left-top")
                                  .setFontSize(20)
                                  .setFont("LiberationFonts/LiberationSans-Regular.ttf")
                                  .set("max-width", 380)
                                  .setColor(1,0,0);


                   var graph = root.createChild("group");

                   var x_axis = graph.createChild("path", "x-axis")
                                     .moveTo(10, 150)
                                     .lineTo(380, 150)
                                     .setColor(1,0,0)
                                     .setStrokeLineWidth(3);

                   var y_axis = graph.createChild("path", "y-axis")
                                     .moveTo(10, 30)
                                     .lineTo(10, 250)
                                     .setColor(1,0,0)
                                     .setStrokeLineWidth(3);

                   var plot = graph.createChild("path", "data")
                                   .setStrokeLineWidth(2)
                                   .setColor(0,0,1)
                                   .moveTo(10,150); # origin

                   var samples = [ # absolute coordinates
                                   [50, 150], [100,140], [200,110], [270, 55]
                                 ];

                   foreach(var set; samples) {
                                               plot.lineTo( set[0], set[1] );
                   }
          ]]>
        </load>
      </nasal>
    </canvas>

    <button>
      <legend>Exit</legend>
      <equal>true</equal>
      <key>Esc</key>
      <binding>
        <command>dialog-close</command>
      </binding>
    </button>

    <empty><stretch>true</stretch></empty>
  </group>
</PropertyList>

Next, you can use a timer to plot properties like /position/altitude-ft or /velocities/groundspeed-kt.