home *** CD-ROM | disk | FTP | other *** search
- 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;
-
- 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 =
- ('None', 'Tab ->', 'Comma ,', 'Space ', 'Colon ;', 'Semicolon :', 'Line Feed ┐', 'Type your own');
-
- 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;
- Label1: TLabel;
- DelimiterComboBox: TComboBox;
- LineEdit: TEdit;
- GroupBox1: 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;
- end;
-
- var
- ParserForm: TParserForm;
-
- implementation
-
- {$R *.dfm}
-
- resourcestring
- sInstruction1 = '1. Select the first line of data, and click on the "1st line of data" button. This enables the "ZData Line " button';
- sInstruction2 = '2. Select the line containing the names of the Series, by clicking on the "Series Names" button, or just type into the Grid.';
- sInstruction3 = '3. Expand the Grid, if needed by clicking on the "Expand" button.';
- sInstruction4 = '4. Set the column type: X, XTEXT, Y, Z or ignore, by clicking on the "Y" in the "X or Y Data ?" line, if needed';
- sInstruction5 = '5. Set the column in which the X Data is located, if needed';
- sInstruction6 = '6. If there is a line (row) of Z Data, select it by clicking on the "Z Data Line" button';
- sInstruction7 = '7. If you want to add the Z Data manually, type it into the last row of the grid under the Y values';
-
- 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
- {$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;
-
- ZDataLineButton.Hint :=
- 'The line containing the Z Data;' + #10 +
- 'If not set, or typed in, you will be prompted for values for 3D plots.';
- 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] := 'Type your own';
- for iDelimiter := dlNone to dlOwn do
- begin
- DelimiterComboBox.Items.Add(DelimiterNames[iDelimiter]);
- end;
-
- with InfoGrid do
- begin
- Cells[0, COLUMN_NOS] := 'Column Number:';
- Cells[0, SERIES_NAMES] := 'Series Names:';
- Cells[0, FIRST_LINE_OF_DATA] := '1st Line of Data:';
- Cells[0, X_OR_Y_OR_Z] := 'X, Y or Z data ?';
- Cells[0, DEPENDS_ON_X] := 'X Data in Column #:';
- Cells[0, Z_DATA_LINE] := 'Z Data:';
- DefaultColWidth := 80;
- ColWidths[0] := 130;
- end;
- 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('There seems to be %d Series', [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
- Self.Width := Screen.Width - 10;
- end;
-
- procedure TParserForm.Timer1Timer(Sender: TObject);
- begin
- InstructionIndex := (InstructionIndex+1) mod 7;
- InstructionsLabel.Caption := Instructions[InstructionIndex];
- end;
-
- end.
-