Naciśnij “Enter” aby skoczyć do treści

Tiny Radio Player #11 – Lista stacji radiowych, zarządzanie danymi w VirtualStringTree

W poprzednim wpisie zapoznaliśmy się z konfiguracją komponentu VirtualStringTree. Dzisiaj przejdziemy do zarządzania danymi.

Dane w VirtualStringTree (VST) zorganizowane są w postaci nodów. Każdy taki nod może wskazywać na swoje rodzeństwo, czyli na nod poprzedni i kolejny. Dodatkowo może posiadać nody podrzędne, czyli dzieci oraz wskazywać na dane zapisane w postaci rekordu. Właśnie ten wskaźnik na dane posłuży nam na przechowanie informacji o stacjach.

Dodawanie danych

Załóżmy, że listę stacji pobraliśmy z bazy danych i chcemy ją teraz umieścić w VST. Aby to zrobić musimy przede wszystkim utworzyć klasę oraz rekord na dane, który podepniemy pod noda.

type
  TStationNodeData = class
  protected
    FID      : string;
    FName    : string;
    FGenre   : string;
    FCountry : string;
  public
    constructor Create(const Id: string;
      const Name, Genre, Country: string); overload;

    property ID       : string   read FID       write FID;
    property Name     : string   read FName     write FName;
    property Genre    : string   read FGenre    write FGenre;
    property Country  : string   read FCountry  write FCountry;
  end;

  PStationNodeRec = ^TStationNodeRec;
  TStationNodeRec =
  record
     snd : TStationNodeData;
  end;

Musimy pamiętać o ustaleniu rozmiaru danych jakie będą spięte z nodem. Możemy to zrobić podczas konfiguracji VST

procedure TMainForm.VstStationListGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  NodeDataSize := SizeOf(TStationNodeRec);
end;

Pobrana wcześniej lista stacji reprezentowana jest przez obiekt query. Iterując po kolekcji w łatwy sposób dodamy wszystkie stacje do VST.

VstList.Clear;
VstList.RootNodeCount := query.RecordCount;
VstList.ReinitNode(VstList.RootNode, True);

VstList.BeginUpdate;

node := nil;
try
  while not query.EOF do
  begin
    if node = nil then
      node := VstList.GetFirst
    else
      node := VstList.GetNext(node);

    data := VstList.GetNodeData(node);

    data^.snd := TStationNodeData.Create(
      query.FieldByName('ID').AsString,
      query.FieldByName('Name').AsString,
      query.FieldByName('GenreText').AsString,
      query.FieldByName('CountryText').AsString
    );

    if (selectedId <> EMPTY_STR) and (query.FieldByName('ID').AsString = selectedId) then
      VstList.Selected[node] := true;

    query.Next;
  end;
finally
  Finalize(node^);
end;

VstList.EndUpdate;

Edycja danych

Aby edytować dane bezpośrednio w komponencie VST musimy wskazać interesujący nas nod i pobrać rekord z danymi. Możemy to zrobić np. przy pomocy kilku dostępnych metod wystawionych przez VST.

procedure EditData(var VstList: TVirtualStringTree)
var
  node, prevNode, nextNode: PVirtualNode;
  data: PStationNodeRec;
begin
  // pobranie pierwszego noda
  node := VstList.GetFirst();

  // pobranie ostatniego noda
  node := VstList.GetLast();

  // pobranie zaznaczonego noda
  node := VstList.GetFirstSelected();

  // mając referencję możemy również pobrać bezpośrednich sąsiadów
  prevNode := VstList.GetPrevious(node);
  nextNode := VstList.GetNext(node);

  if node <> nil then
    data := VstList.GetNodeData(node);

  // edycja danych
  data^.snd.Genre := 'Dance';
end;

Usuwanie danych

Usuwanie wygląda bardzo podobnie do edycji z tą różnicą, że wołamy metodę DeleteNode.

procedure DeleteSelectedData(var VstList: TVirtualStringTree)
var
  node: PVirtualNode;
begin
  // pobranie zaznaczonego noda
  node := VstList.GetFirstSelected();

  VstList.DeleteNode(node);  
end;

Kod aplikacji dostępny jest na GitHubie.