Browse Source

Initial release on http://luaforge.net

Jean-Francois Goulet 19 years ago
parent
commit
ab6e947f1b
5 changed files with 892 additions and 0 deletions
  1. 357 0
      LuaEdit/ComponentList.dfm
  2. 72 0
      LuaEdit/ComponentList.pas
  3. 57 0
      LuaEdit/PrecisionTimer.pas
  4. 91 0
      LuaEdit/Profiler.dfm
  5. 315 0
      LuaEdit/Profiler.pas

+ 357 - 0
LuaEdit/ComponentList.dfm

@@ -0,0 +1,357 @@
+object frmComponentList: TfrmComponentList
+  Left = 361
+  Top = 156
+  BorderIcons = [biSystemMenu]
+  BorderStyle = bsSingle
+  Caption = 'Component List'
+  ClientHeight = 609
+  ClientWidth = 607
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  FormStyle = fsStayOnTop
+  OldCreateOrder = False
+  Position = poOwnerFormCenter
+  DesignSize = (
+    607
+    609)
+  PixelsPerInch = 96
+  TextHeight = 13
+  object GroupBox1: TGroupBox
+    Left = 11
+    Top = 8
+    Width = 585
+    Height = 97
+    Caption = 'SynEdit'
+    TabOrder = 0
+    object Label1: TLabel
+      Left = 24
+      Top = 24
+      Width = 59
+      Height = 13
+      Caption = 'Home Page:'
+    end
+    object Label2: TLabel
+      Left = 96
+      Top = 24
+      Width = 146
+      Height = 13
+      Cursor = crHandPoint
+      Caption = 'http://synedit.sourceforge.net/'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlue
+      Font.Height = -11
+      Font.Name = 'MS Sans Serif'
+      Font.Style = []
+      ParentFont = False
+      OnClick = Label2Click
+    end
+    object Label3: TLabel
+      Left = 24
+      Top = 40
+      Width = 48
+      Height = 13
+      Caption = 'Creator(s):'
+    end
+    object Label4: TLabel
+      Left = 96
+      Top = 40
+      Width = 88
+      Height = 13
+      Caption = 'The SynEdit Team'
+    end
+    object Label5: TLabel
+      Left = 24
+      Top = 57
+      Width = 56
+      Height = 13
+      Caption = 'Description:'
+    end
+    object Label6: TLabel
+      Left = 96
+      Top = 56
+      Width = 481
+      Height = 33
+      AutoSize = False
+      Caption = 
+        'SynEdit is an advanced multi-line edit control, for Borland Delp' +
+        'hi, Kylix (Kylix is supported into latest cvs) and C++Builder.'
+      WordWrap = True
+    end
+  end
+  object GroupBox2: TGroupBox
+    Left = 11
+    Top = 112
+    Width = 585
+    Height = 105
+    Caption = ' JEDI Visual Component Library (JVCL)'
+    TabOrder = 1
+    object Label7: TLabel
+      Left = 24
+      Top = 24
+      Width = 59
+      Height = 13
+      Caption = 'Home Page:'
+    end
+    object Label8: TLabel
+      Left = 96
+      Top = 24
+      Width = 194
+      Height = 13
+      Cursor = crHandPoint
+      Caption = 'http://homepages.borland.com/jedi/jvcl/'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlue
+      Font.Height = -11
+      Font.Name = 'MS Sans Serif'
+      Font.Style = []
+      ParentFont = False
+      OnClick = Label2Click
+    end
+    object Label9: TLabel
+      Left = 24
+      Top = 40
+      Width = 48
+      Height = 13
+      Caption = 'Creator(s):'
+    end
+    object Label10: TLabel
+      Left = 96
+      Top = 40
+      Width = 77
+      Height = 13
+      Caption = 'The JVCL Team'
+    end
+    object Label11: TLabel
+      Left = 24
+      Top = 57
+      Width = 56
+      Height = 13
+      Caption = 'Description:'
+    end
+    object Label12: TLabel
+      Left = 96
+      Top = 56
+      Width = 481
+      Height = 41
+      AutoSize = False
+      Caption = 
+        'The JEDI Visual Component Library (JVCL) consists of a large col' +
+        'lection (currently about 500) visual and non-visual components w' +
+        'hich can be instantly reused in your Delphi, Kylix and C++ Build' +
+        'er projects.'
+      WordWrap = True
+    end
+  end
+  object GroupBox3: TGroupBox
+    Left = 11
+    Top = 224
+    Width = 582
+    Height = 121
+    Caption = 'Virtual Treeview'
+    TabOrder = 2
+    object Label13: TLabel
+      Left = 24
+      Top = 24
+      Width = 59
+      Height = 13
+      Caption = 'Home Page:'
+    end
+    object Label14: TLabel
+      Left = 96
+      Top = 24
+      Width = 126
+      Height = 13
+      Cursor = crHandPoint
+      Caption = 'http://www.soft-gems.net/'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlue
+      Font.Height = -11
+      Font.Name = 'MS Sans Serif'
+      Font.Style = []
+      ParentFont = False
+      OnClick = Label2Click
+    end
+    object Label15: TLabel
+      Left = 24
+      Top = 40
+      Width = 48
+      Height = 13
+      Caption = 'Creator(s):'
+    end
+    object Label16: TLabel
+      Left = 96
+      Top = 40
+      Width = 63
+      Height = 13
+      Caption = 'Mike Lischke'
+    end
+    object Label17: TLabel
+      Left = 24
+      Top = 57
+      Width = 56
+      Height = 13
+      Caption = 'Description:'
+    end
+    object Label18: TLabel
+      Left = 96
+      Top = 56
+      Width = 481
+      Height = 57
+      AutoSize = False
+      Caption = 
+        'Virtual Treeview is a tree view control built from ground up. Mo' +
+        're than 3 years of development made it one of the most flexible ' +
+        'and advanced tree controls available today. Virtual Treeview sta' +
+        'rts off with the claim to improve many aspects of existing solut' +
+        'ions and introduces some new technologies and priniciples which ' +
+        'were not available before.'
+      WordWrap = True
+    end
+  end
+  object btnClose: TButton
+    Left = 525
+    Top = 577
+    Width = 75
+    Height = 25
+    Anchors = [akRight, akBottom]
+    Cancel = True
+    Caption = '&Close'
+    Default = True
+    ModalResult = 1
+    TabOrder = 3
+  end
+  object GroupBox4: TGroupBox
+    Left = 11
+    Top = 352
+    Width = 585
+    Height = 105
+    Caption = 'madExcept'
+    TabOrder = 4
+    object Label19: TLabel
+      Left = 24
+      Top = 24
+      Width = 59
+      Height = 13
+      Caption = 'Home Page:'
+    end
+    object Label20: TLabel
+      Left = 96
+      Top = 24
+      Width = 114
+      Height = 13
+      Cursor = crHandPoint
+      Caption = 'http://www.madshi.net/'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlue
+      Font.Height = -11
+      Font.Name = 'MS Sans Serif'
+      Font.Style = []
+      ParentFont = False
+      OnClick = Label2Click
+    end
+    object Label21: TLabel
+      Left = 24
+      Top = 40
+      Width = 48
+      Height = 13
+      Caption = 'Creator(s):'
+    end
+    object Label22: TLabel
+      Left = 96
+      Top = 40
+      Width = 72
+      Height = 13
+      Caption = 'Mathias Rauen'
+    end
+    object Label23: TLabel
+      Left = 24
+      Top = 57
+      Width = 56
+      Height = 13
+      Caption = 'Description:'
+    end
+    object Label24: TLabel
+      Left = 96
+      Top = 56
+      Width = 481
+      Height = 41
+      AutoSize = False
+      Caption = 
+        'madExcept was built to help you locating crashes in your softwar' +
+        'e. Whenever there'#39's a crash/exception in your program, madExcept' +
+        ' will automatically catch it, analyze it, collect lots of useful' +
+        ' information, and give the end user the possibility to send you ' +
+        'a full bug report.'
+      WordWrap = True
+    end
+  end
+  object GroupBox5: TGroupBox
+    Left = 11
+    Top = 464
+    Width = 585
+    Height = 105
+    Caption = 'XPMenu'
+    TabOrder = 5
+    object Label25: TLabel
+      Left = 24
+      Top = 24
+      Width = 59
+      Height = 13
+      Caption = 'Home Page:'
+    end
+    object Label26: TLabel
+      Left = 96
+      Top = 24
+      Width = 179
+      Height = 13
+      Cursor = crHandPoint
+      Caption = 'http://www.shagrouni.com/index.html'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clBlue
+      Font.Height = -11
+      Font.Name = 'MS Sans Serif'
+      Font.Style = []
+      ParentFont = False
+      OnClick = Label2Click
+    end
+    object Label27: TLabel
+      Left = 24
+      Top = 40
+      Width = 48
+      Height = 13
+      Caption = 'Creator(s):'
+    end
+    object Label28: TLabel
+      Left = 96
+      Top = 40
+      Width = 84
+      Height = 13
+      Caption = 'Khaled Shagrouni'
+    end
+    object Label29: TLabel
+      Left = 24
+      Top = 57
+      Width = 56
+      Height = 13
+      Caption = 'Description:'
+    end
+    object Label30: TLabel
+      Left = 96
+      Top = 56
+      Width = 481
+      Height = 41
+      AutoSize = False
+      Caption = 
+        'XP Menu is a none-visual component that changes the visual aspec' +
+        'ts of menus, toolbars and many other controls to nearly the same' +
+        ' look and feel of MS Office XP. No code required, you do not hav' +
+        'e to reconstruct menus or toolbars using controls other than tho' +
+        'se shipped with Delphi.'
+      WordWrap = True
+    end
+  end
+end

