[Back to OOP SWAG index]  [Back to Main SWAG index]  [Original]

{From: q3817075@bonsai (Olaf Lueder)}
{
: I'm writing a program using BP7.0 and TurboVision. I have DialogBox
: which contains some Datafields and a listbox. The problem is now that
: when the selection in the listbox changes I want to change the
: contents of the datafields. The way i'm doing it now is first get the
: data with Dlg^.GetData(Data) and then delete Dlg^ from the destkop
: (and ofcourse dispose it). Now I modify the data and creates the
: dialogbox all over before I insert it again. This is not really what I
: wannet - How do I do the same without having to delete and then insert
: the dialogbox...
There are various ways to solve your problem...

At first: There is the 'FocusItem'-method, which is called by the
HandleEvent
          of the ListBox, whenever a new Item is focused by pressing the
arrow-
          keys or using the mouse.

That's the method you'll have to modify.

You could do it in the follow way:

  procedure tNewListBox.FocusItem(Item: integer);
  var Data: record
              InputLine1: string[20];
              InputLine2: integer;
              CheckBox1 : word;
              .
              .
              List      : pCollection;
              Item      : integer;
            end;
  begin
    inherited FocusItem(Item);
    Owner^.GetData(Data);
    (* here you can modify Data using the values of your actually list-item*)
    (* for example: Data.InputLine1:=pListBoxItem(List^.at(Item))^.Name    *)
    Owner^.SetData(Data);
  end;

But there still be a problem...

Owner^.SetData calls ListBox^.SetData, and ListBox^.SetData calls
 ListBox^.NewList and this method calls dispose(List, done)...

So you have to redefine the NewList-method:

  procedure tNewListBox.NewList(AList: pCollection);
  begin
    List := AList;
    if AList = nil then SetRange(0)
                   else SetRange(AList^.Count);
    if Range > 0 then FocusItem(0);
    DrawView;
    (* we don't call dispose(List, done *)
  end;

It's a solution of your problem, but it isn't a nice one...

Much better way is to use messages.

What does we have ?

We've a ListBox, and of course a Collection with our data.
Now you can send a Message from the ListBox to the Owner of itself and
every
 subview of your dialog can hear that a new list-item was focused...
Storing a pointer of the focused list-item at the InfoPtr of the
Event-record-
every subview can take required data and change itself.

Short (???) Demo:
}

program Test;
uses Objects, Drivers, App, Menus, Views, Dialogs, Validate;

const cmListItemFocused         = 1000;
      cmTestDialog              = 1001;

type  pListData                 = ^tListData;
      tListData                 = record
                                    FirstName: string[20];
                                    LastName : string[30];
                                    Age      : longint;
                                    Sex      : word;
                                  end;
      pDataCollection           = ^tDataCollection;
      tDataCollection           = object(tCollection)
        constructor Init;
         procedure FreeItem(Item: pointer); virtual;
        (* you have to add 'GetItem' and 'PutItem' and to registrate it *)
      end;
      pNewInputLine             = ^tNewInputLine;
      tNewInputLine             = object(tInputLine)
        constructor Init(var Bounds: TRect; AMaxLen: Integer);
        procedure HandleEvent(var Event: tEvent); virtual;
        procedure Modify(AData: pointer); virtual;
      end;
      pFirstNameInputLine       = ^tFirstNameInputLine;
      tFirstNameInputLine       = object(tNewInputLine)
        procedure Modify(AData: pointer); virtual;
      end;
      pLastNameInputLine        = ^tLastNameInputLine;
      tLastNameInputLine        = object(tNewInputLine)
        procedure Modify(AData: pointer); virtual;
      end;
      pAgeInputLine             = ^tAgeInputLine;
      tAgeInputLine             = object(tNewInputLine)
        procedure Modify(AData: pointer); virtual;
      end;
      pNewRadioButtons          = ^tNewRadioButtons;
      tNewRadioButtons          = object(tRadioButtons)
         constructor Init(var Bounds: TRect; AStrings: PSItem);
        procedure HandleEvent(var Event: tEvent); virtual;
        procedure Modify(AData: pointer); virtual;
      end;
      pSexRadioButtons          = ^tSexRadioButtons;
      tSexRadioButtons          = object(tNewRadioButtons)
        procedure Modify(AData: pointer); virtual;
      end;
      pNewListBox               = ^tNewListBox;
      tNewListBox               = object(tListBox)
        procedure FocusItem(Item: integer); virtual;
      end;
      pTestListBox              = ^tTestListBox;
      tTestListBox              = object(tNewListBox)
        function GetText(Item: integer; MaxLen: integer): string; virtual;
        destructor Done; virtual;
      end;
      pTestDialog               = ^tTestDialog;
      tTestDialog               = object(tDialog)
        constructor Init;
      end;
      tTestApp                  = object(tApplication)
        procedure HandleEvent(var Event: TEvent); virtual;
         procedure InitMenuBar; virtual;
        procedure TestDialog;
      end;

var   TestApp: tTestApp;

FUNCTION NewDataItem(AFirstName, ALastName: string; AAge: longint;
                     ASex: word): pListData;
var Item: pListData;
begin
  GetMem(Item, SizeOf(tListData));
  with Item^ do begin
    FirstName:=AFirstName;
    LastName:=ALastName;
    Age:=AAge;
    Sex:=ASex;
  end;
  NewDataItem:=Item;
end;

CONSTRUCTOR tDataCollection.Init;
begin
  inherited Init( 5, 0);
   insert(NewDataItem('Olaf', 'Lueder', 23, 1));
  insert(NewDataItem('second', 'person', 55, 0));
  insert(NewDataItem('third', 'person', 77, 1));
  insert(NewDataItem('fourth', 'person', 11, 0));
  insert(NewDataItem('fifth', 'person', 33, 1));
end;

PROCEDURE tDataCollection.FreeItem(Item: pointer);
begin
  FreeMem(Item, SizeOf(tListData));
end;

CONSTRUCTOR tNewInputLine.Init(var Bounds: TRect; AMaxLen: Integer);
begin
  inherited Init(Bounds, AMaxLen);
  Options:=Options or ofPostProcess;
end;

PROCEDURE tNewInputLine.HandleEvent(var Event: tEvent);
begin
  inherited HandleEvent(Event);
  if (Event.What=evCommand) and (Event.Command=cmListItemFocused) then
    Modify(Event.InfoPtr);
 end;

PROCEDURE tNewInputLine.Modify(AData: pointer);
begin
  Abstract;
end;

PROCEDURE tFirstNameInputLine.Modify(AData: pointer);
var Str: string;
begin
  Str:=Copy(tListData(AData^).FirstName, 1, MaxLen);
  SetData(Str);
end;

PROCEDURE tLastNameInputLine.Modify(AData: pointer);
var Str: string;
begin
  Str:=Copy(tListData(AData^).LastName, 1, MaxLen);
  SetData(Str);
end;

PROCEDURE tAgeInputLine.Modify(AData: pointer);
var S: string[3];
 begin
  Str(pListData(AData)^.Age, S);
  SetData(S);
end;

CONSTRUCTOR tNewRadioButtons.Init(var Bounds: TRect; AStrings: PSItem);
begin
  inherited Init(Bounds, AStrings);
  Options:=Options or ofPostProcess;
end;

PROCEDURE tNewRadioButtons.HandleEvent(var Event: tEvent);
begin
  inherited HandleEvent(Event);
  if (Event.What=evCommand) and (Event.Command=cmListItemFocused) then
    Modify(Event.InfoPtr);
end;

PROCEDURE tNewRadioButtons.Modify(AData: pointer);
begin
  SetData(pListData(AData)^.Sex);
end;

 PROCEDURE tSexRadioButtons.Modify(AData: pointer);
begin
  SetData(pListData(AData)^.Sex);
end;

PROCEDURE tNewListBox.FocusItem(Item: integer);
begin
  inherited FocusItem(Item);
  Message(Owner, evCommand, cmListItemFocused, List^.At(Item));
end;

FUNCTION tTestListBox.GetText(Item: integer; MaxLen: integer): string;
var S: string;
begin
  with pListData(List^.At(Item))^ do begin
    Str(Age, S);
    case Sex of
      0: S:=S+', male';
      1: S:=S+', female';
    end;
    GetText:=LastName+', '+FirstName+', '+S;
  end;
end;

DESTRUCTOR tTestListBox.Done;
begin
  NewList(nil);
  inherited Done;
end;

CONSTRUCTOR tTestDialog.Init;
var R: tRect;
    View: pView;
begin
  R.Assign( 0, 0, 76, 10);
  inherited Init(R, 'Test-Dialog');
  Options:=Options or ofCentered;
  R.Assign( 15, 2, 37, 3);
  View:=New(pFirstNameInputLine, Init(R, 20));
  insert(View);
  R.Assign( 2, 2, 15, 3);
  Insert(New(pLabel, Init(R, '~F~irstName:', View)));
  R.Assign( 53, 2, 74, 3);
  View:=New(pLastNameInputLine, Init(R, 30));
  insert(View);
  R.Assign( 41, 2, 52, 3);
   Insert(New(pLabel, Init(R, '~L~astName:', View)));
  R.Assign( 15, 4, 20, 5);
  View:=New(pAgeInputLine, Init(R, 3));
  pInputLine(View)^.SetValidator(New(pRangeValidator, Init( 0, 150)));
  insert(View);
  R.Assign( 2, 4, 15, 5);
  Insert(New(pLabel, Init(R, '~A~ge:', View)));
  R.Assign( 32, 4, 74, 5);
  View:=New(pSexRadioButtons, Init(R,
    NewSItem('~f~emale',
    NewSItem('~m~ale',
    nil))));
  insert(View);
  R.Assign( 25, 4, 30, 5);
  insert(New(pLabel, Init(R, '~S~ex:', View)));
  R.Assign( 15, 6, 74, 9);
  View:=New(pTestListBox, Init(R, 1, nil));
  pListBox(View)^.NewList(New(pDataCollection, Init));
  insert(View);
  R.Assign( 2, 6, 15, 7);
  Insert(New(pLabel, Init(R, 'L~i~st:', View)));
end;

 PROCEDURE tTestApp.HandleEvent(var Event: tEvent);
begin
  inherited HandleEvent(Event);
  if (Event.What = evCommand) and (Event.Command = cmTestDialog) then begin
   TestDialog;
    ClearEvent(Event);
  end;
end;

PROCEDURE tTestApp.InitMenuBar;
var R: tRect;
begin
  GetExtent(R);
  R.B.Y := R.A.Y + 1;
  MenuBar := New(pMenuBar, Init(R, NewMenu(
    NewItem('~T~est', '', kbAltT, cmTestDialog, hcNoContext,
  nil))));
end;

PROCEDURE tTestApp.TestDialog;
begin
  ExecuteDialog(New(pTestDialog, Init), nil);
end;

begin
  with TestApp do begin
    Init;
    Run;
    Done;
  end;
end.


[Back to OOP SWAG index]  [Back to Main SWAG index]  [Original]