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

{************************************************}
{                                                }
{   UNIT XVIEWS   A collection of new Views      }
{   Copyright (c) 1994-97 by Tom Wellige         }
{   Donated as FREEWARE                          }
{                                                }
{   Ortsmuehle 4, 44227 Dortmund, GERMANY        }
{   EMail: wellige@itk.de                        }
{                                                }
{************************************************}

(*
  Some few words on this unit:
  ----------------------------

   - This units works fine with Turbo Pascal 6 or higher. If you use
     TP/BP 7 you can use the "inherited" command as shown in the
     comment lines on each line where it is possible.

   - This unit defines first of all a basic object (TXView) for status views
     which are updateable via messages (send from the applications Idle
     methode). All inheritances only have to override the abstract methode
     UPDATE and place the information to display in a string. In this manner
     there are a ClockView, a DateView and an HeapView as examples
     implemented. The usage of these objects (TClock, TDate and THeap) will
     be demonstrated in the programs XTEST1 and XTEST2.

   - There is also a 7-segment view implemented in this unit (T7Segment)
     capable of displaying all numbers from 0 to 9 and the characters
     "A" "b" "c" "d" "E" "F" and "-". The usage of this object is also
     demonstrated in this unit by the object TBigClock which is a clock
     in "hh:mm:ss" format. How to use this clock is demonstrated in the
     XTEST3 program.
*)

unit xviews;

interface

uses dos, objects, drivers, views;

const
  cmGetData        = 5000;   { Request data string from TXView object }
  cmChange7Segment = 5001;   { Set new value to display in T7Segment  }
  cmChangeBack     = 5002;   { Change Background of T7Segment         }

type
  PXView = ^TXView;                  (* Basic status view object  *)
  TXView = object(TView)
      Data: string;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Update; virtual;
    procedure Draw; virtual;
    function  GetString: PString; virtual;
  end;

  PClock = ^TClock;                   (* Displays current time           *)
  TClock = object(TXView)
    procedure Update; virtual;
  end;

  PDate = ^TDate;                     (* Displays current date           *)
  TDate = object(TXView)
    procedure Update; virtual;
  end;

  PHeap = ^THeap;                     (* Displays free bytes on the heap *)
  THeap = object(TXView)
    procedure Update; virtual;
  end;

  PInfoView = ^TInfoView;             (* Show all "actual" datas         *)
  TInfoView = object(TView)
    procedure Draw; virtual;
  end;

  PInfoWindow = ^TInfoWindow;         (* Window holding TInfoView        *)
  TInfoWindow = object(TWindow)
    constructor Init(var Bounds: TRect);
  end;

  TSegment = array[1..13] of byte;    (* Buffer for T7Sgement            *)

  P7Segment = ^T7Segment;             (* 7 Segment View (7x5)            *)
  T7Segment = object(TView)
      Segment: TSegment;
      Number: word;
        { 16 -> segm_ = "-",  >=17 -> segmBlank = " " }
      BackGround: boolean;
        { not active segment visible (gray) ? }
    constructor Init(Top: TPoint; ABackGround: boolean; ANumber: word);
      { Top: upper left corner of segment
        ABackGround: not active segments visible (gray) ?
        ANumber: default value to be displayed }
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Draw; virtual;
    procedure UpdateSegments;
  end;

  PBigClock = ^TBigClock;
  TBigClock = object(TGroup)
      Seg: Array[1..6] of P7Segment;
    constructor Init(Top: TPoint; BackGround: boolean);
      { Top: upper left corner of clock
        BackGround: will passed to each T7Segment: not active segments
                    visible (gray) ? }
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Update;
  end;

const
  Date : PDate  = nil;
  Clock: PClock = nil;
  Heap : PHeap  = nil;

implementation


{***********************************************************************}
{**                             TXView                                **}
{***********************************************************************}

procedure TXView.HandleEvent(var Event: TEvent);
begin
  { TP/BP7: inherited HandleEvent(Event); }
  TView.HandleEvent(Event);
  if Event.What = evBroadCast then
    if Event.Command = cmGetData then
    begin
      ClearEvent(Event);
      Event.InfoPtr:= GetString;
    end;
end;

procedure TXView.Update;
begin
  Abstract;
end;

procedure TXView.Draw;
var
  Buf: TDrawBuffer;
  C: word;
begin
  C:= GetColor(2);  (* Application -> "Menu normal"  *)
                    (* Window      -> "Frame active" *)
  MoveChar(Buf, ' ', C, Size.X);
  MoveStr(Buf, Data, C);
  WriteLine(0, 0, Size.X, 1, Buf);