+ 72 - 0
LuaEdit/ComponentList.pas

@@ -0,0 +1,72 @@
+unit ComponentList;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, Misc;
+
+type
+  TfrmComponentList = class(TForm)
+    GroupBox1: TGroupBox;
+    Label1: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    Label4: TLabel;
+    Label5: TLabel;
+    Label6: TLabel;
+    GroupBox2: TGroupBox;
+    Label7: TLabel;
+    Label8: TLabel;
+    Label9: TLabel;
+    Label10: TLabel;
+    Label11: TLabel;
+    Label12: TLabel;
+    GroupBox3: TGroupBox;
+    Label13: TLabel;
+    Label14: TLabel;
+    Label15: TLabel;
+    Label16: TLabel;
+    Label17: TLabel;
+    Label18: TLabel;
+    btnClose: TButton;
+    GroupBox4: TGroupBox;
+    Label19: TLabel;
+    Label20: TLabel;
+    Label21: TLabel;
+    Label22: TLabel;
+    Label23: TLabel;
+    Label24: TLabel;
+    GroupBox5: TGroupBox;
+    Label25: TLabel;
+    Label26: TLabel;
+    Label27: TLabel;
+    Label28: TLabel;
+    Label29: TLabel;
+    Label30: TLabel;
+    procedure Label2Click(Sender: TObject);
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+    procedure GoToHomePage(HomePage: String);
+  end;
+
+var
+  frmComponentList: TfrmComponentList;
+
+implementation
+
+procedure TfrmComponentList.GoToHomePage(HomePage: String);
+begin
+  BrowseURL(PChar(HomePage));
+end;
+
+{$R *.dfm}
+
+procedure TfrmComponentList.Label2Click(Sender: TObject);
+begin
+  GoToHomePage(TLabel(Sender).Caption);
+end;
+
+end.

