B4J Tutorial PropertySheet

Erel

Administrator
Staff member
Licensed User
jControlsFX library v1.20 includes a control named PropertySheet. With this control it is very simple to create forms with many fields.

The data for these fields comes from a custom type instance.
The editor type used by each field is determined from the field type.



The PropertySheet Set method expects two parameters: the type instance and a metadata map that describes the fields.

The above screenshot was taken from this program:
B4X:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Private sheet As PropertySheet
   Type Record(Text As String, Number As Double, _
     Color As Paint, Fnt As Font, Choices As String, YesNo As Boolean)
   Private cutils As ControlsUtils
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   cutils.DisableCssWarnings
   MainForm = Form1
   MainForm.Show
   sheet.Initialize("sheet")
   MainForm.RootPane.AddNode(sheet, 0, 0, 400, 400)
   Dim rec As Record
   rec.Initialize
   Dim meta As Map = CreateMap("Text": sheet.CreateMeta("Text", "Category1", "Text Text"), _
     "Number": sheet.CreateMeta("Some Number", "Category1", "Number Number"), _
     "Color": sheet.CreateMeta("Nice Color", "Category2", "Nice color"), _
     "Fnt": sheet.CreateMeta("Favorite Font", "Category2", ""), _
     "YesNo": sheet.CreateMeta("Yes?", "Category2", ""), _
     "Choices": sheet.CreateMeta("Choose one", "Category3", _
       "choose one from the list").SetChoices(Array("Choice 1", "Choice 2", "Choice 3")))
   sheet.Set(rec, meta)
End Sub
Editors

The property editor is derived from the field type:

String - Text field.
Numbers (other than Long) - Numbers field.
Paint - Color picker.
Long - Date picker.
Font - Font picker.

You can also set the possible values by calling PropertyMetaData.SetChoices.

Metadata

The metadata map, maps between the fields names, which are case sensitive, and PropertyMetaData objects which are created with PropertySheet.CreateMeta.

The metadata includes:
Name - The text that appears at the left side of the property.
Category - The property category. This is used when the sheet is in category mode to categorize the properties.
Description - The property tooltip.
You can also call SetChoices to define the possible values.

Data

Whenever the user modifies a value, the value is automatically updated in the type instance.

Example



The attached short example creates 10 records and uses RandomAccessFile.WriteB4XObject to save and later load the data from a file.
 

Attachments

Last edited:

alwaysbusy

Expert
Licensed User
Is there some kind of way to send a Map instead of a Type object in sheet.Set(rec, meta)?

I have a bunch of propertysheets to make and it would be a lot easier if I could just load the structure from a JSON file and dynamically create the PropertySheet from it.

e.g. the JSON would look something like this:

B4X:
{"view": {
  "properties": {
    "property": [
      {"name": "ID", "type": "text", "value": "",
        "choices": [
        ]
      },   
      {"name": "Parent", "type": "text", "value": "Page",
        "choices": [
        ]
      },       
      {"name": "ButtonType", "type": "combo", "value": "RAISED",
        "choices": [
            "RAISED",
            "FLOATING",
            "FLAT"
        ]
      },
      {"name": "Enabled", "type": "checkbox", "value": "TRUE",
        "choices": [
            "TRUE",
            "FALSE"
        ]
      },
      {"name": "IconName", "type": "text", "value": "",
        "choices": []
      },
      {"name": "IconAlign", "type": "combo", "value": "ICONALIGN_LEFT",
        "choices": [
            "ICONALIGN_LEFT",
            "ICONALIGN_RIGHT"
        ]
      },
      {"name": "Size", "type": "combo", "value": "BUTTONSIZE_NORMAL",
        "choices": [
            "BUTTONSIZE_SMALL",
            "BUTTONSIZE_NORMAL",
            "BUTTONSIZE_LARGE"
        ]
      },
      {"name": "Text", "type": "text", "value": "",
        "choices": []
      },
      {"name": "ThemeName", "type": "text", "value": "",
        "choices": []
      }
    ]
  }
}

Or can I somehow create a Type object at runtime?
 

alwaysbusy

Expert
Licensed User
Thanks for the offer @Erel! I'm checking out several possible ways to write the tool (B4J, Javascript). However, it may be usefull to be able to use sheet.Set(rec, meta) somewhat more flexible instead of using a Type like with a Map. I do love your implementation with the 'record' Type as it is very easy to use (setting, getting values). It's just in my situation, it means a lot of typing :)

Just a thought:

Expanding meta so it can hold the 'field type'
Then a Map with the key being the 'field name' (maybe concatenated with the category e.g. category_fieldname), value is the actual value.

So I could use: sheet.set(Mapwithvalues, metawithfieldtype).

On a side note (not sure it is possible). Maybe an event that is raised if a property is changed. Now I have to run a timer (300ms) that checks if anything is changed.

But if you have another idea that can do the same, please implement it your way!
 

Erel

Administrator
Staff member
Licensed User

m4.s

Member
Licensed User
@Erel or @alwaysbusy

Was B4J support ever implemented for the functionality requests discussed in this very old thread (i.e. using [JSON] Map and/or trapping property change event)? Or maybe now there is a better alternative to Property Sheets, possibly via some available user/custom controls?
 

Erel

Administrator
Staff member
Licensed User
Was B4J support ever implemented for the functionality requests discussed in this very old thread
No.

Or maybe now there is a better alternative to Property Sheets, possibly via some available user/custom controls
You can dynamically build a similar layout with the standard controls.
 
Top