end;

function TXView.GetString: PString;
begin
  GetString:= PString(@Data);
end;


{***********************************************************************}
{**                             TClock                                **}
{***********************************************************************}

procedure TClock.Update;
type
  Rec = record
    hh, mm, ss: longint; end;
var
  DataRec: Rec;
  hh, mm, ss, hs: word;
begin
  GetTime(hh, mm, ss, hs);
  DataRec.hh:= hh;
  DataRec.mm:= mm;
  DataRec.ss:= ss;
  FormatStr(Data, '%2d:%2d:%2d', DataRec);
  if hh < 10 then Data[1]:= '0';
  if mm < 10 then Data[4]:= '0';
  if ss < 10 then Data[7]:= '0';
  DrawView;
end;


{***********************************************************************}
{**                             TDate                                 **}
{***********************************************************************}

procedure TDate.Update;
type
  Rec = record
    dd, mm, yy: longint; end;
var
  DataRec: Rec;
  dd, mm, yy, dw: word;
begin
  GetDate(yy, mm, dd, dw);
  DataRec.dd:= dd;
  DataRec.mm:= mm;
  DataRec.yy:= yy;
  FormatStr(Data, '%2d.%2d.%4d', DataRec);
  if dd < 10 then Data[1]:= '0';
  if mm < 10 then Data[4]:= '0';
  DrawView;
end;


{***********************************************************************}
{**                             THeap                                 **}
{***********************************************************************}

procedure THeap.Update;
var
  Mem: longint;
begin
  Mem:= MemAvail;
  FormatStr(Data, '%d Bytes', Mem);
  DrawView;
end;


{***********************************************************************}
{**                            TInfoView                              **}
{***********************************************************************}

procedure TInfoView.Draw;
var
  Buf: TDrawBuffer;
  C: word;
  s: string;
begin
  C:= GetColor(2);  (* Application -> "Menu normal"  *)
                    (* Window      -> "Frame active" *)
  s:= 'Date   : ';
  if assigned(Date) then
    s:= s + PString(Message(Date, evBroadCast, cmGetData, nil))^ else
    s:= s + 'not accessable';
  MoveChar(Buf, ' ', C, Size.X);
  MoveStr(Buf, s, C);
  WriteLine(0, 0, Size.X, 1, Buf);

  s:= 'Time   : ';
  if assigned(Clock) then
    s:= s + PString(Message(Clock, evBroadCast, cmGetData, nil))^ else
    s:= s + 'not accessable';
  MoveChar(Buf, ' ', C, Size.X);
  MoveStr(Buf, s, C);
  WriteLine(0, 1, Size.X, 1, Buf);

  s:= 'Memory : ';
  if assigned(Heap) then
    s:= s + PString(Message(Heap, evBroadCast, cmGetData, nil))^ else
    s:= s + 'not accessable';
  MoveChar(Buf, ' ', C, Size.X);
  MoveStr(Buf, s, C);
  WriteLine(0, 2, Size.X, 1, Buf);
end;


{***********************************************************************}
{**                           TInfoWindow                             **}
{***********************************************************************}

constructor TInfoWindow.Init(var Bounds: TRect);
var R: TRect;
begin
  { TP/BP7: inherited Init(Bounds, 'Systeminfo', 0); }
  TWindow.Init(Bounds, 'Systeminfo', 0);
  Palette:= wpCyanWindow;
  Flags:= Flags and not (wfClose + wfZoom + wfGrow);
  GetExtent(R);
  R.Grow(-2, -2);
  Insert(New(PInfoView, Init(R)));
end;


{***********************************************************************}
{**                            T7Segment                              **}
{***********************************************************************}

const              { 1  2  3  4  5  6  7  8  9  A  B  C  D }
  segm0: TSegment = (1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1);
  segm1: TSegment = (0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1);
  segm2: TSegment = (1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1);
  segm3: TSegment = (1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1);
  segm4: TSegment = (1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1);
  segm5: TSegment = (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1);
  segm6: TSegment = (1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1);
  segm7: TSegment = (1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1);
  segm8: TSegment = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
  segm9: TSegment = (1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1);
  segmA: TSegment = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1);
  segmB: TSegment = (1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1);
  segmC: TSegment = (1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1);
  segmD: TSegment = (0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1);
  segmE: TSegment = (1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1);
  segmF: TSegment = (1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0);
  segm_: TSegment = (0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0);
  segmBlank: TSegment =
                    (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);


