Canvas GUI: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
mNo edit summary
 
(33 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{Out of date}}
{{Canvas Navigation}}
{{Canvas Navigation}}
{{cquote
  |<nowiki>I'd love for FlightGear to be runtime configurable through a GUI --
just drag and drop a property onto a drop-down menu, a keyboard
diagram, etc., and build new dialogs while the plane is flying.</nowiki>
  |{{cite web |url=http://www.mail-archive.com/flightgear-devel%40flightgear.org/msg09560.html
    |title=<nowiki>starting the XML GUI; early implementors needed</nowiki>
    |author=<nowiki>David Megginson</nowiki>
    |date=<nowiki> Fri, 08 Nov 2002 17:15:38 -0800</nowiki>
  }}
}}
{{Note| the GUI API documentation can be found here: [[Canvas GUI API]]}}


== Background ==
== Background ==
{{Mergeto|Howto:Creating a Canvas GUI Widget}}
In order to eventually phase out PUI completely, we need to stop adding PUI dependencies to the source tree. We now have the Canvas system, and there’s a formal decision to modernize the GUI using the Canvas, and completely replace PUI sooner rather than later.
In order to eventually phase out PUI completely, we need to stop adding PUI dependencies to the source tree. We now have the Canvas system, and there’s a formal decision to modernize the GUI using the Canvas, and completely replace PUI sooner rather than later.


Line 20: Line 36:
Given that we have agreed to depreciate PUI, there's simply no reasonable reason to keep on adding PUI widgets/dependencies to the source tree - we need to stop doing that right now. Instead, we need to identify required Nasal/Canvas enhancements, in order to allow these widgets to be implemented outside C++ space.
Given that we have agreed to depreciate PUI, there's simply no reasonable reason to keep on adding PUI widgets/dependencies to the source tree - we need to stop doing that right now. Instead, we need to identify required Nasal/Canvas enhancements, in order to allow these widgets to be implemented outside C++ space.


== PUI Widgets ==
== Status 04/2014 ==
Here's a list of custom, hardcoded, PUI widgets which we will need to re-implement using the Canvas, based on [https://gitorious.org/fg/flightgear/trees/next/src/GUI $FG_SRC/GUI]:
{{Note|As of 04/2014, we have several people independently interested in working on Canvas/GUI features:
* owenpsmith & macnab (via [[Aircraft Generation Wizard]])
* Philosopher working on an [[Interactive Nasal Console]] using Canvas
* kuifje09 working on Canvas/GUI widgets (for [[FGPlot]])
* galvedro & Necolatis working on a Canvas-based procedurally created failure management dialog [[A Failure Management Framework for FlightGear]]
* punkedpanda interested in helping with GUI improvements
* also, one user mentioned being interested in working on an integrated GUI launcher in {{Issue|1295}}
It would make sense to coordinate all these efforts a little, so if you're working on anything related, please get in touch via the Canvas subforum.
}}


* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/FGPUIDialog.cxx#line169 loglist]
{{cquote
** Required APIs: logbuffer needs to be exposed to Nasal via cppbind
  |<nowiki>So far, Canvas/MapStructure have helped make 2D maps available for all needs in FlightGear, and a canvas/Nasal-based parser that processes our existing GUI dialogs/HUDs or 2D panels code would have the same benefits (GUI: 10k, HUD:3k, 2D panels:4k). Generic canvas/Nasal framework for each of those would probably also be under 4k in total. But it is so much easier being NOT consistent.</nowiki>
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/AirportList.cxx airport list]
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=209465#p209465
** Required APIs: extended NasalPositioned API
    |title=<nowiki>Re: scaling instruments in xml</nowiki>
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/WaypointList.cxx waypoint list]
    |author=<nowiki>Hooray</nowiki>