+ 57 - 0
LuaEdit/PrecisionTimer.pas

@@ -0,0 +1,57 @@
+unit PrecisionTimer;
+
+interface
+
+uses
+  Windows, Classes, SysUtils;
+
+type
+  // Precision timer class declaration
+  TPrecisionTimer = class
+    OverheadTime: Int64;
+    InitFreq: Int64;
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+    procedure Init;
+    function GetCurrentTime(var lpPerformanceCount: Int64): Extended;
+    function GetFrequency(): Int64;
+    function GetPerformanceOverhead(): Int64;
+  end;
+
+implementation
+
+// Initialize the timer
+procedure TPrecisionTimer.Init;
+var
+  lpStart: Int64;
+  lpEnd: Int64;
+begin
+  // Calculate process overhead
+  QueryPerformanceCounter(lpStart);
+  QueryPerformanceCounter(lpEnd);
+  OverheadTime := lpEnd - lpStart;
+
+  // Get initial frequency
+  QueryPerformanceFrequency(InitFreq);
+end;
+
+function TPrecisionTimer.GetCurrentTime(var lpPerformanceCount: Int64): Extended;
+begin
+  QueryPerformanceCounter(lpPerformanceCount);
+  lpPerformanceCount := lpPerformanceCount - GetPerformanceOverhead();
+end;
+
+function TPrecisionTimer.GetFrequency(): Int64;
+begin
+  Result := InitFreq;
+end;
+
+function TPrecisionTimer.GetPerformanceOverhead(): Int64;
+begin
+  Result := OverheadTime;
+end;
+
+end.
+ 

