Nasal CDU Framework: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
No edit summary
Line 1: Line 1:
{{WIP|[[User:Hcc23|Hcc23]] is working on this. Find him in the FG IRC channel to discuss this page.}}
This page is a rather technical description of the Nasal code for the framework used to implement a Boeing style [[CDU]].
This page is a rather technical description of the Nasal code for the framework used to implement a Boeing style [[CDU]].
{{WIP|[[User:Hcc23|Hcc23]] is working on this. Find him in the FG IRC channel to discuss this page.}}


'''Note:''' Although this is meant as a documentation for the code, it obviously will (always) be (slightly) outdated. However, after reading through this page, the actual source code at https://gitorious.org/fg/fgdata/trees/master/Aircraft/Instruments-3d/cdu should not present any major surprises. [[User:Hcc23|Hcc23]] 10:07, 7 May 2011 (EDT)
'''Note:''' Although this is meant as a documentation for the code, it obviously will (always) be (slightly) outdated. However, after reading through this page, the actual source code at https://gitorious.org/fg/fgdata/trees/master/Aircraft/Instruments-3d/cdu should not present any major surprises. [[User:Hcc23|Hcc23]] 10:07, 7 May 2011 (EDT)
Line 7: Line 7:


= Basic Classes =
= Basic Classes =
These are the core classes in the CDU framework. The documentation should show a brief comment on what each variable or function is intended to do, particularly the ones that are important for the '''creation''' of an actual, content-filled CDU page.
Although Nasal as such has no support for this, the internal stuff in a class is sectioned in three categories, borrowing language from <tt>C++</tt>
* '''Static:''' Stuff in this section is mainly identified by being made directly as part of the <tt>hash</tt> (as opposed to being ''tagged on'' by the the <tt>new</tt> constructor. Elements in here also follow a ''camelCase'' type of notation, whereas ''members'' use an ''underscore_naming_convetion''. Please note that although meant to be comparable to statics, in hindsight a lot of them would be better placed in the member section Public...
* '''Public:''' Elements in here are created from inside the <tt>new</tt> constructor and follow an ''underscore_naming_convetion''. In a perfect world these would only be accessing functions, as exposing variables is always prone for trouble when the time for a redesign comes... Elements in here should be the only ones used in the creation of a page - in a perfect world.
* '''Private:''' Elements in here are created from inside the <tt>new</tt> constructor and follow an ''underscore_naming_convetion''. Although readable by everybody, access to these elements should be limited to functions in the static and public parts of the classes code. Particularly no page creation (user) code should need to access this information.
'''Note:''' I know that I violate these rules. Yes. But I have rewritten the framework to often to (at this point) care much about it - particularly as it seems to be working. Please, feel free to correct the Nasal code I have written (which might involve the pain of revisiting the page creation sections... Sorry for that.) [[User:Hcc23|Hcc23]] 14:45, 9 May 2011 (EDT)


== Line ==
== Line ==
Line 126: Line 138:
<code>
<code>
   var CDU = {
   var CDU = {
     # "STATIC"
     # "Static"
     func M_ERROR(message_string),
     func M_ERROR(message_string),
     func M_WARNING(message_string),
     func M_WARNING(message_string),
Line 151: Line 163:
<code>
<code>
   var ScratchPad = {
   var ScratchPad = {
     # "STATIC"
     # "Static"
     vector messages,
     vector messages,
     scalar deleteString, # "DELETE"~""
     scalar deleteString, # "DELETE"~""
Line 157: Line 169:
     func new(),
     func new(),
    
    
     # "PUBLIC"
     # "Public"
     scalar me.input_string,
     scalar me.input_string,
     func me.erase,
     func me.erase,
      
      
     # "PRIVATE"
     # "Private"
     scalar me.pm_trigger,
     scalar me.pm_trigger,
     func me.plusminus(),
     func me.plusminus(),
Line 175: Line 187:
<code>
<code>
   var ListenerCollection = {
   var ListenerCollection = {
     # "STATIC"
     # "Static"
     func registerInPropTree(path),
     func registerInPropTree(path),
     func add(prop, field_id, subpage_id, side, lsk_index),
     func add(prop, field_id, subpage_id, side, lsk_index),
Line 181: Line 193:
     func new(ptp=nil),
     func new(ptp=nil),
    
    
     # "PRIVATE"
     # "Private"
     scalar me.ptp,
     scalar me.ptp,
     vector me.listener_list,
     vector me.listener_list,

Revision as of 18:45, 9 May 2011

WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
Note: Hcc23 is working on this. Find him in the FG IRC channel to discuss this page.
See history for the latest developments.

This page is a rather technical description of the Nasal code for the framework used to implement a Boeing style CDU.

Note: Although this is meant as a documentation for the code, it obviously will (always) be (slightly) outdated. However, after reading through this page, the actual source code at https://gitorious.org/fg/fgdata/trees/master/Aircraft/Instruments-3d/cdu should not present any major surprises. Hcc23 10:07, 7 May 2011 (EDT)


Basic Classes

These are the core classes in the CDU framework. The documentation should show a brief comment on what each variable or function is intended to do, particularly the ones that are important for the creation of an actual, content-filled CDU page.

Although Nasal as such has no support for this, the internal stuff in a class is sectioned in three categories, borrowing language from C++

  • Static: Stuff in this section is mainly identified by being made directly as part of the hash (as opposed to being tagged on by the the new constructor. Elements in here also follow a camelCase type of notation, whereas members use an underscore_naming_convetion. Please note that although meant to be comparable to statics, in hindsight a lot of them would be better placed in the member section Public...
  • Public: Elements in here are created from inside the new constructor and follow an underscore_naming_convetion. In a perfect world these would only be accessing functions, as exposing variables is always prone for trouble when the time for a redesign comes... Elements in here should be the only ones used in the creation of a page - in a perfect world.
  • Private: Elements in here are created from inside the new constructor and follow an underscore_naming_convetion. Although readable by everybody, access to these elements should be limited to functions in the static and public parts of the classes code. Particularly no page creation (user) code should need to access this information.

Note: I know that I violate these rules. Yes. But I have rewritten the framework to often to (at this point) care much about it - particularly as it seems to be working. Please, feel free to correct the Nasal code I have written (which might involve the pain of revisiting the page creation sections... Sorry for that.) Hcc23 14:45, 9 May 2011 (EDT)

Line

The line class represents data to be shown on a row of the CDU's display matrix. This does not mean that a line has to span a complete row of the CDU's display matrix.

 var Line = {
   # "Static"
   vector 	byID,
   func 	registerInPropTree(path),
   func 	formatOutput(input_data),
   func 	getScreenTextVector(),
   func 	new(line_data,ptp),
   
   # "Public"
   scalar 	me.id,
   scalar 	me.ptp,
   vector 	me.used_properties,
   vector 	me.line_data,
   scalar 	me.line_string_length,
   func 	me.enable(),
   func 	me.disable(),
   
   # "Private"
   scalar 	me.active,
 };

Field

A field holds two lines, the label and the data line, as well as information about what the associated line select key does.

 var Field = {
   # "Static"
   vector 	byID,
   func 	registerInPropTree(path=nil),
   func 	new(label,data,key_action=nil,ptp=nil),
   
   # "Public"
   scalar 	me.id,
   scalar 	me.ptp,
 
   func 	me.get_label_line(),
   func 	me.get_label_line(),
   func 	me.used_properties(),
   func 	me.lsk_binding(),
   func 	me.enable_lsk(),
   func 	me.disable_lsk(),
 
   # "Private"
   (Line)	me.label_line,	
   (Line) 	me.data_line,
   scalar 	me.lsk_active,
 };

SubPage

A SubPage is actually the main element in the CDU framework. It holds the content via its fields and manages the updating of the CDU screen.

 var SubPage = {
   # "Static"
   vector 	byID,
   (Field) 	blankField,
   func 	registerInPropTree(path=nil),
   func 	updateField(field, side, lsk_index),	
   func 	displayFields(field_vector, side),
   func 	displayPage(),
   func 	new(parent_base_page,name=nil,ptp=nil),
   
   # "Public"
   scalar 	me.id,
   scalar      me.separator,
   scalar 	me.ptp,
   func 	me.register_field(field_pos,field),
   func 	me.activate(),
   (Field) 	me.home
 
   # "Private"
   scalar 	me.parent,
   scalar      me.title,
   scalar      me.status,
   vector 	me.left_field,
   vector      me.right_field,
 };

BasePage

A BasePage is exactly that: a base to hold sub pages. A base page most closely represents the concept of a page in a CDU.

 var BasePage = {
   # "Static"
   vector 	byID,
   func 	displayPage(),
   func 	regiserInPropTree(path)
   func 	new(name,ptp=nil),
   
   # "Public"
   scalar 	me.id,
   scalar 	me.active_sub_page_id,
   func 	me.activate(),
   (Field) 	me.home,
   scalar 	me.ptp,
   
   # "Private"
   vector 	me.sub_pages,
   scalar 	me.title,
   scalar 	me.status,
   
 };  

CDU

The CDU is the main class for the instrument. Each simulated CDU should have one and only one CDU instance associated to it. This is intended to support multiple CDUs showing different content in the future.


 var CDU = {
   # "Static"
   func 	M_ERROR(message_string),
   func 	M_WARNING(message_string),
   func 	M_NOTE(message_string),
   func 	M_HINT(message_string),
 
   func 	updateDisplay(),
   scalar 	activeBasePageID,
 
   (ScratchPad) 		scratchPad,
   (Timer) 			timer,
   (ListenerCollection) 	listOfListeners,
 };

Additional Infrastructure

The previous section was more concerned with the conceptually necessary pieces for a/the CDU. This section introduces the other elements the framework introduces in order to code a functional CDU.


ScratchPad

The ScratchPad is the input/output line in the CDU(s). The scratch pas as such is kind of different from the rest of the CDU(s) as the scratch pad messages are truly static, i.e. they happen to be displayed on all CDUs in the cockpit, no matter what the individual CDU is otherwise showing.

 var ScratchPad = {
   # "Static"
   vector 	messages,
   scalar 	deleteString, # "DELETE"~""
   func 	displayScratchPad(),
   func 	new(),
 
   # "Public"
   scalar 	me.input_string,
   func 	me.erase,
   
   # "Private"
   scalar 	me.pm_trigger,
   func 	me.plusminus(),
   func 	me.clear(pressedTime),
   func 	me.erase(),
 };


ListenerCollection

In order to update fields that are tied to a (potentially changing) property, fields that need a (potentially changing) property to compute their data can (and automatically will) register a property listener on the relevant properties whenever the relevant field is displayed. In order to unregister the listener for pages that are no longer displayed, the class CDU keeps a collection of the currently active listeners, such allowing the unregisterling for unneeded listeners.

 var ListenerCollection = {
   # "Static"
   func 	registerInPropTree(path),
   func 	add(prop, field_id, subpage_id, side, lsk_index),
   func 	clearAll(),
   func 	new(ptp=nil),
 
   # "Private"
   scalar 	me.ptp,
   vector 	me.listener_list,
   vector 	me.property_list,
 };