How to use the Preferences Manager
Document #: ?? 
Authors:  Louis Salvail (CWI) 
Editor: (none) 
Reviewer: (none) 
Status: Draft Version. 2 for JDK1.1, SEMPER internal 
 To be done 
-  Improve exceptions handling,
 -  Use of the advanced access control services
 -  Use of the JDK1.1 serialization interface instead of semper.util.serial
 -  Allow selective Access Control for group operations.
 
 General Overview 
The  Preferences Block 
works with 4 main classes:
  -       Configuration class  is
	    responsible for the management of user configuration. In order to be
	    initialised, this class must be able to retrieve a configuration file
	    stored in the target  files system. 
	    It is possible to initialise with the default configuration	 file
	    or any other configuration file by specifying the path and the name
	    for that file. The configuration file is editable by the user. The 
	    general format for that file is:
		
		
		   - 	#Name_of_the_configuration_field Value_of_the_field
		   
 - 	#Name_of_another_configuration_field Value_of_the_field
		   
 -   etc...
		
 
	   In the above representation it is assumed that no blank (or space) appears in
	   both the field name and the field value. It is not allowed in general to include
	   blank in the field name but it is possible to include blank for field values.
	   In order to define a field value with blanks the following can be sed:
	   
	   -  #Name_of_the_configuration_field "this is a value with blanks"
           
 
 	   Note that the symbol " should not be used as part of a field value.
 	   The Configuration manager does not accept the symbol " in field
 	   values with blanks. For field values with no blank symbol, the configuration manager
 	   accepts symbols " if they don't start the field value.
 	
   -       Preferences class : 
	   is the front end for accessing user preferences.
	   This class must be initialised after Configuration initialisation
	   before being used. During initialisation, user preferences are retrieved
	   from the Archive via a default record. If the default file has not been
	   retrieved the manager is not initialised. 
	   The Preferences Manager includes methods to construct preferences environment.
	   A preferences environment contains a set of preferences 
	   groups. Operations on groups are:
	   
		-  adding (addGroup), 
		
 -  removing (delGroup) and
		
 -  getting (getGroup) a particular
	   
 
	   group of preferences are defined in that class.
	   If there is no user preferences in the Archive, a new environment can be
	   built from scratch. Once this is done, the new environment can be saved
	   in the default record (or another one) and initialisation can now be performed.
	  
           In addition,
	   method for
	   
		-  launching interactive edition (editGroup) is also 
           provided. 
	   
 
	   This Preferences Class is also responsible for:
	   
		-  storing (save) and
		
 -  retrieving (load) from the Archive Manager a previously 
	   defined preferences environment.
	   
 
 
	   Preferences environments are
	   stored encrypted in the Archive using encryption services provided
	   by the Archive manager. That means that Access controls for the use
	   of the encryption/decryption keys are assumed to be performed in the
	   Archive block.
	    Methods 
	   
		-  update() and cancel()
           allow to record and cancel changes made by the user during 
	   interactive edition. 
	   
 
           It is also possible to put groups toghether in subgroups. The preferences
 	   manager only uses this group-subgroup structure for the preferences menu
	   creation. Even if the current preferences environment contains subgroups,
	   each group is accessible by its name. The subgroup in which it belongs is
	   not taken into account. The preferences manager allows to:
	   
		-  Create new subgroups below a supergroup
		
 -  Put groups in a subgroup
	        
 -  Retrieve the menu structure defined by the group-subgroup structure.
	   
 
	   
	   
  - 	    PreGroup class  
	   defines a set of preferences fields logically
	   put together. A group has an internal  name by which further 
	   references are made (this is a string). It is by the groupName 
	   that references to that group are made through the Preferences
	   class. In addition, a label is attached to each group and used to 
	   display the name of the group to the user (like the menu items in
	   the Test program).  Methods 
	   
           allow to add and
	   get a field for the current group. In addition,
	   
	     -   delField() method removes
  	   a field of the current group. 
             
 -  update() and  cancel() methods 
	   are used by the Preferences class to update or cancel user's
	   changes during interactive edition. These two methods should not
	   be used directly from the outside. 
	   
 
           It will also be possible to 
	   
		-  save (savePrefGroup()) and
		
 -  load (loadPrefGroup()) a group 
	   
 
           from Archive.
	   The method 
	   
		- showme(frame) add to the frame the components of the 
	   group in the same order by which the fields have been added. This
	   is important for formatting reasons.
	   
 
	   
	   
  - 	    PrefField class  is an 
	   abstract data class providing the methods
	   needed to define a preferences field. Each user-pereferences field
	   items is a subclass of that data class. Each field has a name by which
	   further references (through PrefGroup object) are made. A PrefField object 
	   has a value which is 
	   
		-  get by the getValue() method and 
		
 -  set by the setValue() method. 
	   
 
	   In addition a PrefField object may have a description. That description
	   can be set for each field. When the user, while passing the mouse 
           over a PrefField, double-clicked on the left mouse button the description 
           appears in a window waiting for  "OK" to be pressed.
	   An important point is the appearance of a field. 
	   A PrefField object always provides a 
	   
		- 	showme() method ables to put the 
           component in a  PrefFrame .
	   
 
	
	   A PrefField component is placed into a frame by setting a set of
	    GridBagConstraints  values.
	   These values are used to display the current component according to
	   the previous one. The order by which the fields are added is important for
	   that reason. 
	   Methods cancel(), isModified(), applyModification() are used to manage
	   interactive edition of each field in the same way than explain 
	   before . 
	   The method isOK(), returns true if the new value of this field is allowed.
	   The Preferences manager records user's changes of a field only if that field
           has isOk() == true . Examples of non-trivial isOK() method can be
	   found in String field when the
	    string constraints are  
	   Integers. 
	 
	  Notification of changes
	  A PrefField can also be used to get notice of change of a value by the user.
	  If a manager wants to be notified when the user selects  a new value for a PrefField,
	  it registers the class name responsible to deal with these changes. A PrefField	  
	  allows to register a class by a call to the method registerForNotify(className).
	  The className must be a fully qualified description of the class like in
	  "semper.preferences.Test.BuildPref". In addition the className
	  must represents a class which implements the
	 PrefNotify interface. 
	  Each time a new value is selected for a PrefField, each registered class
	  will be called with the names of the group and the field as input to the
	  notifyChange(groupName,fieldName) method.
	  It is the responsability of the PrefNotify implementation to
	  deal with the change of value. For more details consult the
	 BuildPref example.
	 
	 The notification is called on button reaction and thus during evant handling. If on
	 notification some interactive process has to be launched, a thread should be 
	 started in order for the calling process to return from the call.
 
	Other classes are needed to help the three others:
   -      PrefFrame  is a frame allowing to put each 
	   field appearance. This frame
	   has a GridBagConstraints layout to allow flexible display. The PrefFrame
	   intercept an update of the values selected by the user after interactive
	   edition, a reset of changes  and a cancel of these modifications. 
	   The add(comp, csts) method
           is used to add a new component comp with the constraints csts to the
	   frame.
    
 -    The other classes: 
	   
	    are all subclasses of PrefField. 
		They define different field with different appearance. The field
	    PrefFieldNegotiable allows to define
	   fields to represent priority lists. The field looks like 2 lists of items,
	   the first one contains a list of unused items while the other is
	   the priority list itself. By selecting one element from the unused list
	   and one from the priority list the user indicate that the selected unused 
	   item will be added in the priority list at the selected position. If no
	   poisition is selected in the priority list, the new item is added 
	   in last position. It is also possible to select an item in the priority list
	   and put it back in the unused list.
	   
	   The PrefFieldPassWord class implements preferences fields dealing with passwords.
	   It is possible to associate to a password a preferences field allowing to modify it.
	   A  PrefFieldPassWord appears like a button on a preferences group. 
	   When the user press the button, the control is given to the TINGUIN for asking
	   the user to enter the password to change. If the user succeeds then (s)he is asked
	   to select a new password by giving it twice. The change is processed if at the end
	   the user press the "use" button of the preferences group. 
	 
 
 How to create a Negotiation Field (other fields are similar)? 
