Listing of Source ../source/GOF/GofListBoxIdentifier.javapackage se.entra.phantom.server;
import java.util.StringTokenizer;
import java.util.Vector;
import java.io.IOException;
import java.util.NoSuchElementException;
/**
* This class identifies list box controls for the Gui-on-the-fly, from unused GofHostFields.
* This class will only try to identify selectable lists.
* @author J. Bergström
*/
@SuppressWarnings("unchecked")
public class GofListBoxIdentifier extends GofControlIdentifierAdapter implements PhantomControlType
{
// ------------------
// INSTANCE VARIABLES
// ------------------
/**
* The minimum number of lines (excluding the header) required in a listbox.
* Default is 2.
*/
private int minLines = 2;
/**
* The minimum number of columns required in a listbox.
* Default is 2.
*/
private int minColumns = 2;
/**
* The max number of lines to search for the header fields.
* Default is 1.
*/
private int maxheaderlines = 1;
/**
* The maximum number of character allowed for the selection field.
* Default is 2.
*/
private int maxselfieldlength = 2;
/**
* Flag indicating that a continuation mark has been found on the screen.
*/
private boolean hasContMark;
/**
* The last line to search for a list. If a list continuation mark has been found, this will
* be the same line as this is on, otherwise it will be screen's last line.
*/
private int lastLine;
/**
* Filler character if there is one. Will be <code>null</code> otherwise.
*/
private String listFieldFiller;
/**
* A list that indicates the way the list box's layout will be created.
* Valid values are:
* <pre>
* DEFAULT
* FONT
* COLOR
* LINES
* </pre>
*/
private Vector<String> layout = new Vector<String>( );
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Loads setting for the control from the server ini-file.
* <p>
* There are three settings for the list box that can be specified in the
* configuration file. They are the three below, with typical values.
* <pre>
* listboxmincols=2
* listboxminlines=2
* listboxmaxheaderheight=2
* </pre>
* <p>
* There are four settings for the list box that can be specified in the
* configuration file. They are the four listed below, with typical values.
* <pre>
* listboxmincols=2
* listboxminlines=2
* listboxmaxheaderheight=2
* listboxmaxsellength=2
* </pre>
* The listboxmincols specifies the minimum number of columns required in a
* list box candidate for a list box control. The default value is two.
* <p>
* The listboxminlines specifies the minimum number of lines required in a
* list box candidate for a list box control. The default value is two.
* <p>
* The listboxmaxheaderheight specifies the maximum number of lines to search
* for the column headers. The default value is one.
* <p>
* 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 listfieldfiller,
* and if the filler character were the underscore character, it would look like
* this:
* <pre>
* listfieldfiller=_
* </pre>
* This class has a setting that affects the look of the entry fields. This is
* the listboxlayout setting. Valid values for this setting are:
* <pre>
* listboxlayout=DEFAULT
* listboxlayout=FONT
* listboxlayout=COLOR
* listboxlayout=LINES
* </pre>
* DEFAULT means that no settings are taken from the template panel; default
* values will be used instead.
* <p>
* FONT means that the fonts are taken from template panel, from a list box
* with the id=LISTB. If this control cannot be found, or if it is not an
* output text control, default values will be used. Both the header font
* and the list font are taken from the template list box.
* <p>
* COLOR means that the colors are taken from template panel, from a list
* box with the id=LISTB. If this control cannot be found, or if it is not
* an output text control, default values will be used. The colors that
* will be taken from the template list box are background- and the
* foreground colors for both the header and the list.
* <p>
* LINES means that all the line settings from template panel, from a list
* box with the id=LISTB. If this control cannot be found, or if it is not
* an output text control, default values will be used. The settings that
* are taken from the template list box are line between columns, line
* between headers, line between header and column and the line between lines.
* <p>
* Any other value will be ignored.
* <p>
* All these layout settings can be combined in a suitable way. For example,
* if FONT, COLOR and LINES were wanted, the setting would look like this:
* <pre>
* listboxlayout=FONT COLOR LINES
* </pre>
* @param confFile The server ini file.
* @param subsection The name of the GOF subsection that we are currently loading settings from.
*/
@Override
public void getControlSettings( IniFile confFile, String subsection )
{
String setting;
setting = confFile.getData( subsection, "listboxmaxheaderheight" );
if( setting != null )
{
try
{
maxheaderlines = Integer.valueOf( setting ).intValue( );
}
catch( NumberFormatException e )
{
}
}
setting = confFile.getData( subsection, "listboxminlines" );
if( setting != null )
{
try
{
minLines = Integer.valueOf( setting ).intValue( );
}
catch( NumberFormatException e )
{
}
}
setting = confFile.getData( subsection, "listboxmincols" );
if( setting != null )
{
try
{
minColumns = Integer.valueOf( setting ).intValue( );
}
catch( NumberFormatException e )
{
}
}
setting = confFile.getData( subsection, "listfieldfiller" );
if( setting != null && setting.equals( "" ) == false )
listFieldFiller = setting;
else
listFieldFiller = null;
setting = confFile.getData( subsection, "listboxlayout" );
parseLayoutString( setting, layout );
setting = confFile.getData( subsection, "listboxmaxsellength" );
if( setting != null )
{
try
{
maxselfieldlength = Integer.valueOf( setting ).intValue( );
}
catch( NumberFormatException e )
{
}
}
}
/**
* Identifies all the list box controls from the <code>GofHostFields</code>.
* The identification of list boxes is done in several steps.
* <p>
* First the identification process goes through all unused GofHostFields, and
* creates column elements from them. GofHostFields in consecutive lines that
* starts in the same column, and has the same width, will be placed in a single
* column element.
* <p>
* In the second step, the identification process will go through all column elements,
* and create list elements from them. Column elements starting on the same line and
* with the same height are considered to belong to a single list element. When
* comparing the column elements start line to each other, consideration is taken that
* a column header might have been included at the top of some of the column elements.
* So if one starts, for example, one line above the other, but they end at the same
* line, they will still be considered to belong to the same list element. The first
* line in the column that started one line earlier will be used in the header.
* <p>
* Next, the identification process will check if a list element has the minimum
* number of lines and columns required for a list. The minimum number of lines and
* columns are specified in the configuration file. It will also check if the list
* element has texts or entry fields to left, if so it will not be considered a
* candidate for a list box. This means that the list box should be the first
* control from the left. This will always be true for a list in an AS/400
* application created as a subfile.
* <p>
* The list box candidates left will be checked if the first column (NOTYET! The last)
* is editable and has a maximum width not greater than the value specified for the
* listboxmaxsellength setting. Then this column is accepted as a selection column,
* and the list accepted as a list box.
* <p>
* As a last step the identification process will try and find the column headers, before
* creating the list box.
* @param areaIdentifier The areaIdentifier in which the entry fields 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.
*/
@SuppressWarnings("rawtypes")
@Override
public void identifyCtrls( GuiOnTheFlyRuntime gofRuntime,
GofHostAreaIdentifier areaIdentifier,
PhantomHostScreen phantomHostScreen,
HostScreen hostScreen,
PhantomPanelData templPanel,
PhantomPanelData newPanel,
int offsetX,
int offsetY )
{
this.templPanel = templPanel;
//prevHeadGce = null;
Vector<GofHostField> gofHostFields = areaIdentifier.getAreasGofHostFields( );
int scrnCx = hostScreen.getWidth( );
int scrnCy = hostScreen.getHeight( );
Object attrib = gofRuntime.getAttribute( "hasListCont" );
if( attrib != null )
hasContMark = ( ( Boolean )attrib ).booleanValue( );
else
hasContMark = false;
attrib = gofRuntime.getAttribute( "lastListLine" );
if( hasContMark == true && attrib != null )
lastLine = ( ( Integer )attrib ).intValue( );
else
lastLine = scrnCy;
Vector[] gceMap = createColumnElements( gofHostFields, scrnCx );
Vector[] gleList = createListElements( gceMap, scrnCy, scrnCx );
for( int i = 0; i < scrnCy; i++ )
{
Vector v = gleList[i];
for( int j = 0, s = v.size( ); j < s; j++ )
{
GofListElement gle = ( GofListElement )v.elementAt( j );
if( gle.colCount( ) >= minColumns && gle.height >= minLines && gle.isLeftColLeftmost( gceMap ) == true )
createListBox( gle, phantomHostScreen, hostScreen, newPanel, gceMap, offsetX, offsetY );
}
}
}
/**
* Creates column elements. GofHostFields in consecutive lines that starts in the
* same column, and has the same width, will be placed in a single column element.
* @param gofHostFields The GofHostFields to analyze.
* @param scrnCx The width of the area to analyze.
* @return An array of <code>Vectors</code> containing all the column elements.
* A column element will placed in the Vector that is in the element with
* the index equal to the column elemet'ss start column.
*/
@SuppressWarnings("rawtypes")
private Vector[] createColumnElements( Vector<GofHostField> gofHostFields, int scrnCx )
{
Vector[] gceList = new Vector[scrnCx];
for( int x = 0; x < scrnCx; x++ )
gceList[x] = new Vector( );
for( int i = 0, s = gofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = gofHostFields.elementAt( i );
int x = ghf.getX( );
int y = ghf.getY( );
if( y > lastLine )
break;
GofColumnElement prevGce;
try
{
prevGce = ( GofColumnElement )gceList[x].lastElement( );
}
catch( NoSuchElementException e )
{
prevGce = null;
}
int cx = ghf.getCx( );
if( prevGce != null && ( prevGce.startLine + prevGce.height ) == y && prevGce.width == cx )
{
prevGce.addGofHostField( y, ghf );
}
else
{
GofColumnElement gce = new GofColumnElement( x, y, ghf );
gceList[x].addElement( gce );
}
}
return gceList;
}
/**
* Creates list elements from column elements starting on the same line, and with
* the same height are considered to belong to a single list element. When comparing
* the column elements start line to each other, consideration is taken that a column
* header might have been included at the top of some of the column elements, so if one
* starts, for example, one line above the other, but they end at the same line, they
* will still be considered to belong to the same list element. The first line in the
* column that started one line earlier will be used in the header.
* @param gceList An array of Vectors holding all the column elements.
* @param scrnCy The height of the area to analyze.
* @param scrnCx The width of the area to analyze.
* @return An array of vectors containing all the list elements. A list element will
* be placed in the Vector in the element with the index equal to the start
* line for the list element.
*/
@SuppressWarnings("rawtypes")
private Vector[] createListElements( Vector[] gceList, int scrnCy, int scrnCx )
{
Vector[] gleList = new Vector[scrnCy];
for( int y = 0; y < scrnCy; y++ )
gleList[y] = new Vector( );
for( int x = 0; x < scrnCx; x++ )
{
for( int i = 0, s = gceList[x].size( ); i < s; i++ )
{
GofColumnElement gce = ( GofColumnElement )gceList[x].elementAt( i );
int y = gce.startLine;
GofListElement prevGle = getPrevListElement( gleList, y, gce.height );
int yOffs = 0;
while( prevGle == null && yOffs < maxheaderlines )
{
yOffs++;
prevGle = getPrevListElement( gleList, y + yOffs, gce.height - yOffs );
}
if( prevGle != null )
{
prevGle.addGofColumnElement( gce );
gce.offset = yOffs;
}
else
{
GofListElement gle = new GofListElement( x, y, gce );
gleList[y].addElement( gle );
}
}
}
return gleList;
}
/**
* Gets the previous list element that starts on the same row.
* @param gleList An array of Vectors containing all the list elements.
* @param y The required start line.
* @param cy The required height.
* @return If no previous list element exists, or if the previous list
* element's height does not equal the specified height, or has
* a height less that minimum lines, <code>null</code> will be returned,
* otherwise the previous list element will be returned.
*/
@SuppressWarnings("rawtypes")
private GofListElement getPrevListElement( Vector[] gleList, int y, int cy )
{
GofListElement prevGle;
try
{
prevGle = ( GofListElement )gleList[y].lastElement( );
if( prevGle.height != cy || prevGle.height < minLines )
prevGle = null;
}
catch( NoSuchElementException e )
{
prevGle = null;
}
return prevGle;
}
/**
* Creates a listbox from a listbox element.
* <p>
* The list box element will be checked if the first column (NOTYET! The last)
* is editable and has a maximum width of two characters. Then this column is
* accepted as a selection column, and the list accepted as a list box.
* <p>
* As a last step the identification process will try and find the column headers,
* before creating the list box.
* @param gle The list box element that should be converted to a list box.
* @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 gceMap
*/
@SuppressWarnings("rawtypes")
private void createListBox( GofListElement gle,
PhantomHostScreen phantomHostScreen,
HostScreen hostScreen,
PhantomPanelData newPanel,
Vector[] gceMap,
int offsetX,
int offsetY )
{
int listX = 0, listY = 0, listXx = 0, listYy = 0;
int headCy = 0;
int s = gle.listsGofColumnElements.size( );
GofListColumnElement[] lce = new GofListColumnElement[s];
for( int i = 0; i < s; i++ )
{
GofColumnElement gce = gle.listsGofColumnElements.elementAt( i );
boolean isEditable = gce.isEditable( );
int x = gce.startCol;
int y = gce.startLine + gce.offset;
int cx = gce.width;
int cy = gce.height - gce.offset;
int colCx;
if( ( i == 0 && isEditable == false ) || ( i == 0 && cx > maxselfieldlength ) )
return;
gce.markAsProcessed( );
if( i < s - 1 )
{
// Not last column.
GofColumnElement nxtgce = gle.listsGofColumnElements.elementAt( i + 1 );
colCx = nxtgce.startCol - x;
}
else
colCx = cx;
if( listX == 0 || x < listX )
listX = x;
if( listY == 0 || y < listY )
listY = y;
if( listXx == 0 || x + cx > listXx )
listXx = x + cx;
if( listYy == 0 || y + cy > listYy )
listYy = y + cy;
String headText = "";
if( maxheaderlines > 0 )
{
if( gce.offset == maxheaderlines )
{
// Get header from top of column.
headText = gce.getHeadText( );
}
else if( gce.offset < maxheaderlines && gce.offset > 0 )
{
// Get header from column element(s) above column.
headText = getHeader( x, y, cx, gce.offset, gceMap );
// Get header from top of column.
String colHeadText = gce.getHeadText( );
if( headText.equals( "" ) == false )
headText = headText + "\r\n" + colHeadText;
else
headText = colHeadText;
}
else
{
// Get header from column element(s) above column.
headText = getHeader( x, y, cx, gce.offset, gceMap );
}
}
int hh = 0;
if( !headText.equals( "" ) )
{
hh = 1;
int p = headText.indexOf( "\n" );
while( p > -1 )
{
hh++;
p = headText.indexOf( "\n", p + 1 );
}
}
int newHcy = hh * GOF_STEPY;
if( newHcy > headCy )
headCy = newHcy;
PhantomHostField phf = new PhantomHostField( phantomHostScreen, hostScreen, x, y, cx, cy );
if( listFieldFiller != null )
{
phf.filler = listFieldFiller.charAt( 0 );
phf.flags = PhantomHostField.FORMAT_STRIPEND;
}
phantomHostScreen.addHostField( phf );
GofListColumnElement gofListColumnElement = new GofListColumnElement( phf, colCx, isEditable, headText.trim( ) );
lce[i] = gofListColumnElement;
}
int font = -1;
int headFont = -1;
int color = 0;
int listBgColor = 0;
int headColor = 0;
int headerBgColor = 0;
int lineValues[] = new int[4];
PhantomControl templateControl = templPanel.getControlFromID( "LISTB" );
if( isReqLayout( "FONT" ) == true )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_LIST )
{
font = ( ( PhantomCListBox )templateControl ).font;
headFont = ( ( PhantomCListBox )templateControl ).headFont;
}
}
if( isReqLayout( "COLOR" ) == true )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_LIST )
{
color = ( ( PhantomCListBox )templateControl ).color;
listBgColor = ( ( PhantomCListBox )templateControl ).listBgColor;
headColor = ( ( PhantomCListBox )templateControl ).headColor;
headerBgColor = ( ( PhantomCListBox )templateControl ).headerBgColor;
}
}
if( isReqLayout( "LINES" ) == true )
{
if( templateControl != null && templateControl.controlBase.type == CTRLTYPE_LIST )
{
lineValues[0] = ( ( PhantomCListBox )templateControl ).divBetwCols;
lineValues[1] = ( ( PhantomCListBox )templateControl ).divBetwHeaders;
lineValues[2] = ( ( PhantomCListBox )templateControl ).divBetwHeadCol;
lineValues[3] = ( ( PhantomCListBox )templateControl ).lineBetwRows;
}
}
// Create the base control.
int listCx = listXx - listX;
int listCy = listYy - listY;
PhantomControlBase bc = new PhantomControlBase( GOF_MARGINX + ( listX - offsetX ) * GOF_STEPX,
GOF_MARGINY + ( listY - offsetY ) * GOF_STEPY - 1 - headCy,
listCx * GOF_STEPX,
listCy * GOF_STEPY + headCy,
CTRLTYPE_LIST );
try
{
PhantomCListBox lb = new PhantomCListBox( newPanel, bc, headCy, lineValues, lce );
lb.font = font;
lb.headFont = headFont;
lb.color = color;
lb.listBgColor = listBgColor;
lb.headColor = headColor;
lb.headerBgColor = headerBgColor;
newPanel.addControl( lb );
}
catch( IOException e )
{
}
}
/**
* Tries to found a header for a GofColumnElement.
* @param x The start column of the current column element.
* @param y The start line of the current column element.
* @param cx The width of he current column element.
* @param offset The columns elements offset. This is the number of lines above
* the list elements topline this column starts.
* @param gceMap An array of Vectors into which all the screens column elements are mapped.
* @return The header text, if one was found, otherwise an empty String.
*/
@SuppressWarnings("rawtypes")
private String getHeader( int x, int y, int cx, int offset, Vector[] gceMap )
{
String hText = "";
boolean hasBeenFound = false;
int headStartLine = y - maxheaderlines;
// First check current column's startcolumn.
for( int i = 0, s = gceMap[x].size( ); i < s; i++ )
{
GofColumnElement gce = ( GofColumnElement )gceMap[x].elementAt( i );
int sl = gce.startLine;
int el = sl + gce.height - 1;
if( sl >= headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is completely inside the lines where the header is allowed to be.
hText = gce.getText( 0, x, cx );
hasBeenFound = true;
break;
}
else if( sl < headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is starts above the first allowed header line,
// but ends inside the lines where the header is allowed to be.
hText = gce.getText( headStartLine - sl, x, cx );
hasBeenFound = true;
break;
}
}
if( hasBeenFound == false )
{
// Check startcolumns between the column's startcolumn and it's endcolumn.
int xx = x + 1;
int ss = x + cx;
while( xx < ss && hasBeenFound == false )
{
for( int i = 0, s = gceMap[xx].size( ); i < s; i++ )
{
GofColumnElement gce = ( GofColumnElement )gceMap[xx].elementAt( i );
int sl = gce.startLine;
int el = sl + gce.height - 1;
if( sl >= headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is completely inside the lines where the header is allowed to be.
hText = gce.getText( 0, xx, cx - ( xx - x ) + 1 );
hasBeenFound = true;
break;
}
else if( sl < headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is starts above the first allowed header line,
// but ends inside the lines where the header is allowed to be.
hText = gce.getText( headStartLine - sl, xx, cx - ( xx - x ) + 1 );
hasBeenFound = true;
break;
}
}
xx++;
}
}
if( hasBeenFound == false )
{
// Check startcolumns before the column's startcolumn.
int xx = x - 1;
while( xx >= 0 && hasBeenFound == false )
{
for( int i = 0, s = gceMap[xx].size( ); i < s; i++ )
{
GofColumnElement gce = ( GofColumnElement )gceMap[xx].elementAt( i );
int sl = gce.startLine;
int el = sl + gce.height - 1;
if( sl >= headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is completely inside the lines where the header is allowed to be.
hText = gce.getText( 0, x, cx );
hasBeenFound = true;
break;
}
else if( sl < headStartLine && sl < y + offset && el >= headStartLine && el < y + offset )
{
// A column object that is starts above the first allowed header line,
// but ends inside the lines where the header is allowed to be.
hText = gce.getText( headStartLine - sl, x, cx );
hasBeenFound = true;
break;
}
}
xx--;
}
}
return hText;
}
// ==================================================================
// GofColumnElement subclass
// ==================================================================
/**
* The GofColumnElement is a private inner class that is used to store information
* about the column elements created during the identification process of the list
* box. A column element is a column of one or more GofHostFields that starts in
* the same x-position, and has the same width.
* <p>
* In addition to some methods to set and retrieve information, it also contains
* some methods for retrieving column headers, one method that checks if the column
* element is editable.
* <p>
* The used GofColumnElements will be deleted when a new host screen is processed.
*/
private class GofColumnElement
{
// ------------------
// INSTANCE VARIABLES
// ------------------
/**
* A Vector containing all GofHostFields that is part of this column element.
*/
private Vector<GofHostField> colsGofHostFields;
/**
* The column elements startcolumn on the host screen.
*/
private int startCol;
/**
* The column elements startline on the host screen.
*/
private int startLine;
/**
* The width of the column element in characters.
*/
private int width;
/**
* The height of the column element in lines.
*/
private int height;
/**
* The offset at which the list starts. Will be zero if no header text is in the column element.
*/
private int offset = 0;
// -----------
// CONSTRUCTOR
// -----------
/**
* Creates a new Gof column element.
* @param x The column element's start column on the host screen.
* @param y The column element's start line on the host screen.
* @param ghf The first GofHostField that belongs to this column element.
*/
private GofColumnElement( int x, int y, GofHostField ghf )
{
startCol = x;
startLine = y;
width = ghf.getCx( );
height = 1;
colsGofHostFields = new Vector<GofHostField>( );
colsGofHostFields.addElement( ghf );
}
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Adds a GofHostField to this column element. The new GofHostField must be on
* the line following the last line in this column element.
* @param y The line on which this column element is located.
* @param ghf The GofHostField to add.
*/
private void addGofHostField( int y, GofHostField ghf )
{
height = y - startLine + 1;
colsGofHostFields.addElement( ghf );
}
/**
* Marks all the GofHostFields in this column element as processed.
*/
private void markAsProcessed( )
{
for( int i = 0, s = colsGofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = colsGofHostFields.elementAt( i );
ghf.hasBeenProcessed = true;
}
}
/**
* Checks if the column is editable. The column is considered editable if it has one
* ore more fields that is not protected.
* @return <code>true</code> if the column is editable, <code>false</code> otherwise.
*/
private boolean isEditable( )
{
boolean isEditable = false;
for( int i = 0, s = colsGofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = colsGofHostFields.elementAt( i );
if( ghf.isProtected( ) == false )
isEditable = true;
}
return isEditable;
}
/**
* Gets the header text from this column element. Depending on the offset,
* the text should be combined from the equal number of GofHostFiels.
* @return The header text.
*/
private String getHeadText( )
{
String text = "";
GofHostField ghf;
int i = 0;
while( i < offset )
{
ghf = colsGofHostFields.elementAt( i );
if( text.equals( "" ) == false )
text = text + "\r\n" + ghf.getText( );
else
text = ghf.getText( );
ghf.hasBeenProcessed = true;
i++;
}
return text;
}
/**
* Gets the text for this column element. If the column element contains several lines, the text
* from each line will be separated by CR + LF.
* @param yOffset The first line in this column element that the header should be read from.
* @param x The character column to start reading the header from.
* @param cx The width of the header text.
* @return The text from the column element.
*/
private String getText( int yOffset, int x, int cx )
{
String text = "";
for( int i = yOffset, s = colsGofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = colsGofHostFields.elementAt( i );
int ghfX = ghf.getX( );
int ghfCx = ghf.getCx( );
String ghfText = ghf.getText( );
if( ghfX <= x )
{
if( ghfX + ghfCx >= x + cx )
{
if( text.equals( "" ) )
text = ghfText.substring( x - ghfX, x - ghfX + cx );
else
text = text + "\r\n" + ghfText.substring( x - ghfX, x - ghfX + cx );
ghf.hasBeenProcessed = true;
}
else if( x - ghfX < ghfText.length( ) )
{
if( text.equals( "" ) )
text = ghfText.substring( x - ghfX );
else
text = text + "\r\n" + ghfText.substring( x - ghfX );
ghf.hasBeenProcessed = true;
}
}
}
return text;
}
}
// ==================================================================
// GofListElement subclass
// ==================================================================
/**
* The GofListElement is a private inner class that is used to store information
* about the list elements created during the identification process of the list
* box. A list element consists of one or more column elements, where all column
* elements start on the same line, and has the same height.
*/
private class GofListElement
{
// ------------------
// INSTANCE VARIABLES
// ------------------
/**
* A Vector containing all the column elements in the list element.
*/
private Vector<GofColumnElement> listsGofColumnElements;
/**
* The start column on the host screen for this list element.
*/
private int startCol;
/**
* The start line on the host screen for this list element.
*/
private int startLine;
/*
* The width in characters, on the host screen, for this list element.
*/
//private int width;
/**
* The height in lines for this list element.
*/
private int height;
// -----------
// CONSTRUCTOR
// -----------
/**
* Creates a new list element.
* @param x The start column for this list element.
* @param y The start line for this list element.
* @param gce The first column element in this list element.
*/
private GofListElement( int x, int y, GofColumnElement gce )
{
startCol = x;
startLine = y;
//width = gce.width;
height = gce.height;
listsGofColumnElements = new Vector<GofColumnElement>( );
listsGofColumnElements.addElement( gce );
}
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Adds a column element to this list element. Will first check if it is the same column element
* as the last column element already in the list element.
* @param gce The new column element to add.
*/
private void addGofColumnElement( GofColumnElement gce )
{
GofColumnElement lastGce;
try
{
lastGce = listsGofColumnElements.lastElement( );
}
catch( NoSuchElementException e )
{
lastGce = null;
}
if( lastGce.equals( gce ) == false )
{
//width = gce.startCol + gce.width - startCol + 1;
listsGofColumnElements.addElement( gce );
}
}
/**
* Gets the number of columns in the list box element.
* @return The number of columns.
*/
private int colCount( )
{
return listsGofColumnElements.size( );
}
/**
* Checks if the leftmost column has any column element to the left side.
* <p>
* A column element is considered to be on the left side, if it starts in a column to the left
* of the list's startcolumn, and if one of the following criteria matches:
* <ul>
* <li>
* A column element that starts above the list's first line, bat that stretches to, or past
* the first line in the list.
* </li>
* <li>
* A column element that starts between the list's first line and it's last line.
* </li>
* </ul>
* @param gceMap An arry of vectors containing all the columnelements on the screen.
* @return <code>true</code> if the selection column has no column element to the left,
* <code>false</code> otherwise.
*/
@SuppressWarnings("rawtypes")
private boolean isLeftColLeftmost( Vector[] gceMap )
{
for( int i = 0; i < startCol; i++ )
{
Vector v = gceMap[i];
for( int j = 0, s = v.size( ); j < s; j++ )
{
GofColumnElement gce = ( GofColumnElement )v.elementAt( j );
if( gce.startLine < startLine && gce.startLine + gce.height >= startLine )
return false;
else if( gce.startLine >= startLine && gce.startLine < startLine + height )
return false;
}
}
return true;
}
}
/**
* Parses the layout string into separate layout commands. Valid separators
* are blanks and commas.
* @param layoutStr The layout string from gof.ini
* @param layout A <code>Vector</code> where the layout commands will be stored.
*/
private void parseLayoutString( String layoutStr, Vector<String> layout )
{
if( layoutStr == null )
return;
StringTokenizer st = new StringTokenizer( layoutStr, ", " );
while( st.hasMoreTokens( ) )
{
String s = st.nextToken( ).trim( );
if( s.equals( "" ) == false )
layout.addElement( s );
}
}
/**
* Checks if a layout command is in the <code>Vector</code> containing the requested
* layout commands.
* @param str The layout command to check.
* @return <code>true</code> if the layout command was in the list,
* <code>false</code> otherwise.
*/
private boolean isReqLayout( String str )
{
boolean isReq = false;
for( int i = 0, s = layout.size( ); i < s; i++ )
{
String elem = layout.elementAt( i );
if( str.equals( elem ) == true )
{
isReq = true;
break;
}
}
return isReq;
}
}