unit MetaEditor;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, _BaseTemplate, ExtCtrls, VirtualTrees, StdCtrls, ComCtrls, Grids,
  MPHexEditor, Wrapgrid, VTHeaderPopup, Menus, _TreeElement;

type
  TForm_Meta = class(TForm_BaseTemplate)
    VST: TVirtualStringTree;
    splitter: TSplitter;
    rightPages: TPageControl;
    tab_hex: TTabSheet;
    tab_meta: TTabSheet;
    panel_hex_actions: TPanel;
    hex: TMPHexEditor;
    splitter_hex_1: TSplitter;
    value_viewer: TWrapGrid;
    splitter_hex_2: TSplitter;
    structviewer: TVirtualStringTree;
    value_viewer_context: TPopupMenu;
    value_viewer_context_copy: TMenuItem;
    value_viewer_context_copyasdec: TMenuItem;
    value_viewer_context_copyasfloat: TMenuItem;
    value_viewer_context_copyasbitset: TMenuItem;
    value_viewer_context_copyasstring: TMenuItem;
    value_viewer_context_copyashex: TMenuItem;
    VTHPopup: TVTHeaderPopupMenu;
    btn_export: TButton;
    btn_import: TButton;
    procedure FormCreate(Sender: TObject);
    procedure VSTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
      var ChildCount: Cardinal);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex);
    procedure VSTFocusChanging(Sender: TBaseVirtualTree; OldNode,
      NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
      var Allowed: Boolean);
    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
    procedure VSTPaintText(Sender: TBaseVirtualTree;
      const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
      TextType: TVSTTextType);
  private
    root: TTreeElement;
    procedure NewCon(ID: Integer);
  public
  end;


implementation
{$R *.dfm}
uses _MetaManager, _MetaTypes, ConnectionManager, Data, _FileTypes;

type
  PNodeData = ^TNodeData;

  TNodeData = record
    Field: TTreeElement;
  end;

function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
  ARecord: TNodeData): PVirtualNode;
var
  Data: PNodeData;
begin
  Result := AVST.AddChild(ANode);
  Data   := AVST.GetNodeData(Result);
  AVST.ValidateNode(Result, False);
  Data^ := ARecord;
end;


procedure TForm_Meta.NewCon(ID: Integer);
var
  i: Integer;
  data: TNodeData;
  node: PVirtualNode;
  Meta: TMetaManager;
  root: TTreeElement;
begin
  if ID >= 0 then
  begin
    //VST
    VST.Clear;
    VST.BeginUpdate;
//    root := ConManager.Connection[FConnectionID].MetaData.Root;
    root := ConManager.Connection[FConnectionID].MetaData.FileById[454];
    for i := 0 to root.ChildCount - 1 do
    begin
      data.Field := root.Child[i];
      node := AddVSTEntry(VST, nil, data);
      VST.HasChildren[node] := True;
    end;
    VST.EndUpdate;
  end;
end;


procedure TForm_Meta.VSTInitChildren(Sender: TBaseVirtualTree;
  Node: PVirtualNode; var ChildCount: Cardinal);
var
  data: PNodeData;
  newdata: TNodeData;
  newnode: PVirtualNode;
  i: Integer;
  Meta: TMetaManager;
begin
  data := Sender.GetNodeData(node);
  Meta := ConManager.Connection[ConnectionID].MetaData;

  if data.Field.ChildCount > 0 then
  begin
    for i := 0 to data.Field.ChildCount - 1 do
    begin
      newdata.Field := data.Field.Child[i];
      newnode := AddVSTEntry(TCustomVirtualStringTree(Sender), Node, newdata);
      if newdata.Field.ChildCount > 0 then
        Sender.HasChildren[newnode] := True;
    end;
  end;
  ChildCount := Sender.ChildCount[Node];
end;


procedure TForm_Meta.VSTFocusChanged(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex);
var
  data: PNodeData;
begin
  data := Sender.GetNodeData(Node);
  if data.Field is TFile then
  begin
    TFile(data.Field).InitEditor;
    if Assigned(TFile(data.Field).Editor) then
    begin
      TFile(data.Field).Editor.Align := alClient;
      tab_meta.InsertControl(TFile(data.Field).Editor);
      TFile(data.Field).Opened := True;
    end;
  end;
end;


procedure TForm_Meta.VSTFocusChanging(Sender: TBaseVirtualTree; OldNode,
  NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
  var Allowed: Boolean);
var
  data: PNodeData;
  i: Integer;
begin
  data := Sender.GetNodeData(NewNode);
  if data.Field is TFile then
  begin
    TFile(data.Field).InitEditor;
    if Assigned(TFile(data.Field).Editor) then
      Allowed := not TFile(data.Field).Opened
    else
      Allowed := True;
  end;
  if Allowed and Assigned(OldNode) then
  begin
    data := Sender.GetNodeData(OldNode);
    if data.Field is TFile then
    begin
      if TFile(data.Field).Opened then
      begin
        if tab_meta.ControlCount > 0 then
          for i := 0 to tab_meta.ControlCount - 1 do
            tab_meta.RemoveControl(tab_meta.Controls[i]);
        TFile(data.Field).Opened := False;
      end;
    end;
  end;
end;


procedure TForm_Meta.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
  Data: PNodeData;
begin
  Data     := Sender.GetNodeData(Node);
  CellText := '';
  if TextType = ttNormal then
  begin
    case Column of
      0:
        begin
          CellText := Data.Field.GetCaption;
        end;
      1:
        begin
          if Data.Field is TFile then
            CellText := TFile(Data.Field).FileInfo.Extension;
        end;
      2:
        begin
          if Data.Field is TFile then
            CellText := IntToStr(TFile(Data.Field).FileInfo.ID);
        end;
      3:
        begin
          if Data.Field is TDataField then
            CellText := TDataField(Data.Field).ValueAsString;
        end;
    end;
  end;
end;


procedure TForm_Meta.VSTPaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  Data: PNodeData;
begin
  Data     := Sender.GetNodeData(Node);
  if TextType = ttNormal then
  begin
    case Column of
      0:
        begin
          if Data.Field is TFile then
          begin
            if Length(TFile(Data.Field).FileInfo.Name) = 0 then
              TargetCanvas.Font.Color := $C06060;
            if TFile(Data.Field).FileInfo.Size = 0 then
              TargetCanvas.Font.Color := $2020A0;
          end;
        end;
    end;
  end;
end;



procedure TForm_Meta.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//  Meta.Free;
  inherited;
end;

procedure TForm_Meta.FormCreate(Sender: TObject);
begin
  inherited;
  OnNewConnection := NewCon;

  VST.NodeDataSize := SizeOf(TNodeData);
  VST.Font.Charset := AppSettings.CharSet;
  VST.Clear;

  UpdateConList;
end;

end.