+ 91 - 0
LuaEdit/Profiler.dfm

@@ -0,0 +1,91 @@
+object frmProfiler: TfrmProfiler
+  Left = 441
+  Top = 247
+  Width = 601
+  Height = 211
+  BorderStyle = bsSizeToolWin
+  Caption = 'Profiler'
+  Color = clBtnFace
+  DockSite = True
+  DragKind = dkDock
+  DragMode = dmAutomatic
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poOwnerFormCenter
+  OnCreate = FormCreate
+  OnDestroy = FormDestroy
+  PixelsPerInch = 96
+  TextHeight = 13
+  object vstLuaProfiler: TVirtualStringTree
+    Left = 0
+    Top = 0
+    Width = 593
+    Height = 184
+    Align = alClient
+    Header.AutoSizeIndex = 0
+    Header.Font.Charset = DEFAULT_CHARSET
+    Header.Font.Color = clWindowText
+    Header.Font.Height = -11
+    Header.Font.Name = 'MS Sans Serif'
+    Header.Font.Style = []
+    Header.Options = [hoColumnResize, hoDrag, hoVisible]
+    TabOrder = 0
+    TreeOptions.SelectionOptions = [toFullRowSelect]
+    TreeOptions.StringOptions = [toSaveCaptions]
+    OnAfterCellPaint = vstLuaProfilerAfterCellPaint
+    OnCollapsing = vstLuaProfilerCollapsing
+    OnGetText = vstLuaProfilerGetText
+    OnGetNodeDataSize = vstLuaProfilerGetNodeDataSize
+    Columns = <
+      item
+        Position = 0
+        Width = 150
+        WideText = 'Function Name'
+      end
+      item
+        Position = 1
+        WideText = 'Line'
+      end
+      item
+        Position = 2
+        WideText = 'Source'
+      end
+      item
+        Position = 3
+        Style = vsOwnerDraw
+        Width = 125
+        WideText = 'Relative Usage'
+      end
+      item
+        Position = 4
+        Style = vsOwnerDraw
+        Width = 125
+        WideText = 'Overall Usage'
+      end
+      item
+        Position = 5
+        Width = 100
+        WideText = 'Duration (s)'
+      end
+      item
+        Position = 6
+        Width = 75
+        WideText = 'Enter Time'
+      end
+      item
+        Position = 7
+        Width = 75
+        WideText = 'Exit Time'
+      end>
+  end
+  object JvDockClient1: TJvDockClient
+    DirectDrag = False
+    DockStyle = frmMain.jvDockVSNet
+    Left = 16
+    Top = 32
+  end
+end

+ 315 - 0
LuaEdit/Profiler.pas