constructor T7Segment.Init(Top: TPoint; ABackGround: boolean; ANumber: word);
var R: TRect;
begin
  R.Assign(Top.X, Top.Y, Top.X+7, Top.Y+5);
  { TP/BP7: inherited Init(R); }
  TView.Init(R);
  BackGround:= ABackGround;
  Number:= ANumber;
  UpdateSegments;
end;

procedure T7Segment.HandleEvent(var Event: TEvent);
begin
  { TP/BP7: inherited HandleEvent(Event); }
  TView.HandleEvent(Event);
  if Event.What = evBroadCast then
    case Event.Command of
      cmChange7Segment: begin
                          Number:= Word(Event.InfoPtr^);
                          UpdateSegments;
                          DrawView;
                          ClearEvent(Event);
                        end;
      cmChangeBack    : begin
                          if BackGround then BackGround:= false
                                        else BackGround:= true;
                          DrawView;
                        end;
    end;
end;

procedure T7Segment.Draw;
var
  Buf: TDrawBuffer;
  Front, Back: byte;

  function SetColor(w: word; c: byte): word;
  begin
    w:= w and $00FF;
    w:= swap(w);
    w:= w or c;
    w:= swap(w);
    SetColor:= w;
  end;

  procedure SetBufColor(var B: TDrawBuffer; C: word);
  var i: integer;
  begin
    for i:= 0 to Size.X do
      Buf[i]:= SetColor(Buf[i], C);
  end;

begin
  if BackGround then Back:= $8 else Back:= $0;
  Front:= $F;

  { Segment 1,2,3 }
  SetBufColor(Buf, $0);
  MoveStr (Buf, ' þþþþþ', Back);
  if Segment[1] = 1 then
    Buf[1]:= SetColor(Buf[1], Front);
  if Segment[2] = 1 then begin
    Buf[2]:= SetColor(Buf[2], Front);
    Buf[3]:= SetColor(Buf[3], Front);
    Buf[4]:= SetColor(Buf[4], Front); end;
  if Segment[3] = 1 then
    Buf[5]:= SetColor(Buf[5], Front);
  WriteLine(0, 0, Size.X, 1, Buf);

  { Segment 4,5 }
  SetBufColor(Buf, $0);
  MoveStr (Buf, ' Û   Û', Back);
  if Segment[4] = 1 then
    Buf[1]:= SetColor(Buf[1], Front);
  if Segment[5] = 1 then
    Buf[5]:= SetColor(Buf[5], Front);
  WriteLine(0, 1, Size.X, 1, Buf);

  { Segment 6,7,8 }
  SetBufColor(Buf, $0);
  MoveStr (Buf, ' þþþþþ', Back);
  if Segment[6] = 1 then
    Buf[1]:= SetColor(Buf[1], Front);
  if Segment[7] = 1 then begin
    Buf[2]:= SetColor(Buf[2], Front);
    Buf[3]:= SetColor(Buf[3], Front);
    Buf[4]:= SetColor(Buf[4], Front); end;
  if Segment[8] = 1 then
    Buf[5]:= SetColor(Buf[5], Front);
  WriteLine(0, 2, Size.X, 1, Buf);

  { Segment 9,10 }
  SetBufColor(Buf, $0);
  MoveStr (Buf, ' Û   Û', Back);
  if Segment[9] = 1 then
    Buf[1]:= SetColor(Buf[1], Front);
  if Segment[10] = 1 then
    Buf[5]:= SetColor(Buf[5], Front);
  WriteLine(0, 3, Size.X, 1, Buf);

  { Segment 11,12,13 }
  SetBufColor(Buf, $0);
  MoveStr (Buf, ' þþþþþ', Back);
  if Segment[11] = 1 then
    Buf[1]:= SetColor(Buf[1], Front);
  if Segment[12] = 1 then begin
    Buf[2]:= SetColor(Buf[2], Front);
    Buf[3]:= SetColor(Buf[3], Front);
    Buf[4]:= SetColor(Buf[4], Front); end;
  if Segment[13] = 1 then
    Buf[5]:= SetColor(Buf[5], Front);
  WriteLine(0, 4, Size.X, 1, Buf);
end;

procedure T7Segment.UpdateSegments;
begin
  case Number of
    0:  Segment:= segm0;
    1:  Segment:= segm1;
    2:  Segment:= segm2;
    3:  Segment:= segm3;
    4:  Segment:= segm4;
    5:  Segment:= segm5;
    6:  Segment:= segm6;
    7:  Segment:= segm7;
    8:  Segment:= segm8;
    9:  Segment:= segm9;
    10: Segment:= segmA;
    11: Segment:= segmB;
    12: Segment:= segmC;
    13: Segment:= segmD;
    14: Segment:= segmE;
    15: Segment:= segmF;
    16: Segment:= segm_;
  else
    Segment:= segmBlank;
  end;
