jMonkey LorisGUI - Models

Interactions between Loris and your application

Home Overview Visuals XML Style Model Controls Components Layouts
 

Model/View/Controller

LorisGUI follows a classic MVC paradigm that segregates and isolates the various elements that make up your GUI. The View consists of the various visuals used to actually display the GUI. These are based on standard jme components, such as Quads and BitmapText, and have no inherent knowledge of what they are displaying. The Model is the data used by your application. In this case of a jMonkey GUI, your model is probably a set of configuration values that control some aspect of your application. This could be a volume level for music, or screen resolution for your graphics. LorisGUI imposes no restriction or meaning to the values in your application Model. It only provides some helper classes to assist in getting those values appropriately displayed. The Controller is the glue between the View and the Model. It handles interaction policy with the end user and formats Model data for View display.

LorisGUI provides various interaction levels to support your application working with the GUI. These range from simple init/probe, to callback processing, to dynamic polling. These mechanism are not mutually exclusive and can be combined in any way.

 

Initialize/Probe

The simplest interaction between your application and Loris is to initialize the GUI controls with particular values, and the then to probe the GUI at some subsequent time to check on the current value. The initial value can be established directly within the XML definition, or the control can be located via its GuiContext and its value set:

        
    Checkbox aCheckbox = aContext.findByName( "MyCheckbox", Checkbox.class );
    aCheckbox.setVisualValue( true );
	    

Probing the value is similar, you locate the control and ask for its current value. You will be given a GuiValue and it is your responsibility to know how to decipher it:

        
    DropDown aDropDown = aContext.findByName( "MyDropDown", DropDown.class );
    GuiValue currentValue = aDropDown.getVisualValue();
    
    // I know the dropdown is representing a set of integers
    int someValue = currentValue.intValue();
	    
 

Callback

Loris supports the Actionable interface, which allows you to wire up callback handlers. Your implementation of Actionable provides the method that is called when the user takes some action on a GUI control. The simplest callback would be handling the user clicking on a Button. Other controls can provide the current value of the control to the callback method.

An Actionable can be defined and wired directly into a control that you locate via its GuiContext, or you can register a set of Actionables with the GuiContext and assign action codes to the controls. When the control fires, it will locate the appropriate Actionable via its action code and invoke the associated method.

 

Dynamic Polling

You can configure Loris to actively monitor and reflect a dynamic data value in the GUI. This is done via a DataField. The DataField interface operates on a version number, which is incremented any time the underlying data value is changed. On the controller side, a DataReflector is assigned to a given GUI element and wired to a DataField. Through the jme update polling cycle, any change in the DataField version number causes the View to be updated with the latest data value. Likewise, any end user change via the GUI View causes the DataField data value to be updated.

Loris provides some standard implementations of DataField that provide a slot for the actual Object value and manages the version number. Likewise, Loris provides implementations of DataReflector that connect to a DataField and understand various primitive data types (Boolean, Number, String, ...). You can subclass a DataReflector to provide a callback method invoked when the end user changes a value.

    BooleanField aBoolean = new BooleanField( true );
    BooleanReflector aHandler = new BooleanReflector( aBoolean, true );
	    	   
    Checkbox aCheckbox = aContext.findByName( "MyCheckbox", Checkbox.class );
    aCheckbox.addDataReflector( aHandler );
	        
    // After this point, any changes you make to the aBoolean value will be
    // automatically reflected in the checkbox state.
    aBoolean.setData( true );
	    
 
TypedField/TypedReflector

The simplest DataField/DataReflector is for typed data. In this case, you declare the data type you are operating with (TypedField<Integer>, TypedReflector<Integer>), and Loris does most of the rest. There are predefined, convenience classes for BooleanField/BooleanReflector, IntField/NumberReflector, FloatField/NumberReflector

 
ListField/ListReflector

List-based controls represent a single value selected from some set of values. RadioButtonGroup, ListBox, and DropDown all operate by the user picking a single element from the collection of possibilities. The different options can be set from the XML, with a declaration of the value to use for each option.

But you can also configure the option set via Model processing. In this case, you use a ListField, connected via a ListReflector. The ListField is generically 'typed', so you indicate the underlying data type when you use it. You then provide a java.util.List of values to use. These values are assigned in order to the sub-controls that comprise the list-based control. You can also supply a list of 'decoration' strings, or direct the ListField to build the decorations from the underlying values. These decorations are incorporated into the visual display of the sub-controls.

 
Range/RangeReflector