@@ -0,0 +1,315 @@
+unit Profiler;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  ComCtrls, Dialogs, JvComponent, JvDockControlForm, VirtualTrees, Gauges,
+  PrecisionTimer, JvExControls, JvgProgress, JvSpecialProgress;
+
+type
+  PProfilerCall = ^TProfilerCall;
+  TProfilerCall = record
+    EnterTime: Int64; // Time when function enter
+    EnterTimeStr: String;
+    ExitTime: Int64; // Time when function exit
+    ExitTimeStr: String;
+    FctName: String; // Function's name
+    Source: String;
+    FctPointer: Pointer; // Functions's pointer
+    Line: Integer; // Function call line declaration
+    Parent: PVirtualNode; // Parent's pointer (pointer to caller's informations structure)
+    DurationRGauge: TGauge; // Relative duration gauge
+    DurationOGauge: TGauge; // Overall duration gauge
+  end;
+
+  TfrmProfiler = class(TForm)
+    JvDockClient1: TJvDockClient;
+    vstLuaProfiler: TVirtualStringTree;
+    procedure vstLuaProfilerGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+    procedure vstLuaProfilerGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
+    procedure FormDestroy(Sender: TObject);
+    procedure vstLuaProfilerAfterCellPaint(Sender: TBaseVirtualTree;
+      TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
+      CellRect: TRect);
+    procedure vstLuaProfilerCollapsing(Sender: TBaseVirtualTree;
+      Node: PVirtualNode; var Allowed: Boolean);
+    procedure FormCreate(Sender: TObject);
+  private
+    { Private declarations }
+    pCurrentCall: PVirtualNode;
+    pTimer: TPrecisionTimer;
+  public
+    { Public declarations }
+    procedure InitProfiler;
+    procedure ComputeProfiler;
+    function AddCall(FctPointer: Pointer; FctName: String; Line: Integer; Source: String): PProfilerCall;
+    procedure AddReturn(FctPointer: Pointer; FctName: String);
+  end;
+
+var
+  frmProfiler: TfrmProfiler;
+
+implementation
+
+uses Types;
+
+{$R *.dfm}
+
+procedure TfrmProfiler.InitProfiler;
+var
+  VTVColumn: TVirtualTreeColumn;
+  pNode: PVirtualNode;
+  pNodeData: PProfilerCall;
+begin
+  pCurrentCall := vstLuaProfiler.RootNode;
+  vstLuaProfiler.BeginUpdate;
+  pTimer.Init;
+  pNode := vstLuaProfiler.GetLast();
+
+  // Manually clear the tree to free gauges in node data
+  while Assigned(pNode) do
+  begin
+    pNodeData := vstLuaProfiler.GetNodeData(pNode);
+    FreeAndNil(pNodeData.DurationRGauge);
+    FreeAndNil(pNodeData.DurationOGauge);
+    vstLuaProfiler.DeleteNode(pNode);
+    pNode := vstLuaProfiler.GetLast();
+  end;
+end;
+
+procedure TfrmProfiler.ComputeProfiler;
+var
+  pNode, pMainNode: PVirtualNode;
+  pNodeData: PProfilerCall;
+  lpResidualDuration: Int64;
+begin
+  // Computing residual process duration
+  // This englobe all lines in the script that were not function calls...
+  pNode := vstLuaProfiler.GetFirstChild(vstLuaProfiler.RootNode);
+  pMainNode := vstLuaProfiler.GetFirstChild(vstLuaProfiler.RootNode);
+  pNodeData := vstLuaProfiler.GetNodeData(pNode);
+  lpResidualDuration := pNodeData.ExitTime - pNodeData.EnterTime;
+  pNode := vstLuaProfiler.GetNext(pNode);
+
+  while pNode <> nil do
+  begin
+    pNodeData := vstLuaProfiler.GetNodeData(pNode);
+    lpResidualDuration := lpResidualDuration - (pNodeData.ExitTime - pNodeData.EnterTime);
+    pNode := vstLuaProfiler.GetNextSibling(pNode);
+  end;
+
+  // Adding residual process duration node
+  pNode := vstLuaProfiler.AddChild(pMainNode);
+  pNodeData := vstLuaProfiler.GetNodeData(pNode);
+  pNodeData.Parent := pMainNode;
+  pNodeData.EnterTime := 0;
+  pNodeData.EnterTimeStr := '';
+  pNodeData.ExitTime := lpResidualDuration;
+  pNodeData.ExitTimeStr := '';
+  pNodeData.Line := -1;
+  pNodeData.Source := 'Lua';
+  pNodeData.FctPointer := nil;
+  pNodeData.FctName := '[RESIDUAL PROCESSES]';
+
+  pNodeData.DurationRGauge := TGauge.Create(Self);
+  pNodeData.DurationRGauge.Parent := vstLuaProfiler;
+  pNodeData.DurationRGauge.MinValue := 0;
+  pNodeData.DurationRGauge.MaxValue := 100;
+  pNodeData.DurationRGauge.Progress := 0;
+  pNodeData.DurationRGauge.Visible := False;
+
+  pNodeData.DurationOGauge := TGauge.Create(Self);
+  pNodeData.DurationOGauge.Parent := vstLuaProfiler;
+  pNodeData.DurationOGauge.MinValue := 0;
+  pNodeData.DurationOGauge.MaxValue := 100;
+  pNodeData.DurationOGauge.Progress := 0;
+  pNodeData.DurationOGauge.Visible := False;
+
+  // Display the profiler
+  vstLuaProfiler.EndUpdate;
+end;
+
+function TfrmProfiler.AddCall(FctPointer: Pointer; FctName: String; Line: Integer; Source: String): PProfilerCall;
+var
+  StartedTime: Int64;
+  pCallData: PProfilerCall;
+  pCallNode: PVirtualNode;
+begin
+  pTimer.GetCurrentTime(StartedTime);
+  pCallNode := vstLuaProfiler.AddChild(pCurrentCall);
+  pCallData := vstLuaProfiler.GetNodeData(pCallNode);
+
+  pCallData.DurationRGauge := TGauge.Create(Self);
+  pCallData.DurationRGauge.Parent := vstLuaProfiler;
+  pCallData.DurationRGauge.MinValue := 0;
+  pCallData.DurationRGauge.MaxValue := 100;
+  pCallData.DurationRGauge.Progress := 0;
+  pCallData.DurationRGauge.Visible := False;
+
+  pCallData.DurationOGauge := TGauge.Create(Self);
+  pCallData.DurationOGauge.Parent := vstLuaProfiler;
+  pCallData.DurationOGauge.MinValue := 0;
+  pCallData.DurationOGauge.MaxValue := 100;
+  pCallData.DurationOGauge.Progress := 0;
+  pCallData.DurationOGauge.Visible := False;
+
+  pCallData.EnterTimeStr := FormatDateTime('hh:nn:ss:zzz', Time);
+  pCallData.Parent := pCurrentCall;
+  pCallData.FctName := FctName;
+  pCallData.FctPointer := FctPointer;
+  pCallData.Line := Line;
+  pCallData.Source := Source;
+  pCallData.EnterTime := StartedTime;
+  pCurrentCall := pCallNode;
+  Result := pCallData;
+end;
+
+procedure TfrmProfiler.AddReturn(FctPointer: Pointer; FctName: String);
+var
+  EndedTime: Int64;
+  pCallData: PProfilerCall;
+  test1, test2: Int64;
+begin
+  pTimer.GetCurrentTime(EndedTime);
+  pCallData := vstLuaProfiler.GetNodeData(pCurrentCall);
+  pCallData.ExitTimeStr := FormatDateTime('hh:nn:ss:zzz', Time);
+  pCurrentCall := pCallData.Parent;
+  pCallData.ExitTime := EndedTime;
+end;
+
+procedure TfrmProfiler.vstLuaProfilerGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+var
+  pData: PProfilerCall;
+begin
+  // Set text to display for all nodes
+  if TextType = ttNormal then
+  begin
+    case Column of
+      0: // Function Name
+      begin
+        pData := Sender.GetNodeData(Node);
+        if pData.Parent = Sender.RootNode then
+          CellText := '[MAIN]'
+        else if pData.FctName = '' then
+          CellText := '[UNKNOWN]'
+        else
+        CellText := pData.FctName;
+      end;
+      1: // Line
+      begin
+        pData := Sender.GetNodeData(Node);
+        if pData.Line = -1 then
+          CellText := 'N/A'
+        else
+          CellText := IntToStr(pData.Line);
+      end;
+      2: // Source
+      begin
+        pData := Sender.GetNodeData(Node);
+        CellText := pData.Source;
+      end;
+      5: // Duration (s)
+      begin
+        pData := Sender.GetNodeData(Node);
+        CellText := FormatFloat('0.000000', (pData.ExitTime - pData.EnterTime) / pTimer.GetFrequency());
+      end;
+      6: // Enter Time
+      begin
+        pData := Sender.GetNodeData(Node);
+
+        if pData.EnterTimeStr = '' then
+          CellText := 'N/A'
+        else
+          CellText := pData.EnterTimeStr;
+      end;
+      7: // Exit Time
+      begin
+        pData := Sender.GetNodeData(Node);
+
+        if pData.ExitTimeStr = '' then
+          CellText := 'N/A'
+        else
+          CellText := pData.ExitTimeStr;
+      end;
+    else
+      CellText := '';
+    end;
+  end;
+end;
+
+procedure TfrmProfiler.vstLuaProfilerGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
+begin
+  NodeDataSize := SizeOf(TProfilerCall);
+end;
+
+procedure TfrmProfiler.vstLuaProfilerAfterCellPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; CellRect: TRect);
+var
+  pFirstNode: PVirtualNode;
+  pFirstNodeData: PProfilerCall;
+  pData, pParentData: PProfilerCall;
+  pPt: TPoint;
+  pRect: TRect;
+begin
+  case Column of
+    3: // Relative Usage
+    begin
+      pRect := Sender.GetDisplayRect(Node, Column, False);
+      pData := Sender.GetNodeData(Node);
+      pParentData := Sender.GetNodeData(pData.Parent);
+
+      if pData.Parent = Sender.RootNode then
+        pData.DurationRGauge.Progress := 100
+      else
+        pData.DurationRGauge.Progress := Round(((pData.ExitTime - pData.EnterTime) / pTimer.GetFrequency()) / ((pParentData.ExitTime - pParentData.EnterTime) / pTimer.GetFrequency()) * 100);
+
+      InflateRect(pRect, -1, -1);
+      pData.DurationRGauge.BoundsRect := pRect;
+      pData.DurationRGauge.Visible := True;
+    end;
+    4: // Overall Usage
+    begin
+      pRect := Sender.GetDisplayRect(Node, Column, False);
+      pFirstNode := Sender.GetFirstChild(vstLuaProfiler.RootNode);
+      pFirstNodeData := Sender.GetNodeData(pFirstNode);
+      pData := Sender.GetNodeData(Node);
+
+      if pData.Parent = Sender.RootNode then
+        pData.DurationOGauge.Progress := 100
+      else
+        pData.DurationOGauge.Progress := Round(((pData.ExitTime - pData.EnterTime) / pTimer.GetFrequency()) / ((pFirstNodeData.ExitTime - pFirstNodeData.EnterTime) / pTimer.GetFrequency()) * 100);
+
+      InflateRect(pRect, -1, -1);
+      pData.DurationOGauge.BoundsRect := pRect;
+      pData.DurationOGauge.Visible := True;
+    end;
+  end;
+end;
+
+procedure TfrmProfiler.vstLuaProfilerCollapsing(Sender: TBaseVirtualTree; Node: PVirtualNode; var Allowed: Boolean);
+var
+  pChildNode: PVirtualNode;
+  pChildData: PProfilerCall;
+begin
+  // Manually hidding gauges that shouldn't be visible anymore
+  pChildNode := Sender.GetFirstChild(Node);
+  while ((pChildNode <> nil) and (Node.Parent <> pChildNode.Parent)) do
+  begin
+    pChildData := Sender.GetNodeData(pChildNode);
+    pChildData.DurationRGauge.Visible := False;
+    pChildData.DurationOGauge.Visible := False;
+    pChildNode := Sender.GetNext(pChildNode);
+  end;
+end;
+
+procedure TfrmProfiler.FormCreate(Sender: TObject);
+begin
+  pTimer := TPrecisionTimer.Create;
+end;
+
+procedure TfrmProfiler.FormDestroy(Sender: TObject);
+begin
+  pTimer.Free;
+end;
+
+end.