Listing of Source ../source/GOF/GofSpinButtonIdentifier.javapackage se.entra.phantom.server;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* This class identifies spin button controls for the Gui-on-the-fly, from unused
* GofHostFields. Will only spin buttons with numerical ranges.
* @author J. Bergström
*/
public class GofSpinButtonIdentifier extends GofControlIdentifierAdapter implements PhantomControlType
{
// ------------------
// INSTANCE VARIABLES
// ------------------
/**
* The start indicator for a range specification.
* <p>
* Defaults to "(".
*/
private String spinRangeStart = "(";
/**
* The end indicator for a range specification.
* <p>
* Defaults to ")".
*/
private String spinRangeEnd = ")";
/**
* The separator between the start and end values.
* <p>
* Defaults to "-".
*/
private String spinValueSep = "-";
/**
* Flag indicating where to search for the spin button, and in what order if multiple search.
* <p>
* The following values are valid:
* <pre>
* 0 Do not search for spin button.
* 1 Only search the preceding lead text.
* 2 Only search the trailing lead text.
* 3 First search the preceding, then the trailing lead text.
* 4 First search the trailing, then the preceding lead text.
* </pre>
*/
private int spinSearch = 0;
/**
* Filler character if there is one. Will be <coed>null</code> otherwise.
*/
private String spinFieldFiller;
/**
* Indicates the way the spin button's layout will be created.
* Valid values are:
* <pre>
* DEFAULT
* FONT
* COLOR
* FONTANDCOLOR
* </pre>
*/
private String layout;
/*
* Flag indicating if we should always use an editable or un-editable spin button.
* Defaults to un-editable.
*/
//private boolean isAlwaysEditable = false;
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Loads setting for the controll from the server ini-file.
* <p>
* For the identification of spin buttons, the following settings are used:
* <pre>
* spinrangestart The start indicator for a value range.
* spinrangeend The end indicator for a value range.
* spinvaluesep The separator between the range values.
* </pre>
* There are also several possibilities of where the spin button indicator can
* be placed relative to the entry field that will be replaced by the spin button.
* The indicator can either be in the preceding lead text or in the trailing
* lead text.
* <p>
* The setting spinsearch will tell this class where to look for the spin button
* indicator, and in what order to search if multiple places are to be searched.
* <p>
* Valid values are:
* <pre>
* pre Search the preceding lead text.
* post Search the trailing lead text.
* </pre>
* It is also possible to force the spin button to always be created as an editable
* spin button. This is specified in the spinalwayseditable setting.
* <pre>
* spinalwayseditable=1
* </pre>
* There is also a setting that specifies if there is a filler character to use,
* and what character this should be. This setting is called spinfieldfiller, and
* if the filler character were the underscore character, it would look like this:
* <pre>
* spinfieldfiller=_
* </pre>
* This class also uses a setting that affects the look of the spin buttons. This
* is the spinlayout setting. Valid values for this setting are:
* <pre>
* spinlayout=DEFAULT
* spinlayout=FONT
* spinlayout=COLOR
* spinlayout=FONTANDCOLOR
* </pre>
* DEFAULT means that no settings are taken from the template panel; default values will be
* used instead.
* <p>
* FONT means that the font is taken from template panel, from a combination box with the
* id=SB or SBE (SB is for non-editable combination boxes, SBE is for editable combination
* boxes). If this control cannot be found, or if it is not a combination box control, default
* values will be used.
* <p>
* COLOR means that the color is taken from template panel, from a combination box with the
* id=SB or SBE (SB is for non-editable combination boxes, SBE is for editable combination
* boxes). If this control cannot be found, or if it is not a combination box control, default
* values will be used.
* <p>
* FONTANDCOLOR means that the font and color are taken from template panel, from a combination
* box with the id=SB or SBE (SB is for non-editable combination boxes, SBE is for editable
* combination boxes). If this control cannot be found, or if it is not a combination box control,
* default values will be used.,
* <p>
* Any other value will be treated as DEFAULT.
* @param confFile The server ini file.
*/
@Override
public void getControlSettings( IniFile confFile, String subsection )
{
String setting;
setting = confFile.getData( subsection, "spinrangestart" );
if( setting != null )
spinRangeStart = setting;
setting = confFile.getData( subsection, "spinrangeend" );
if( setting != null )
spinRangeEnd = setting;
setting = confFile.getData( subsection, "spinvaluesep" );
if( setting != null )
spinValueSep = setting;
setting = confFile.getData( subsection, "spinsearch" );
spinSearch = parseSpinSearch( setting );
setting = confFile.getData( subsection, "spinfieldfiller" );
if( setting != null && setting.equals( "" ) == false )
spinFieldFiller = setting;
else
spinFieldFiller = null;
layout = confFile.getData( subsection, "spinlayout" );
if( layout == null )
layout = "DEFAULT";
/*
setting = confFile.getData( subsection, "spinalwayseditable" );
if( setting != null )
{
if( setting.equals( "1" ) == true )
isAlwaysEditable = true;
}*/
}
/**
* Identifies all the spin-button controls from the <code>GofHostFields</code>.
* <p>
* The identification of spin buttons are done by searching for a lead text that
* indicates an entry field that could be replaced by a spin button. A lead text
* indicating a spin button should have a start indicator, an end indicator and
* two values separated by a separator. The start indicator is usually a start
* parenthesis, the end indicator is usually an end parenthesis, and the separator
* is usually a hyphen. But these are configurable in the configuration file.
* <p>
* After a lead text has been identified to hold a spin button indicator, it checks
* if the next or previous field is an entry field, and that it is on the same line.
* There is a configuration that determines if the lead text should be before the
* entry field, or after, or if both are accepted, and if so, in which order to search.
* @param gofRuntime The GuiOnTheFlyRuntime instance.
* @param areaIdentifier The areaIdentifier in which the controls should be identified.
* @param phantomHostScreen The Phantom host screen corresponding to the host screen.
* @param hostScreen The host screen that we are trying to build a GOF panel for.
* @param newPanel The newly created Gui-on-the-fly runtime panel.
* @param offsetX The offset in columns for popup window.
* @param offsetY The offset in lines for popup window.
*/
@Override
public void identifyCtrls( GuiOnTheFlyRuntime gofRuntime,
GofHostAreaIdentifier areaIdentifier,
PhantomHostScreen phantomHostScreen,
HostScreen hostScreen,
PhantomPanelData templPanel,
PhantomPanelData newPanel,
int offsetX,
int offsetY )
{
this.templPanel = templPanel;
Vector<GofHostField> gofHostFields = areaIdentifier.getAreasGofHostFields( );
for( int i = 0, s = gofHostFields.size( ); i < s; i++ )
{
GofHostField gofHostField = gofHostFields.elementAt( i );
if( gofHostField.hasBeenProcessed == false && gofHostField.isProtected( ) == true && gofHostField.isEmpty( ) == false )
{
String text = gofHostField.getText( );
int sp = text.indexOf( spinRangeStart );
int ep = text.indexOf( spinRangeEnd, sp + 1 );
if( sp > -1 && ep > -1 )
{
String spintext = text.substring( sp + 1, ep );
int vseppos = spintext.indexOf( spinValueSep );
if( vseppos > -1 )
{
int[] range = getMaxAndMinValue( spintext, vseppos );
if( range[0] > 0 && range[1] > 0 )
{
boolean wasFound;
boolean doLoop = true;
int curSpinSearch = spinSearch;
int j = 0;
while( doLoop )
{
switch( curSpinSearch )
{
case 1:
case 3:
j++;
break;
case 2:
case 4:
j--;
break;
default:
doLoop = false;
}
int curElement = i + j;
if( gofHostFields.size( ) > curElement && curElement > 0 )
{
GofHostField nxtGofHostField = gofHostFields.elementAt( curElement );
if( gofHostField.getY( ) == nxtGofHostField.getY( ) )
{
if( nxtGofHostField.isProtected( ) == false && nxtGofHostField.isEmpty( ) == false )
{
wasFound = convertFieldToSpinb( range,
nxtGofHostField,
areaIdentifier,
phantomHostScreen,
hostScreen,
newPanel,
offsetX,
offsetY );
if( wasFound == true )
doLoop = false;
else
{
switch( curSpinSearch )
{
case 3:
j = 0;
curSpinSearch = 2;
break;
case 4:
j = 0;
curSpinSearch = 1;
break;
default:
doLoop = false;
}
}
}
else
{
switch( curSpinSearch )
{
case 3:
j = 0;
curSpinSearch = 2;
break;
case 4:
j = 0;
curSpinSearch = 1;
break;
}
}
}
else
doLoop = false; // We have switched line, don't continue.
}
else
doLoop = false;
}
}
}
}
}
}
}
/**
* This method tries to found numeric values on each side of the spin-button value separator.
* @param text The text string that hopefully includes the min and max value.
* @param seppos The position of spin value separator in the string.
* @return An array of two elements containing the min and max value, or zero for both the
* min and max value.
*/
private int[] getMaxAndMinValue( String text, int seppos )
{
int[] values = new int[2];
values[0] = 0;
values[1] = 1;
// Check if separator is first or last character, if so, no range.
if( seppos == 0 || seppos == text.length( ) - 1 )
return values;
String startNum = "";
String endNum = "";
// Get start value as string.
int p = seppos - 1;
char c = text.charAt( p );
while( c >= '0' && c <= '9' )
{
startNum = text.substring( p, p + 1 ) + startNum;
p--;
if( p < 0 )
break;
c = text.charAt( p );
}
// If start value equals empty string, no range.
if( startNum.equals( "" ) == true )
return values;
// Get end value as string.
p = seppos + 1;
c = text.charAt( p );
while( c >= '0' && c <= '9' )
{
endNum = text.substring( p, p + 1 ) + endNum;
p++;
if( p >= text.length( ) )
break;
c = text.charAt( p );
}
if( endNum.equals( "" ) == true )
return values;
// Try and convert the strings representing the start and end value into int values.
int v1, v2;
try
{
v1 = Integer.valueOf( startNum ).intValue( );
v2 = Integer.valueOf( endNum ).intValue( );
}
catch( NumberFormatException e )
{
values[0] = 0;
values[1] = 0;
return values;
}
if( v1 < v2 )
{
values[0] = v1;
values[1] = v2;
}
else
{
values[0] = v2;
values[1] = v1;
}
return values;
}
/**
* Tries to convert an entry field to a spin button.
* <p>
* Before the creation of the PhantomCComboBox, a check will be done to se if the text in the host field
* is included in the list.
* @param areaIdentifier The areaIdentifier in which the controls should be identified.
* @param phantomHostScreen The Phantom host screen corresponding to the host screen.
* @param hostScreen The host screen that we are trying to build a GOF panel for.
* @param newPanel The newly created Gui-on-the-fly runtime panel.
* @param offsetX Offset in columns used for popup windows.
* @param offsetY Offset in lines used for popup windows.
* @return <code>true</code> if the GofHostField was converted to a spin button box,
* <code>false</code> otherwise.
*/
private boolean convertFieldToSpinb( int[] range,
GofHostField gofHostField,
GofHostAreaIdentifier areaIdentifier,
PhantomHostScreen phantomHostScreen,
HostScreen hostScreen,
PhantomPanelData newPanel,
int offsetX,
int offsetY )
{
if( gofHostField.hasBeenProcessed == false &&
gofHostField.isProtected( ) == false &&
gofHostField.isEmpty( ) == false )
{
HostField hf = gofHostField.getHostField( );
int x = gofHostField.getX( );
int y = gofHostField.getY( );
int cx = gofHostField.getCx( );
//String orgtext = gofHostField.getText( );
// Get template values
/*
int font = -1;
int foregroundColor = -1;
PhantomControl templateControl = null;
if( isAlwaysEditable == false )
templateControl = templPanel.getControlFromID( "SB" );
else
templateControl = templPanel.getControlFromID( "SBE" );
if( layout.equals( "FONT" ) )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_SPIN )
font = ( ( PhantomCSpinButton )templateControl ).font;
}
else if( layout.equals( "COLOR" ) )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_SPIN )
foregroundColor = ( ( PhantomCSpinButton )templateControl ).getForegroundColor();
}
else if( layout.equals( "FONTANDCOLOR" ) )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_SPIN )
{
font = ( ( PhantomCSpinButton )templateControl ).font;
foregroundColor = ( ( PhantomCSpinButton )templateControl ).getForegroundColor();
}
}*/
// Create the base control.
PhantomControlBase bc = new PhantomControlBase( GOF_MARGINX + ( x - offsetX ) * GOF_STEPX,
GOF_MARGINY + ( y - offsetY ) * GOF_STEPY,
cx * GOF_GUIUNITX + 15,
GOF_GUIUNITY,
CTRLTYPE_SPIN );
// Create the PhantomHostField.
PhantomHostField phf = new PhantomHostField( phantomHostScreen, hostScreen, hf );
if( spinFieldFiller != null )
{
phf.filler = spinFieldFiller.charAt( 0 );
phf.flags = PhantomHostField.FORMAT_STRIPEND;
}
phantomHostScreen.addHostField( phf );
// Create the spin button.
PhantomCSpinButton sb = new PhantomCSpinButton( newPanel, bc, phf, range );
// Add the spin button.
newPanel.addControl( sb );
areaIdentifier.addControl( sb );
gofHostField.hasBeenProcessed = true;
return true;
}
return false;
}
/**
* Parses the spin search setting, and converts into a flag value.
* @param setting The setting from the server.ini file.
* @return The value for the spin search flag.
*/
private int parseSpinSearch( String setting )
{
if( setting == null || setting.equals( "" ) )
return 0;
int flag = 0;
StringTokenizer st = new StringTokenizer( setting, ", " );
while( st.hasMoreTokens( ) )
{
String s = st.nextToken( );
switch( flag )
{
case 1:
if( s.equals( "pre" ) )
flag = 1;
else if( s.equals( "post" ) )
flag = 3;
break;
case 2:
if( s.equals( "pre" ) )
flag = 4;
else if( s.equals( "post" ) )
flag = 2;
break;
default:
if( s.equals( "pre" ) )
flag = 1;
else if( s.equals( "post" ) )
flag = 2;
}
}
return flag;
}
}