end;


{***********************************************************************}
{**                            TBigClock                              **}
{***********************************************************************}

type
  PBlackView = ^TBlackView;    (* black background for TBigClock *)
  TBlackView = object(TView)
    procedure Draw; virtual;
  end;

procedure TBlackView.Draw;
var
  Buf  : TDrawBuffer;
  Color: word;
  i    : integer;
begin
  Color:= $0F;
  for i:= 0 to Size.Y do
  begin
    MoveChar(Buf, ' ', Color, Size.X);
    if (i = 2) or (i = 4) then
    begin
      Buf[16]:= $0FFE;
      Buf[33]:= $0FFE;
    end;
    WriteLine(0, i, Size.X, 1, Buf);
  end;
end;


constructor TBigClock.Init(Top: TPoint; BackGround: boolean);
const
  XPos : Array [1..6] of word = (1, 8, 18, 25, 35, 42);
var
  R: TRect;
  P: TPoint;
  i: integer;
begin
  R.Assign(Top.X, Top.Y, Top.X+50, Top.Y+7);
  { TP/BP7: inherited Init(R); }
  TGroup.Init(R);

  R.Assign(0, 0, Size.X, Size.Y);
  Insert(new(PBlackView, Init(R)));

  for i:= 1 to 6 do
  begin
    P.X:= XPos[i]; P.Y:= 1;
    Seg[i]:= new(P7Segment, Init(P, BackGround, 0));
    insert(Seg[i]);
  end;
end;

procedure TBigClock.HandleEvent(var Event: TEvent);
var i: integer;
begin
  { TP/BP7: inherited HandleEvent(Event); }
  TGroup.HandleEvent(Event);
  if Event.What = evBroadCast then
    if Event.Command = cmChangeBack then
    begin
      for i:= 1 to 6 do
        Message(Seg[i], evBroadCast, cmChangeBack, nil);
    end;
end;

procedure TBigClock.Update;
var
  w, h, m, s, hs: word;
begin
  GetTime(h, m, s, hs);
  w:= h div 10;
  Message(Seg[1], evBroadCast, cmChange7Segment, @w); (* Hours   - 10^1 *)
  w:= h mod 10;
  Message(Seg[2], evBroadCast, cmChange7Segment, @w); (* Hours   - 10^0 *)
  w:= m div 10;
  Message(Seg[3], evBroadCast, cmChange7Segment, @w); (* Minutes - 10^1 *)
  w:= m mod 10;
  Message(Seg[4], evBroadCast, cmChange7Segment, @w); (* Minutes - 10^0 *)
  w:= s div 10;
  Message(Seg[5], evBroadCast, cmChange7Segment, @w); (* Seconds - 10^1 *)
  w:= s mod 10;
  Message(Seg[6], evBroadCast, cmChange7Segment, @w); (* Seconds - 10^0 *)
end;


end.

{ -------------------- DEMO -------------- CUT HERE ------------ }

program XTest1;

{ usage of TDate, TClock and THeap defined in Unit XVIEWS }

uses Drivers, Objects, App, Views, Menus, XViews;

const
  cmWindow = 1000;

type
  PMyApp = ^TMyApp;
  TMyApp = object(TApplication)
    constructor Init;
    procedure Idle; virtual;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Window;
    procedure InitStatusLine; virtual;
  end;

constructor TMyApp.Init;
var R: TRect;
begin
  { TP/BP7: inherited Init; }
  TApplication.Init;

  GetExtent(R);
  R.A.X:= R.B.X - 11;
  R.A.Y:= R.B.Y - 1;
  Date:= New(PDate, Init(R));
  Insert(Date);

  GetExtent(R);
  R.A.X:= R.B.X - 9;
  R.B.Y:= R.A.Y + 1;
  Clock:= New(PClock, Init(R));
  Insert(Clock);

  GetExtent(R);
  R.A.X:= R.A.X + 1;
  R.B.X:= R.A.X + 20;
  R.B.Y:= R.A.Y + 1;
  Heap:= New(PHeap, Init(R));
  Insert(Heap);
end;

procedure TMyApp.Idle;
var Event: TEvent;
begin
  { TP/BP7: inherited Idle; }
  TApplication.Idle;
  Date^.Update;
  Clock^.Update;
  Heap^.Update;
end;

