home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 October
/
Chip_2001-10_cd1.bin
/
zkuste
/
delphi
/
kompon
/
d123456
/
CHEMPLOT.ZIP
/
TPlot
/
Parser.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2001-07-24
|
21KB
|
651 lines
unit Parser;
{$I Plot.inc}
{-----------------------------------------------------------------------------
The contents of this file are subject to the Q Public License
("QPL"); you may not use this file except in compliance
with the QPL. You may obtain a copy of the QPL from
the file QPL.html in this distribution, derived from:
http://www.trolltech.com/products/download/freelicense/license.html
The QPL prohibits development of proprietary software.
There is a Professional Version of this software available for this.
Contact sales@chemware.hypermart.net for more information.
Software distributed under the QPL is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the QPL for
the specific language governing rights and limitations under the QPL.
The Original Code is: Parser.pas, released 12 September 2000.
The Initial Developer of the Original Code is Mat Ballard.
Portions created by Mat Ballard are Copyright (C) 1999 Mat Ballard.
Portions created by Microsoft are Copyright (C) 1998, 1999 Microsoft Corp.
All Rights Reserved.
Contributor(s): Mat Ballard e-mail: mat.ballard@chemware.hypermart.net.
Last Modified: 04/18/2001
Current Version: 2.00
You may retrieve the latest version of this file from:
http://Chemware.hypermart.net/
This work was created with the Project JEDI VCL guidelines:
http://www.delphi-jedi.org/Jedi:VCLVCL
in mind.
Purpose:
To allow users to paste or import complex data into TPlot.
Known Issues:
-----------------------------------------------------------------------------}
interface
uses
Classes, SysUtils,
{$IFDEF WINDOWS}
WinTypes, WinProcs,
Buttons, ComCtrls, Controls, ExtCtrls, Forms, Graphics, Grids, StdCtrls,
{$ENDIF}
{$IFDEF WIN32}
Windows,
Buttons, ComCtrls, Controls, ExtCtrls, Forms, Graphics, Grids, StdCtrls,
{$ENDIF}
{$IFDEF LINUX}
QTypes, Types,
QButtons, QComCtrls, QControls, QExtCtrls, QForms, QGraphics, QGrids, QStdCtrls,
{$ENDIF}
Misc, PlotDefs;
type
TDelimiter = (dlNone, dlTab, dlComma, dlSpace, dlColon, dlSemiColon,
dlLineFeed, dlOwn);
const
COLUMN_NOS = 0;
SERIES_NAMES = 1;
FIRST_LINE_OF_DATA = 2;
X_OR_Y_OR_Z = 3;
DEPENDS_ON_X = 4;
Z_DATA_LINE = 5;
{Delimiters: array[TDelimiter] of string =
('', #9, ',', ' ', ';', ':', #10, 'Type your own');}
DelimiterNames: array[TDelimiter] of string =
(sNone, sTab, sComma, sSpace, sColon, sSemiColon, sLineFeed, sTypeYourOwn);
type
TColumnType = (ctIgnore, ctX, ctY);
TSeriesInfo = Record {The series are 0, 1, 2}
Index: Integer; {What is the Index of this series of data in the SeriesList ?}
XCol: Integer; {in which column is this series' X data ?}
XTextCol: Integer; {in which column is this series' X STRING data, if any ?}
YCol: Integer; {in which column is this series' Y data ?}
XSeriesIndex: Integer; {what is the index of the series that contains the X Data in the SeriesList ?}
XValue: Single; {the X Value, after a string conversion}
YValue: Single; {the Y Value, after a string conversion}
end;
{A TSeriesInfoArray is never declared directly - instead, it is used as a
template for a dynamic array}
TSeriesInfoArray = array[0..1023] of TSeriesInfo;
pSeriesInfoArray = ^TSeriesInfoArray;
TParserForm = class(TForm)
DataListBox: TListBox;
DelimiterLabel: TLabel;
DelimiterComboBox: TComboBox;
LineEdit: TEdit;
SetGroupBox: TGroupBox;
SeriesNamesButton: TButton;
FirstLineOfDataButton: TButton;
HelpBitBtn: TBitBtn;
BitBtn2: TBitBtn;
OKBitBtn: TBitBtn;
InfoGrid: TStringGrid;
PickXDataComboBox: TComboBox;
ZDataLineButton: TButton;
NoSeriesLabel: TLabel;
ExpandBitBtn: TBitBtn;
Timer1: TTimer;
InstructionsLabel: TLabel;
procedure FormCreate(Sender: TObject);
procedure DataListBoxClick(Sender: TObject);
procedure FirstLineOfDataButtonClick(Sender: TObject);
procedure SeriesNamesButtonClick(Sender: TObject);
procedure InfoGridClick(Sender: TObject);
procedure PickXDataComboBoxClick(Sender: TObject);
procedure HelpBitBtnClick(Sender: TObject);
procedure ZDataLineButtonClick(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure ExpandBitBtnClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
OriginalHeight: Integer;
InstructionIndex: Integer;
procedure CheckDelimiter;
procedure CalculateNoSeries;
public
{NB: Delimiters have to be public, so it cannot be a const array.}
Delimiters: array[TDelimiter] of String;
{DelimiterNames: array[TDelimiter] of String;}
TheDelimiter: TDelimiter;
TheFirstDataLine: Integer;
TheSeriesNamesLine: Integer;
TheSeriesUnitsLine: Integer;
TheZDataLine: Integer;
NumberOfSeries: Integer;
TheCol, TheRow: Integer;
XDataPresent: Boolean;
{$IFNDEF LANG_ENGLISH}
procedure DoCaptionsFromResource;
{$ENDIF}
procedure DoHintsFromResource;
end;
var
ParserForm: TParserForm;
implementation
{$R *.dfm}
const
Instructions: array[0..6] of string =
(sInstruction1,
sInstruction2,
sInstruction3,
sInstruction4,
sInstruction5,
sInstruction6,
sInstruction7);
{Delimiters[dlNone] := '';
DelimiterNames[dlNone] := 'None';
Tabs come from spreadsheet / table data from the clipboard:
Delimiters[dlTab] := #9;
DelimiterNames[dlTab] := 'Tab ->';
Commas come from disk data:
Delimiters[dlComma] := ',';
DelimiterNames[dlComma] := 'Comma ,';
Delimiters[dlSpace] := ' ';
DelimiterNames[dlSpace] := 'Space ';
Delimiters[dlColon] := ';';
DelimiterNames[dlColon] := 'Colon ;';
Delimiters[dlSemicolon] := #58;
DelimiterNames[dlSemicolon] := 'Semicolon :';
Delimiters[dlLinefeed] := #10;
DelimiterNames[dlLinefeed] := 'Line Feed ┐';
Delimiters[dlOwn] := 'Type your own';
DelimiterNames[dlOwn] := 'Type your own';}
{------------------------------------------------------------------------------
Procedure: TParserForm.FormCreate
Description: standard FormCreate procedure
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/09/2001 by Mat Ballard
Purpose: sets the position, the Delimiters and their names, and putsw headings on the stringgrid
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.FormCreate(Sender: TObject);
var
iDelimiter: TDelimiter;
begin
{$IFNDEF LANG_ENGLISH}
DoCaptionsFromResource;
{$ENDIF}
DoHintsFromResource;
{$IFDEF MSWINDOWS}
Self.BorderStyle := bsSizeable;
{$ENDIF}
{$IFDEF LINUX}
Self.BorderStyle := fbsSizeable;
{$ENDIF}
Self.Scaled := FALSE;
Self.HorzScrollBar.Visible := FALSE;
Self.VertScrollBar.Visible := FALSE;
Self.Left := 5;
Self.Top := 10;
OriginalHeight := OKBitBtn.Top + 2 * OKBitBtn.Height;
Self.ClientWidth := DataListBox.Left + DataListBox.Width + DataListBox.Left;
Self.ClientHeight := OriginalHeight;
TheZDataLine := -1;
TheFirstDataLine := -1;
TheSeriesNamesLine := -1;
TheSeriesUnitsLine := -1;
XDataPresent := TRUE;
InstructionIndex := 0;
InstructionsLabel.Caption := Instructions[InstructionIndex];
Delimiters[dlNone] := '';
{Tabs come from spreadsheet / table data from the clipboard:}
Delimiters[dlTab] := #9;
{Commas come from disk data:}
Delimiters[dlComma] := ',';
Delimiters[dlSpace] := ' ';
Delimiters[dlColon] := ';';
Delimiters[dlSemicolon] := ':';
Delimiters[dlLinefeed] := #10;
Delimiters[dlOwn] := sTypeYourOwn;
for iDelimiter := dlNone to dlOwn do
begin
DelimiterComboBox.Items.Add(DelimiterNames[iDelimiter]);
end;
with InfoGrid do
begin
Cells[0, COLUMN_NOS] := sColumn + ' ' + sNumber;
Cells[0, SERIES_NAMES] := sSeries + ' ' + sNames;
Cells[0, FIRST_LINE_OF_DATA] := sFirst + ' ' + sLine + sOf + sData;
Cells[0, X_OR_Y_OR_Z] := 'X, Y' + sOr + 'Z ' + sData;
Cells[0, DEPENDS_ON_X] := sData + strIn + sColumn + ' #:';
Cells[0, Z_DATA_LINE] := 'Z ' + sData;
DefaultColWidth := 80;
ColWidths[0] := 150;
end;
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.DoCaptionsFromResource
Description: standard loading of labels from resources
Author: Mat Ballard
Date created: 06/25/2001
Date modified: 06/25/2001 by Mat Ballard
Purpose: display in different languages
Known Issues:
------------------------------------------------------------------------------}
{$IFNDEF LANG_ENGLISH}
procedure TParserForm.DoCaptionsFromResource;
begin
Self.Caption := sParser;
DelimiterLabel.Caption := sDelimiter;
SetGroupBox.Caption := sSetGroupBox;
SeriesNamesButton.Caption := sSeries + ' ' + sNames;
FirstLineOfDataButton.Caption := sFirstLine;
ZDataLineButton.Caption := sZDataLine;
NoSeriesLabel.Caption := sNoSeriesFoundYet;
ExpandBitBtn.Caption := sExpand;
end;
{$ENDIF}
{------------------------------------------------------------------------------
Procedure: TParserForm.DoHintsFromResource
Description: standard loading of hints from resources
Author: Mat Ballard
Date created: 06/25/2001
Date modified: 06/25/2001 by Mat Ballard
Purpose: display in different languages
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.DoHintsFromResource;
begin
DelimiterComboBox.Hint := sDelimiterComboBoxHint;
SeriesNamesButton.Hint := sSeriesNamesButtonHint;
FirstLineOfDataButton.Hint := sFirstLineOfDataButtonHint;
ZDataLineButton.Hint := sZDataLineButtonHint;
InfoGrid.Hint := sInfoGridHint;
PickXDataComboBox.Hint := sPickXDataComboBoxHint;
ExpandBitBtn.Hint := sExpandBitBtnHint;
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.DataListBoxClick
Description: responds to user selection of a line
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: places the selected line into the Edit box, and checks it for Delimiters
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.DataListBoxClick(Sender: TObject);
begin
LineEdit.Text := DataListBox.Items[DataListBox.ItemIndex];
CheckDelimiter;
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.CheckDelimiter
Description: determines the Delimiter in a line
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: sets Delimiter
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.CheckDelimiter;
var
iDelimiter: TDelimiter;
begin
TheDelimiter := dlNone;
for iDelimiter := dlTab to dlLineFeed do
begin
if (Pos(Delimiters[iDelimiter], LineEdit.Text) > 0) then
begin
TheDelimiter := iDelimiter;
break;
end;
end;
DelimiterComboBox.ItemIndex := Ord(TheDelimiter);
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.CalculateNoSeries
Description: Calculates the number of Series (Y columns)
Author: Mat Ballard
Date created: 04/09/2001
Date modified: 04/09/2001 by Mat Ballard
Purpose: see Description
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.CalculateNoSeries;
var
iColumn: Integer;
begin
NumberOfSeries := 0;
for iColumn := 2 to InfoGrid.ColCount-1 do
begin
if (InfoGrid.Cells[iColumn, X_OR_Y_OR_Z] = 'Y') then
Inc(NumberOfSeries);
end;
NoSeriesLabel.Caption := Format(sThereSeemsToBe + ' %d ' + sSeries, [NumberOfSeries]);
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.FirstLineOfDataButtonClick
Description: responds to the selection of the first line of data
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: fills the InfoGrid cells with the parsed line
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.FirstLineOfDataButtonClick(Sender: TObject);
var
TheLine: String;
iColumn: Integer;
begin
ZDataLineButton.Enabled := TRUE;
TheFirstDataLine := DataListBox.ItemIndex;
TheLine := DataListBox.Items[DataListBox.ItemIndex];
iColumn := 1;
{InfoGrid.ColCount := 3;}
while (Length(TheLine) > 0) do
begin
if (InfoGrid.ColCount <= iColumn) then
InfoGrid.ColCount := iColumn+1;
InfoGrid.Cells[iColumn, FIRST_LINE_OF_DATA] :=
GetWord(TheLine, Delimiters[TheDelimiter]);
Inc(iColumn);
end;
for iColumn := 1 to InfoGrid.ColCount-1 do
begin
InfoGrid.Cells[iColumn, COLUMN_NOS] := IntToStr(iColumn);
end;
InfoGrid.Cells[1, X_OR_Y_OR_Z] := 'X';
for iColumn := 2 to InfoGrid.ColCount-1 do
begin
InfoGrid.Cells[iColumn, X_OR_Y_OR_Z] := 'Y';
end;
InfoGrid.Cells[1, DEPENDS_ON_X] := '';
for iColumn := 2 to InfoGrid.ColCount-1 do
begin
InfoGrid.Cells[iColumn, DEPENDS_ON_X] := '1';
end;
OKBitBtn.Enabled := TRUE;
CalculateNoSeries;
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.SeriesNamesButtonClick
Description: responds to the selection of the Series names
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: fills the InfoGrid Series Names row with the parsed line
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.SeriesNamesButtonClick(Sender: TObject);
var
TheLine: String;
iColumn: Integer;
begin
TheSeriesNamesLine := DataListBox.ItemIndex;
TheLine := DataListBox.Items[DataListBox.ItemIndex];
iColumn := 1;
while (Length(TheLine) > 0) do
begin
if (InfoGrid.ColCount <= iColumn) then
InfoGrid.ColCount := iColumn+1;
InfoGrid.Cells[iColumn, SERIES_NAMES] :=
GetWord(TheLine, Delimiters[TheDelimiter]);
Inc(iColumn);
end;
InfoGrid.ColCount := iColumn;
for iColumn := 1 to InfoGrid.ColCount-1 do
begin
InfoGrid.Cells[iColumn, COLUMN_NOS] := IntToStr(iColumn);
end;
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.InfoGridClick
Description: responds to the selection of a cell in the StringGrid
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: sets the InfoGrid options, contents of some cells, and PickXDataComboBox position and visibility
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.InfoGridClick(Sender: TObject);
var
Rect: TRect;
iColumn, iXColumn: Integer;
LocalXDataPresent: Boolean;
TheText: String;
begin
with InfoGrid do
begin
if (((Row = SERIES_NAMES) or
(Row = Z_DATA_LINE)) and
(Col > 0)) then
begin
Options := [goFixedVertLine,goFixedHorzLine,goVertLine,goHorzLine,
goDrawFocusSelected,goColSizing, goEditing];
end
else
begin
Options := [goFixedVertLine,goFixedHorzLine,goVertLine,goHorzLine,
goDrawFocusSelected,goColSizing];
end;
if ((Row = X_OR_Y_OR_Z) and (Col >= 1)) then
begin
if (Cells[Col, Row] = 'X') then
begin
Cells[Col, Row] := 'XTEXT';
Cells[Col, Row + 1] := '';
Cells[Col, Z_DATA_LINE] := '';
end
else if (Cells[Col, Row] = 'XTEXT') then
begin
Cells[Col, Row] := 'Y';
Cells[Col, Row + 1] := '1';
Cells[Col, Z_DATA_LINE] := '';
end
else if (Cells[Col, Row] = 'Y') then
begin
Cells[Col, Row] := 'Z';
Cells[Col, Row + 1] := '';
Cells[Col, Z_DATA_LINE] := '';
end
else if (Cells[Col, Row] = 'Z') then
begin
Cells[Col, Row] := 'ignore';
Cells[Col, Row + 1] := '';
Cells[Col, Z_DATA_LINE] := '';
end
else
begin
Cells[Col, Row] := 'X';
Cells[Col, Row + 1] := '';
Cells[Col, Z_DATA_LINE] := '';
end;
CalculateNoSeries;
end;
if ((Row = DEPENDS_ON_X) and (Col > 2)) then
begin
TheCol := Col;
TheRow := Row;
{Rect := TRect(CellRect(Col, Row));}
Rect := CellRect(TheCol, TheRow);
PickXDataComboBox.Left :=
InfoGrid.Left + Rect.Left;
PickXDataComboBox.Top :=
InfoGrid.Top + Rect.Top;
PickXDataComboBox.Width := Rect.Right - Rect.Left;
PickXDataComboBox.Height := Rect.Bottom - Rect.Top;
PickXDataComboBox.Clear;
for iColumn := 1 to ColCount-1 do
begin
if (Cells[iColumn, X_OR_Y_OR_Z] = 'X') then
PickXDataComboBox.Items.Add(IntToStr(iColumn));
end;
PickXDataComboBox.Visible := TRUE;
end;
{Is there X Data ?}
LocalXDataPresent := FALSE;
for iColumn := 1 to ColCount-1 do
begin
if (Cells[iColumn, X_OR_Y_OR_Z] = 'X') then
begin
LocalXDataPresent := TRUE;
iXColumn := iColumn;
break;
end;
end;
if (LocalXDataPresent) then
begin
if (not XDataPresent) then
{Oh merde ! we have to put ALL the X's back in !}
begin
TheText := IntToStr(iXColumn);
for iColumn := 1 to ColCount-1 do
if (Cells[iColumn, X_OR_Y_OR_Z] = 'Y') then
Cells[iColumn, DEPENDS_ON_X] := TheText;
end;
end
else
begin
for iColumn := 1 to ColCount-1 do
Cells[iColumn, DEPENDS_ON_X] := '';
end;
XDataPresent := LocalXDataPresent;
end; {with InfoGrid}
end;
{------------------------------------------------------------------------------
Procedure: TParserForm.PickXDataComboBoxClick
Description: responds to the selection of a particular X Data column
Author: Mat Ballard
Date created: 04/25/2000
Date modified: 04/25/2000 by Mat Ballard
Purpose: sets the XData column
Known Issues:
------------------------------------------------------------------------------}
procedure TParserForm.PickXDataComboBoxClick(Sender: TObject);
begin
with PickXDataComboBox do
begin
Visible := FALSE;
if (ItemIndex >= 0) then
InfoGrid.Cells[TheCol, TheRow] := Items[ItemIndex];
end;
end;
procedure TParserForm.HelpBitBtnClick(Sender: TObject);
{$IFDEF LINUX}
var
TheHelpFile: String;
{$ENDIF}
begin
{$IFDEF LINUX}
TheHelpFile := 'hs' + IntToStr(HelpBitBtn.HelpContext) + '.htm';
{$ENDIF}
end;
procedure TParserForm.ZDataLineButtonClick(Sender: TObject);
var
TheLine: String;
iColumn: Integer;
begin
TheZDataLine := DataListBox.ItemIndex;
TheLine := DataListBox.Items[DataListBox.ItemIndex];
iColumn := 1;
while (Length(TheLine) > 0) do
begin
if (InfoGrid.ColCount <= iColumn) then
InfoGrid.ColCount := iColumn+1;
InfoGrid.Cells[iColumn, Z_DATA_LINE] :=
GetWord(TheLine, Delimiters[TheDelimiter]);
Inc(iColumn);
end;
end;
procedure TParserForm.FormResize(Sender: TObject);
begin
Self.ClientHeight := OriginalHeight;
DataListBox.Width := Self.ClientWidth - 2*DataListBox.Left;
LineEdit.Width := Self.ClientWidth - 2*DataListBox.Left;
InfoGrid.Width := Self.ClientWidth - 2*DataListBox.Left;
end;
procedure TParserForm.ExpandBitBtnClick(Sender: TObject);
begin
if (ExpandBitBtn.Tag = 0) then
begin
Self.Width := Screen.Width - Self.Left;
ExpandBitBtn.Caption := sContract;
ExpandBitBtn.Tag := 1;
end
else
begin
Self.Width := SetGroupBox.Left + SetGroupBox.Width + HelpBitBtn.Left;
ExpandBitBtn.Caption := sExpand;
ExpandBitBtn.Tag := 0;
end;
end;
procedure TParserForm.Timer1Timer(Sender: TObject);
begin
InstructionIndex := (InstructionIndex+1) mod 7;
InstructionsLabel.Caption := Instructions[InstructionIndex];
end;
end.