** Required APIs: extended NasalPositioned API
    |date=<nowiki>Wed May 14</nowiki>
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/property_list.cxx property list]
  }}
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/PUIFileDialog.cxx file dialog]
}}
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/menubar.cxx menubar]
* [https://gitorious.org/fg/flightgear/blobs/next/src/GUI/MapWidget.cxx map widget] (see [[Canvas Map API]])


In order to re-implement these using the Canvas system, we need to identify Nasal APIs that are currently missing, and which need to be provided via the cppbind framework.
Before creating new widgets please have a look at Tom's fgdata branch: {{gitorious url|fg|toms-fgdata|branch=canvas-gui-demo}}
Tom is currently working on creating a standard widget and layout system (similar to eg. Qt). At the moment there only exists a button widget (but already with focus, and hover/press effects) [http://forum.flightgear.org/viewtopic.php?f=24&p=186563#p186563].
Specifically, see {{gitorious source|fg|toms-fgdata|branch=canvas-gui-demo|path=Nasal/canvas/gui|view=tree|pre=$FG_ROOT}}.


== Replacing native PUI widgets with Canvas widgets ==
Before we can replace PUI with a Canvas based GUI a lot work has to be done. Tom is currently working on extending the current canvas windows manager to also become a simple decorator engine which will allow creating unified window decorations and handling like dragging/resizing/closing windows. When this is done we can think of creating simple dialogs. And then we can start creating different widgets and see how to implement a layouting engine. And only then we can start thinking about replacing PUI dialogs with Canvas dialogs. (We may also need a fallback for older hardware as render-to-texture probably won't be supported).


* provide a PropertyList-XML file that specifies the canvas to be put into $FG_ROOT/gui/widgets
So in the current state it would bring us much benefit to create a separate canvas dialog showing log messages without being able to show it in normal PUI dialogs. Later if we have got a list widgets it will be very easy to just print the log messages to this list widget.
* provide a Nasal implementation to be put into $FG_ROOT/Nasal/canvas/widgets
* modify all existing uses of the hardcoded widget


For example, to replace the loglist widget (prototype available at: https://gitorious.org/~hooray/fg/hoorays-fgdata/commits/topics/canvas-loglist ) :
== Creating new Widgets ==


Provide an PropertyList-XML that declares the canvas and its default settings, including a Nasal section that implements the logic, saved as gui/widgets/loglist.xml:
* text label
<syntaxhighlight lang="xml">
* checkbox
<?xml version="1.0"?>
* radio buttons
<PropertyList>
* text field
              <name></name>
* edit box
              <valign>fill</valign>
              <halign>fill</halign>
              <stretch>true</stretch>
              <pref-width>400</pref-width>
              <pref-height>200</pref-height>
                <nasal><load><![CDATA[
                print("canvas loglist running!");
                ]]></load></nasal>
</PropertyList>
</syntaxhighlight>


Instead of embedding all code inline, you can also include an external Nasal by using:
== PUI Widgets ==
Canvas dialogs are definitely the way to go, as they are far more flexible and will replace PUI in the future. Since I think FG 2.11 you can create canvas dialogs with window decoration, including a title bar allowing to drag the window around and a close icon:


<syntaxhighlight lang="php">
<syntaxhighlight lang="nasal">
io.load_nasal( getprop("/sim/fg-root") ~ "/Nasal/canvas/widgets/loglist.nas" );
var dlg = canvas.Window.new([400,300], "dialog")
    .set("title", "My Canvas Dialog");
</syntaxhighlight>
</syntaxhighlight>


To implement the widget-specific logic, you can access the parent canvas using the '''cmdarg()''' API:
The existing XML dialogs can still be used and will also be usable in the future (by a backwards compatibility layer or some migration path).  
<syntaxhighlight lang="php">
var my_canvas = canvas.get( cmdarg() ); # this will get a handle to the parent canvas 


var root = my_canvas.createGroup();
Implementing all our existing PUI/XML-based dialogs is almost certainly going to be more work than providing a Nasal-space migration path/wrapper that reads the old dialogs and turns them into "modern" canvas windows, possibly by just overwriting the dialog-show fgcommand via the new removecommand/addcommand APIs. And phasing out canvas widget should be fairly straightforward too, because those can be directly mapped to embedded/nested canvas textures, so I wouldn't worry too much ...
var text = root.createChild("text")
.setText("some custom canvas widget")
.setTranslation(10, 30)
.setAlignment("left-top")
.setFontSize(20)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.set("max-width", 380)
.setColor(1,0,0);
</syntaxhighlight>


For handling mouse/GUI events, see: [[Canvas - Event Handling]].
All standard widgets (textbox, label, radio button, checkbox etc) can be provided by a Nasal parser that turns the existing GUI XML into canvas widgets — our hard-coded widgets however, need to be separately re-implemented. Here's a list of custom, hardcoded, PUI widgets which we will need to re-implement using the Canvas, usually located in {{flightgear file|src/GUI}}:


Next, replace the original <loglist> in all dialogs in $FG_ROOT/gui/dialogs
* {{flightgear file|src/GUI/MapWidget.cxx|t=map widget}} (see [[MapStructure]])
** {{flightgear commit|433af2}} (expose the flight recorder/replay buffers via cppbind)
** {{flightgear commit|11c00a}} (add support for helipads from apt.dat 850+)
** {{flightgear commit|6bf47c}} (MapWidget: make use of the new POI system and display cities on the map. This is meant as a preview.)
** {{flightgear commit|658bda}} (MapWidget: Show counties and towns as well, depending on the zoom. Some colors added.)
** {{flightgear commit|38a373}} (Display AI traffic route in map. Add some helpers so MapWidget can show the origin and destination of AIAircraft with a FlightPlan.)
* {{flightgear file|src/GUI/FGPUIDialog.cxx|l=169|t=loglist}} {{progressbar|70}}
** Required APIs: logbuffer needs to be exposed to Nasal via cppbind
* {{flightgear file|src/GUI/WaypointList.cxx|l=169|t=waypoint list}}
** {{flightgear commit|7afedb}}
** {{flightgear commit|846fd2}}
* {{flightgear file|src/GUI/AirportList.cxx|t=airport list}}
** Required APIs: extended NasalPositioned API
* {{flightgear file|src/GUI/WaypointList.cxx|t=waypoint list}}
** Required APIs: extended NasalPositioned API
* {{flightgear file|src/GUI/property_list.cxx|t=property list}}
* {{flightgear file|src/GUI/PUIFileDialog.cxx|t=file dialog}}
* {{flightgear file|src/GUI/menubar.cxx|t=menubar}} (see [[Howto:Making a Canvas Menubar]])


<syntaxhighlight lang="xml">
In order to re-implement these using the Canvas system, we need to identify Nasal APIs that are currently missing, and which need to be provided via the cppbind framework.
<loglist>
 
                <halign>fill</halign>
This way, C++ developers can concentrate on providing the missing Nasal/C++ hooks, whereas Nasal developers can provide the required widgets.
                <valign>fill</valign>
                <stretch>true</stretch>
                <pref-width>450</pref-width>
                <pref-height>200</pref-height>
                <padding>6</padding>
</loglist>
</syntaxhighlight>


And include the corresponding canvas file:


<syntaxhighlight lang="xml">
[[Category:Canvas GUI]]
<canvas include="gui/widgets/loglist.xml"> <!-- see $FG_ROOT/Docs/README.gui for details -->
                <halign>fill</halign>
                <valign>fill</valign>
                <stretch>true</stretch>
                <pref-width>450</pref-width>
                <pref-height>200</pref-height>
                <padding>6</padding>
</canvas>
</syntaxhighlight>

Latest revision as of 14:30, 14 January 2017

This article or section contains out-of-date information

Please help improve this article by updating it. There may be additional information on the talk page.


Cquote1.png I'd love for FlightGear to be runtime configurable through a GUI -- just drag and drop a property onto a drop-down menu, a keyboard diagram, etc., and build new dialogs while the plane is flying.
— David Megginson ( Fri, 08 Nov 2002 17:15:38 -0800). starting the XML GUI; early implementors needed.
Cquote2.png
Note  the GUI API documentation can be found here: Canvas GUI API

Background

Merge-arrow.gif
It has been suggested that this article or section be merged into Howto:Creating a Canvas GUI Widget.

In order to eventually phase out PUI completely, we need to stop adding PUI dependencies to the source tree. We now have the Canvas system, and there’s a formal decision to modernize the GUI using the Canvas, and completely replace PUI sooner rather than later.

The shortcomings of our GUI, and PUI in particular, have been repeatedly brought up on the devel list over the years.

It was a lot of work to get rid of hard-coded PUI dialogs, and we still have a bunch of hard-coded PUI widgets – as long as we have those, getting totally rid of PUI will be increasingly difficult, because each hard-coded widget will either need to be phased out or manually ported.

Which is exactly the reason why adding additional PUI widgets to the source tree is a really bad idea and counter-constructive to accomplish our long-term goal of phasing out PUI completely.

We should really work out a plan to get rid of hard-coded PUI widgets and re-implement them using canvas-driven widgets, and extend the canvas as we go. Once that is accomplished, completely replacing PUI will become much more straightforward, because it will basically boil down to writing a parser in Nasal to turn our existing dialogs into canvas widgets.

Adding more and more hard-coded PUI widgets to the mix will make our work increasingly difficult, especially if they implement important and useful features that we really want.

We really need to keep the total picture in mind, or we are growing our todo lists with stuff that wasn’t really necessary in the first place.

This discussion is solely focussed on providing a sane migration path, with the ultimate goal of getting totally rid of PUI.

Given that we have agreed to depreciate PUI, there's simply no reasonable reason to keep on adding PUI widgets/dependencies to the source tree - we need to stop doing that right now. Instead, we need to identify required Nasal/Canvas enhancements, in order to allow these widgets to be implemented outside C++ space.

Status 04/2014

Note  As of 04/2014, we have several people independently interested in working on Canvas/GUI features:

It would make sense to coordinate all these efforts a little, so if you're working on anything related, please get in touch via the Canvas subforum.

Cquote1.png So far, Canvas/MapStructure have helped make 2D maps available for all needs in FlightGear, and a canvas/Nasal-based parser that processes our existing GUI dialogs/HUDs or 2D panels code would have the same benefits (GUI: 10k, HUD:3k, 2D panels:4k). Generic canvas/Nasal framework for each of those would probably also be under 4k in total. But it is so much easier being NOT consistent.
— Hooray (Wed May 14). Re: scaling instruments in xml.
Cquote2.png

Before creating new widgets please have a look at Tom's fgdata branch: https://gitorious.org/fg/toms-fgdata?p=fg:toms-fgdata.git;a=shortlog;h=refs/heads/canvas-gui-demo Tom is currently working on creating a standard widget and layout system (similar to eg. Qt). At the moment there only exists a button widget (but already with focus, and hover/press effects) [1]. Specifically, see $FG_ROOT/Nasal/canvas/gui.

Before we can replace PUI with a Canvas based GUI a lot work has to be done. Tom is currently working on extending the current canvas windows manager to also become a simple decorator engine which will allow creating unified window decorations and handling like dragging/resizing/closing windows. When this is done we can think of creating simple dialogs. And then we can start creating different widgets and see how to implement a layouting engine. And only then we can start thinking about replacing PUI dialogs with Canvas dialogs. (We may also need a fallback for older hardware as render-to-texture probably won't be supported).

So in the current state it would bring us much benefit to create a separate canvas dialog showing log messages without being able to show it in normal PUI dialogs. Later if we have got a list widgets it will be very easy to just print the log messages to this list widget.

Creating new Widgets

  • text label
  • checkbox
  • radio buttons
  • text field
  • edit box

PUI Widgets

Canvas dialogs are definitely the way to go, as they are far more flexible and will replace PUI in the future. Since I think FG 2.11 you can create canvas dialogs with window decoration, including a title bar allowing to drag the window around and a close icon:

var dlg = canvas.Window.new([400,300], "dialog")
    .set("title", "My Canvas Dialog");

The existing XML dialogs can still be used and will also be usable in the future (by a backwards compatibility layer or some migration path).

Implementing all our existing PUI/XML-based dialogs is almost certainly going to be more work than providing a Nasal-space migration path/wrapper that reads the old dialogs and turns them into "modern" canvas windows, possibly by just overwriting the dialog-show fgcommand via the new removecommand/addcommand APIs. And phasing out canvas widget should be fairly straightforward too, because those can be directly mapped to embedded/nested canvas textures, so I wouldn't worry too much ...

All standard widgets (textbox, label, radio button, checkbox etc) can be provided by a Nasal parser that turns the existing GUI XML into canvas widgets — our hard-coded widgets however, need to be separately re-implemented. Here's a list of custom, hardcoded, PUI widgets which we will need to re-implement using the Canvas, usually located in flightgear/src/GUI:

In order to re-implement these using the Canvas system, we need to identify Nasal APIs that are currently missing, and which need to be provided via the cppbind framework.

This way, C++ developers can concentrate on providing the missing Nasal/C++ hooks, whereas Nasal developers can provide the required widgets.