The Slider control can be configured to operate with a given range of values. In that case, a RangeReflector will be used to connect the DataField with the control. If the Slider has been configured to use a Range, then the interpreted range value, between min and max, will be reflected into the underlying DataField Number value. If there is no Range, then the percentage value between 0.0 and 1.0 will be reflected into the underlying DataField Number.

 
StringField

A string on the model side can be represented by TypedField<String> and then connected back to a control with a TypedReflector<String>. Or a StringField can be used. A StringField provides extra services for modifying an existing String. For example, you can append new text and/or new lines to a dynamic string. Future enhancements may involve setting color or style.

In addition, text based controllers like TextString and TextBlock look for StringField and will honor any auto-positioning specifications defined there. This can force scrolling to keep newly added text in view.

 

GuiValue

There is no restriction on the data values you use within your application model. However, the Controller layer needs to operate with known entities when reflecting those values to the end user via the Views. The Controllers use a GuiValue, which provides a set of services to access the underlying object value as a desired primitive. When given any arbitrary model value, the Controller will map it to the best-fit GuiValue it can find. If your application probes for the current value of a control, an instance of GuiValue will be returned.

boolean booleanValue()
Access to the true/false boolean value.
int intValue()
Access to the value as an integer.
long longValue()
Access to the value as a long.
float floatValue()
Access to the value as a float.
double doubleValue()
Access to the value as a double.
String stringValue()
Access to the value as a String.
Object getDataValue()
Access to the non-primitive, Object representation of the value.
Number numberValue()
Access to the underlying value as Number.
 

Range

The GuiValue 'Range' is a very specialized value designed explicitly to work with a Slider. A Slider inherently tracks its thumb's position as a percentage of the distance traveled. It therefore operates between 0.0 and 1.0. While you can interpret this as any range of values, the Range allows you to configure a minimum and maximum. The accessible value of the Range (.intValue(), .floatValue(), ...) will then reflect something between the given min and max.

The Range can also be used to provide decorations within the Slider. The minimum value can be applied to the decrementing end-cap. The maximum value can be applied to the incrementing end-cap. And the value itself can be applied to the thumb. These decorations appear in the visual presentation of the Slider. These decorations can be defined as a static, literal string, or a MessageFormat pattern can be used to dynamically produce the string from the underlying value.

The Range can be established by the <thumbPosition class='range'> declaration within the XML configuration, or by Style attributes. If you choose to use dynamic polling for your Model interaction, be sure to use a RangeReflector when wiring things up.

asInt='true/false'
When true, the current, min, and max values are treated as integers, not floats, and are truncated accordingly. The default is false.
data='avalue'
Establish the thumb position value. This value is expected to be between the min and max.
dataFormat='pattern'
Provide a format pattern (java.text.MessageFormat) applied to the value to dynamically produce the string that decorates the thumb.
dataString='Literal'
Provide a literal, static string to decorate the thumb.
min='avalue'
Establish the minimum value.
minFormat='pattern'
Provide a format pattern (java.text.MessageFormat) applied to the minimum to dynamically produce the string that decorates the minimum end-cap.
minString='Literal'
Provide a literal, static string to decorate the minimum end-cap.
max='avalue'
Establish the maximum value.
maxFormat='pattern'
Provide a format pattern (java.text.MessageFormat) applied to the maximum to dynamically produce the string that decorates the maximum end-cap.
maxString='Literal'
Provide a literal, static string to decorate the maximum end-cap.
 

StringField

StringField is a blend of a 'typed' DataField along with GuiValue style access. On the java code side, it supports all the GuiValue primitive data type accessors, and allows modification of the existing string via append.

appendText( String pValue )
Append the given String value to the currently defined run of text.
appendLine( String pValue )
Append the given String value to the currently defined run of text after including a '\n'.
setFieldInView( FieldInView pWhere )
Keep the selected text position (None/First/LastCharacter/LastRow) visible to the user.
SEE ALSO:
GuiValue for the primitive data accessors

A StringField can also be built within the XML configuration with the <stringField> element supported on TextString and TextBlock. You can then define the initial text and select the field to keep in view. Once a StringField has been created for a control, its 'fieldInView' remains in force even if the underlying text is dynamically altered.

fieldInView='None/First/LastCharacter/LastRow'
Keep the selected text position visible to the user.
text='astring'
Set the initial seed text string.