Just by specifying the available items, the fieldname and the formatting
constraints (optional).
String it[] = new String[6];
it[0] = new String( "item 1" ); 
it[1] = new String( "item 2" ); 
it[2] = new String( "item 3" ); 
it[3] = new String( "item 4" ); 
it[4] = new String( "item 5" ); 
it[5] = new String( "item 6" ); 
PrefFieldNegotiable neg1 = new PrefFieldNegotiable( new String("neg1"),
								    it,
								    4,
								    cs);
Here  cs  is the constraints for the position of that field in the group. They
are GridBagConstraints from the stantard awt package. If you are not concern
with these constraints, you always have access to a constructor with no 
constraints. In that case defaults are used. Every field is then put one
below the previous one. From the previous exemple: 
		PrefFieldNegotiable neg1 = new PrefFieldNegotiable( new String("neg1"),
                                                                    it,
                                                                    4);
 
Now the description for that field can be set by
	neg1.setDescription("The description intendended to the user. /n This will appear when the left
	mouse button  is doubleclicked.");
The surface of reaction to the double-clicked depends on the particular field. A PrefFieldString
for instance, does not react on double-clicking over the text area but just on the label
area. A PrefFieldList does not react on the list component but everywhere else.
Therefore it is possible that before getting the description the mous has to be moved a bit.
 How to create a Group? 
	groupe1 = new PrefGroup(new String("G1"), new String("Group 1")); 
	groupe2 = new PrefGroup(new String("G2"),new String("Group 2"));
This two lines create two groups . To put a field in a group just call the
method put() provides by the PrefGroup class. To add neg1 in the group
groupe1 just perform:
			groupe1.put(neg1);
You just have to continue like that until all fields are added in the group.
For more details on how to create groups see the PrefTestC.java file in the
Test directory.
How to create a Preferences environment?
	To create a preferences environment, you just have to add group
in the Preferences class. If groupe1 and groupe2 have already been defined,
you can add them by doing:
			Preferences.addGroup(groupe1); 
			Preferences.addGroup(groupe2); 
How to create subgroups?
In order to create a menu structure from which the user
selects the group he wants to edit, the following can be used. Assume
that group1,group2 and group3 have been defined and added to the preferences
manager like described above:
		Preferences.addToSubGroup(groupe2.getName(),"SuperGroup");
		Preferences.newSubGroupBelow("SuperGroup2","SuperGroup");
		Preferences.addToSubGroup(groupe3.getName(),"SuperGroup2");
The result is that:
	- group1 is accessible from the first level of the preferences menu
	
 - group2 is accessible in the submenu SuperGroup
	
 - group3 is accessible in the submenu SuperGroup2 which is a subgroup
	    of SuperGroup.
 
By default when a new group is added to the preferences manager whithout specifiying
in which subgroup it will appear, the group will be put at the root level. That means
that the group will be accessible at the first level of the menu structure.
Do not confuse groups and subgroups, they are different things. A group is
a PrefGroup object while a subgroup is just a string. Subgroups are only
used to display the menu structure. For the preferences manager all 
preferences groups are at the same level.
In order to retrieve the menu structure currently defined in the preferences manager
one should use:
	Preferences.getMenuStruct(pref_menu); 
where pref_menu is an object of class java.awt.Menu.
How to get the values?
	To get the values for a particular field, you must first retrieve
the group which contains the field you are looking for:
			group = Preferences.getGroup("G1"); 
Now group contains the group having the name "G1". Then you can get the 
the field with name "neg1" by doing:
			field = group.get("neg1");
The field value is then obtain by calling:
			val = field.getVal(); 
In that case, since that field is PrefFieldNegotiable field type the value
returned by getVal() is a vector. Thus, val.size() is the size for that vector
and val[i] contains the i^th string items in priority selected by the user.
Also available is the  Test  package where you
can learn how to use the Preferences manager by examples.
 Date: August, 1996 .