procedure TMyApp.HandleEvent(var Event: TEvent);
begin
  { TP/BP7: inherited HandleEvent(Event); }
  TApplication.HandleEvent(Event);
  case Event.What of
    evCommand:
      case Event.Command of
        cmWindow : Window;
      end;
  end;
end;

procedure TMyApp.Window;
var
  P: PWindow;
  R: TRect;
begin
  Desktop^.GetExtent(R);
  P:= New(PWindow, Init(R, 'Memory-Eater', 0));
  P^.Options:= P^.Options or ofTileAble;
  Desktop^.Insert(P);
  Cascade;
end;

procedure TMyApp.InitStatusLine;
var R: TRect;
begin
  GetExtent(R);
  R.A.Y:= R.B.Y - 1;
  New(StatusLine, Init(R,
    NewStatusDef(0, $FFFF,
      NewStatusKey('~Alt-X~ Exit',               kbAltX,  cmQuit,
      NewStatusKey('~F3~ Open Window',           kbF3,    cmWindow,
      NewStatusKey('',                           kbAltF3, cmClose,
      nil))),
    nil)));
end;


var
  MyApp: TMyApp;

begin
  MyApp.Init;
  MyApp.Run;
  MyApp.Done;
end.

{ -------------------- DEMO -------------- CUT HERE ------------ }
program XTest2;

{ usage of TInfoWindow defined in Unit XVIEWS }

uses Drivers, Objects, App, Views, XViews;

type
  PMyApp = ^TMyApp;
  TMyApp = object(TApplication)
      Info: PInfoWindow;
    constructor Init;
    procedure Idle; virtual;
  end;

constructor TMyApp.Init;
var R: TRect;
begin
  { TP/BP7: inherited Init; }
  TApplication.Init;

  R.Assign(0,0,1,1);
  Date:= New(PDate, Init(R));
  Date^.Hide;
  Insert(Date);

  Clock:= New(PClock, Init(R));
  Clock^.Hide;
  Insert(Clock);

  Heap:= New(PHeap, Init(R));
  Heap^.Hide;
  Insert(Heap);

  R.Assign(1,1,35,8);
  Info:= New(PInfoWindow, Init(R));
  Info^.Options:= Info^.Options or ofCentered;
  Insert(Info);
end;

procedure TMyApp.Idle;
var Event: TEvent;
begin
  { TP/BP7: inherited Idle; }
  TApplication.Idle;
  if assigned(Date) then Date^.Update;
  if assigned(Clock) then Clock^.Update;
  if assigned(Heap) then Heap^.Update;
  Info^.Redraw;
end;

var
  MyApp: TMyApp;

begin
  MyApp.Init;
  MyApp.Run;
  MyApp.Done;
end.
{ -------------------- DEMO -------------- CUT HERE ------------ }
program XTest3;

{ usage of TBigClock defined in Unit XVIEWS }

uses Drivers, Objects, App, Menus, Views, XViews;

const
  cmToggle = 1000;

type
  PMyApp = ^TMyApp;
  TMyApp = object(TApplication)
      BigClock: PBigClock;
    constructor Init;
    procedure InitStatusLine; virtual;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Idle; virtual;
  end;


constructor TMyApp.Init;
var P: TPoint;
begin
  { TP/BP7: inherited Init; }
  TApplication.Init;
  P.X:= 15; P.Y:= 9;
  BigClock:= new(PBigClock, Init(P, true));
  Insert(BigClock);
end;

procedure TMyApp.InitStatusLine;
var R: TRect;
begin
  GetExtent(R);
  R.A.Y:= R.B.Y - 1;
  New(StatusLine, Init(R,
    NewStatusDef(0, $FFFF,
      NewStatusKey('~Alt-X~ Exit',            kbAltX, cmQuit,
      NewStatusKey('~F2~ Toggle Background',  kbF2,   cmToggle,
      nil)),
    nil)));
end;

procedure TMyApp.HandleEvent(var Event: TEvent);
begin
  { TP/BP7: inherited HandleEvent(Event); }
  TApplication.HandleEvent(Event);
  if Event.What = evCommand then
    if Event.Command = cmToggle then
      Message(BigClock, evBroadCast, cmChangeBack, nil);
end;

procedure TMyApp.Idle;
var Event: TEvent;
begin
  { TP/BP7: inherited Idle; }
  TApplication.Idle;
  if assigned(BigClock) then BigClock^.Update;
end;


var
  MyApp: TMyApp;

begin
  MyApp.Init;
  MyApp.Run;
  MyApp.Done;
end.

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