summaryrefslogtreecommitdiff
path: root/packages/fv/src/statuses.pas
diff options
context:
space:
mode:
Diffstat (limited to 'packages/fv/src/statuses.pas')
-rw-r--r--packages/fv/src/statuses.pas1404
1 files changed, 1404 insertions, 0 deletions
diff --git a/packages/fv/src/statuses.pas b/packages/fv/src/statuses.pas
new file mode 100644
index 0000000000..143848ba25
--- /dev/null
+++ b/packages/fv/src/statuses.pas
@@ -0,0 +1,1404 @@
+{$V-}
+unit Statuses;
+
+{$CODEPAGE cp437}
+
+{#Z+}
+{ Free Vision Status Objects Unit
+ Free VIsion
+ Written by : Brad Williams, DVM
+
+Revision History
+
+1.2.3 (96/04/13)
+ - moved Pause and Resume to methods of TStatus leaving TStatus Pause and
+ Resume "aware"
+ - eliminated many bugs
+ - moved Pause, Resume and Cancel from TStatusDlg to TStatus
+
+1.2.1 (95/12/6)
+ - minor typo corrections in opening unit documentation
+ - F+ to Z+ around stream registration records
+ - removed redundant sentence in TAppStatus definition
+ - updated CBarStatus documentation and constant
+ - removed TGauge.Init cross-reference from TSpinner.Init
+ - added THeapMemAvail and RegistertvStatus documentation
+ - numerous other documentation updates
+ - changed all calls to Send to Message
+
+1.2.0 (95/11/24)
+ - conversion to Bsd format
+
+1.1.0 (05/01/94)
+ - initial WVS release
+
+
+Known Bugs
+
+ScanHelp Errors
+ - sdXXXX constants help documentation doesn't show TStatusDlg and
+ TMessageStatusDlg
+ - ScanHelp produces garbage in evStatus help context
+
+tvStatus Bugs
+ - CAppStatus may not be correct }
+{#Z-}
+
+{ The tvStatus unit implements several views for providing information to
+the user which needs to be updated during program execution, such as a
+progress indicator, clock, heap viewer, gauges, etc. All tvStatus views
+respond to a new message event class, evStatus. An individual status view
+only processes an event with its associated command. }
+
+interface
+
+{$i platform.inc}
+
+{$ifdef PPC_FPC}
+ {$H-}
+{$else}
+ {$F+,O+,E+,N+}
+{$endif}
+{$X+,R-,I-,Q-,V-}
+{$ifndef OS_UNIX}
+ {$S-}
+{$endif}
+
+uses
+
+ FVCommon, FVConsts, Objects, Drivers, Views, Dialogs;
+{ Resource;}
+
+const
+
+ evStatus = $8000;
+ { evStatus represents the event class all status views know how to
+ respond to. }
+ {#X Statuses }
+
+
+ CStatus = #1#2#3;
+{$ifndef cdPrintDoc}
+{#F+}
+{ÝTStatus.CStatus palette
+ßßßßßßßßßßßßßßßßßßßßßßßßß}
+{#F-}
+{$endif cdPrintDoc}
+{ Status views use the default palette, CStatus, to map onto the first three
+entries in the standard window palette. }
+{#F+}
+{ 1 2 3
+ ÉÍÍÍÍÑÍÍÍÍÑÍÍÍÍ»
+ CStatus º 1 ³ 2 ³ 3 º
+ ÈÍÍÑÍÏÍÍÑÍÏÍÍÑͼ
+Normal TextÄÄÄÙ ³ ³
+OtherÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
+Highlighted TextÄÄÄÄÄÄÄÄÙ }
+{#F-}
+{#X TStatus }
+
+ CAppStatus = #2#5#4;
+{$ifndef cdPrintDoc}
+{#F+}
+{ÝTAppStatus.CAppStatus palette
+ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}
+{#F-}
+{$endif cdPrintDoc}
+{ Status views which are inserted into the application rather than a dialog
+or window use the default palette, CAppStatus, to map onto the application
+object's palette. }
+{#F+}
+{ 1 2 3
+ ÉÍÍÍÍÑÍÍÍÍÑÍÍÍÍ»
+ CAppStatus º 2 ³ 5 ³ 4 º
+ ÈÍÍÑÍÏÍÍÑÍÏÍÍÑͼ
+Normal TextÄÄÄÄÄÄÙ ³ ³
+OtherÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
+Highlighted TextÄÄÄÄÄÄÄÄÄÄÄÙ }
+{#F-}
+ {#X tvStatus TAppStatus }
+
+
+ CBarGauge = CStatus + #16#19;
+{$ifndef cdPrintDoc}
+{#F+}
+{ÝTBarGauge.CBarGauge palette
+ßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}
+{#F-}
+{$endif cdPrintDoc}
+{ TBarGauge's use the default palette, CBarGauge, to map onto the dialog or
+window owner's palette. }
+{#F+}
+{ 1 2 3 4 5
+ ÉÍÍÍÍÑÍÍÍÍÑÍÍÍÍÑÍÍÍÍÑÍÍÍÍ»
+ CAppStatus º 2 ³ 5 ³ 4 ³ 16 ³ 19 º
+ ÈÍÍÑÍÏÍÍÑÍÏÍÍÑÍÏÍÍÑÍÏÍÍÑͼ
+Normal TextÄÄÄÄÄÄÙ ³ ³ ³ ÀÄÄÄÄ filled in bar
+OtherÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÀÄÄÄÄÄÄÄÄÄ empty bar
+Highlighted TextÄÄÄÄÄÄÄÄÄÄÄÙ }
+{#F-}
+ {#X tvStatus TBarGauge }
+
+
+{#T sdXXXX }
+{$ifndef cdPrintDoc}
+{#F+}
+{ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
+Ý sdXXXX constants (STDDLG unit) Þ
+ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}
+{#F-}
+{$endif cdNoPrintDoc}
+{ sdXXXX constants are used to determine the types of buttons displayed in a
+#TStatusDlg# or #TStatusMessageDlg#. }
+{#F+}
+{ Constant ³ Value ³ Meaning
+ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+ sdNone ³ $0000 ³ no buttons
+ sdCancelButton ³ $0001 ³ show Cancel button
+ sdPauseButton ³ $0002 ³ show Pause button
+ sdResumeButton ³ $0004 ³ show Resume button
+ sdAllButtons ³ $0008 ³ show Cancel, Pause and Resume
+ ³ ³ buttons }
+{#Z+}
+ sdNone = $0000;
+ sdCancelButton = $0001;
+ sdPauseButton = $0002;
+ sdResumeButton = $0004;
+ sdAllButtons = sdCancelButton or sdPauseButton or sdResumeButton;
+{#Z-}
+ {#X tvStatus TStatusDlg TStatusMessageDlg }
+
+ SpinChars : String[4] = '³/Ä\';
+ { SpinChars are the characters used by a #TSpinnerGauge# when it is drawn.
+ Only one character is displayed at a time. The string is cycled
+ through then started over again until the view is disposed. }
+ {#X tvStatus }
+
+ sfPause = $F000;
+ { sfPause is an additional state flag used internally by status views to
+ indicate they are in a paused state and should not respond to their
+ command. }
+
+type
+ {#Z+}
+ PStatus = ^TStatus;
+ {#Z-}
+ TStatus = Object(TParamText)
+ { TStatus is the base object type from which all status views descend.
+ Status views are used to display information that will change at
+ run-time based upon some state or process in the application, such as
+ printing.
+
+ All status views that are to be inserted into the application should
+ descend from #TAppStatus# for proper color mapping. }
+ Command : Word;
+ { Command is the only command the status view will respond to. When
+ the status view receives an evStatus event it checks the value of the
+ Event.Command field against Command before handling the event. }
+ {#X HandleEvent }
+ constructor Init (R : TRect; ACommand : Word; AText : String;
+ AParamCount : Integer);
+ { Init calls the inherited constructor then sets #Command# to ACommand.
+
+ If an error occurs Init fails. }
+ {#X Load }
+ constructor Load (var S : TStream);
+ { Load calls the inherited constructor then reads #Command# from the
+ stream.
+
+ If an error occurs Load fails. }
+ {#X Store Init }
+ function Cancel : Boolean; virtual;
+ { Cancel should prompt the user when necessary for validation of
+ canceling the process which the status view is displaying. If the
+ user elects to continue the process Cancel must return False,
+ otherwise Cancel must return True. }
+ {#X Pause Resume }
+ function GetPalette : PPalette; virtual;
+ { GetPalette returns a pointer to the default status view palette,
+ #CStatus#. }
+ {#X TAppStatus CAppStatus }
+ procedure HandleEvent (var Event : TEvent); virtual;
+ { HandleEvent captures any #evStatus# messages with its command value
+ equal to #Command#, then calls #Update# with Data set to
+ Event.InfoPtr. If the State field has its #sfPause# bit set, the
+ view ignores the event. }
+ procedure Pause; virtual;
+ { Pause sends an evStatus message to the application with Event.Command
+ set to cmStatusPause and Event.InfoPtr set to #Status#^.Command. The
+ #Status# view's sfPause bit of the State flag is set by calling
+ SetState. In the paused state, the status view does not respond to
+ its associated command. }
+ {#X Resume sdXXXX Cancel }
+ procedure Reset; virtual;
+ { Reset causes the status view to be reset to its beginning or default
+ value, then be redrawn. Reset is used after an event is aborted
+ which can only be performed in its entirety. }
+ procedure Resume; virtual;
+ { Resume is called in response to pressing the Resume button. Resume
+ sends an evStatus message to the application with Event.Command set
+ to cmStatusPause and Event.InfoPtr set to #Status#^.Command. The
+ Status view's sfPause bit is turned off by calling SetState. }
+ {#X Pause sdXXXX Cancel }
+ procedure Store (var S : TStream); { store should never be virtual;}
+ { Store calls the inherited Store method then writes #Command# to the
+ stream. }
+ {#X Load }
+ procedure Update (Data : Pointer); virtual;
+ { Update changes the status' displayed text as necessary based on
+ Data. }
+ {#X Command HandleEvent }
+ end; { of TStatus }
+
+
+ {#Z+}
+ PStatusDlg = ^TStatusDlg;
+ {#Z-}
+ TStatusDlg = Object(TDialog)
+ { A TStatusDlg displays a status view and optional buttons. It may be
+ used to display any status message and optionally provide end user
+ cancelation or pausing of an ongoing operation, such as printing.
+
+ All status views that are to be inserted into a window or dialog should
+ descend from #TStatus# for proper color mapping. }
+ Status : PStatus;
+ { Status is the key status view for the dialog. When a cmStatusPause
+ command is broadcast in response to pressing the pause button,
+ Event.InfoPtr is set to point to the command associated with Status. }
+ {#X TStatus cmXXXX }
+ constructor Init (ATitle : TTitleStr; AStatus : PStatus; AFlags : Word);
+ { Init calls the inherited constructor to create the dialog and sets
+ the EventMask to handle #evStatus# events. AStatus is assigned to
+ #Status# and inserted into the dialog at position 2,2.
+
+ The dialog is anchored at AStatus^.Origin and its size is at least
+ AStatus^.Size + 2 in both dimensions. The actual size is determined
+ by the AFlags byte. The #sdXXXX# constants should be used to signify
+ which buttons to display.
+
+ If an error occurs Init fails. }
+ {#X TStatus.Pause TStatus.Resume }
+ constructor Load (var S : TStream);
+ { Load calls the inherited constructor then loads #Status#.
+
+ If an error occurs Load fails. }
+ {#X Store }
+ procedure Cancel (ACommand : Word); virtual;
+ { Cancel sends an evStatus message to the Application object with
+ command set to cmCancel and InfoPtr set to the calling status view's
+ command, then calls the inherited Cancel method. }
+ {#X TBSDDialog.Cancel }
+ procedure HandleEvent (var Event : TEvent); virtual;
+ { All evStatus events are accepted by the dialog and sent to each
+ subview in Z-order until cleared.
+
+ If the dialog recieves an evCommand or evBroadcast event with the
+ Command parameter set to cmCancel, HandleEvent sends an #evStatus#
+ message to the Application variable with Event.Command set to the
+ cmStatusCancel and Event.InfoPtr set to the #Status#.Command and
+ disposes of itself.
+
+ When a pause button is included, a cmStatusPause broadcast event is
+ associated with the button. When the button is pressed a call to
+ #TStatus.Pause# results. The status view is inactivated until it
+ receives an evStatus event with a commond of cmStatusResume and
+ Event.InfoPtr set to the status view's Command value. When a pause
+ button is used, the application should respond to the evStatus event
+ (with Event.Command of cmStatusPause) appropriately, then dispatch a
+ cmStatusResume evStatus event when ready to resume activity. }
+ {#X TStatus.Command }
+ procedure InsertButtons (AFlags : Word); virtual;
+ { InsertButtons enlarges the dialog to the necessary size and inserts
+ the buttons specified in AFlags into the last row of the dialog. }
+ procedure Store (var S : TStream); { store should never be virtual;}
+ { Store calls the inherited Store method then writes #Status# to the
+ stream. }
+ {#X Load }
+ end; { of TStatusDlg }
+
+
+ {#Z+}
+ PStatusMessageDlg = ^TStatusMessageDlg;
+ {#Z-}
+ TStatusMessageDlg = Object(TStatusDlg)
+ { A TStatusMessageDlg displays a message as static text with a status
+ view on the line below it.
+
+ All status views that are to be inserted into a window or dialog should
+ descend from #TStatus# for proper color mapping. }
+ constructor Init (ATitle : TTitleStr; AStatus : PStatus; AFlags : Word;
+ AMessage : String);
+ { Init calls the inherited constructor then inserts a TStaticText view
+ containing AMessage at the top line of the dialog.
+
+ The size of the dialog is determined by the size of the AStatus. The
+ dialog is anchored at AStatus^.Origin and is of at least
+ AStatus^.Size + 2 in heighth and width. The exact width and heighth
+ are determined by AOptions.
+
+ AFlags contains flags which determine the buttons to be displayed
+ in the dialog.
+
+ If an error occurs Init fails. }
+ end; { of TStatusMessageDlg }
+
+
+ {#Z+}
+ PGauge = ^TGauge;
+ {#Z-}
+ TGauge = Object(TStatus)
+ { A gauge is used to represent the current numerical position within a
+ range of values. When Current equals Max a gauge dispatches an
+ #evStatus# event with the command set to cmStatusDone to the
+ Application object. }
+ Min : LongInt;
+ { Min is the minimum value which #Current# may be set to. }
+ {#X Max }
+ Max : LongInt;
+ { Max is the maximum value which #Current# may be set to. }
+ {#X Min }
+ Current : LongInt;
+ { Current is the current value represented in the gauge. }
+ {#X Max Min }
+ constructor Init (R : TRect; ACommand : Word; AMin, AMax : LongInt);
+ { Init calls the inherited constructor then sets #Min# and #Max# to
+ AMin and AMax, respectively. #Current# is set to AMin.
+
+ If an error occurs Init fails. }
+ {#X Load }
+ constructor Load (var S : TStream);
+ { Load calls the inherited constructor then reads #Min#, #Max# and
+ #Current# from the stream.
+
+ If an error occurs Load fails. }
+ {#X Init Store }
+ procedure Draw; virtual;
+ { Draw writes the following to the screen: }
+{#F+}
+{
+Min = XXX Max = XXX Current = XXX }
+{#F-}
+ { where XXX are the current values of the corresponding variables. }
+ procedure GetData (var Rec); virtual;
+ { GetData assumes Rec is a #TGaugeRec# and returns the current settings
+ of the gauge. }
+ {#X SetData }
+ procedure Reset; virtual;
+ { Reset sets #Current# to #Min# then redraws the status view. }
+ {#X TStatus.Reset }
+ procedure SetData (var Rec); virtual;
+ { SetData assumes Rec is a #TGaugeRec# and sets the gauge's variables
+ accordingly. }
+ {#X GetData }
+ procedure Store (var S : TStream); { store should never be virtual;}
+ { Store calls the inherited Store method then writes #Min#, #Max# and
+ #Current# to the stream. }
+ {#X Load }
+ procedure Update (Data : Pointer); virtual;
+ { Update increments #Current#. }
+ end; { of TGauge }
+
+
+ {#Z+}
+ PGaugeRec = ^TGaugeRec;
+ {#Z-}
+ TGaugeRec = record
+ { A TGaugeRec is used to set and get a #TGauge#'s variables. }
+ {#X TGauge.GetData TGauge.SetData }
+ Min, Max, Current : LongInt;
+ end; { of TGaugeRec }
+
+
+ {#Z+}
+ PArrowGauge = ^TArrowGauge;
+ {#Z-}
+ TArrowGauge = Object(TGauge)
+ { An arrow gauge draws a progressively larger series of arrows across the
+ view. If Right is True, the arrows are right facing, '>', and are
+ drawn from left to right. If Right is False, the arrows are left
+ facing, '<', and are drawn from right to left. }
+ Right : Boolean;
+ { Right determines the direction of arrow used and the direction which
+ the status view is filled. If Right is True, the arrows are right
+ facing, '>', and are drawn from left to right. If Right is False,
+ the arrows are left facing, '<', and are drawn from right to left. }
+ {#X Draw }
+ constructor Init (R : TRect; ACommand : Word; AMin, AMax : Word;
+ RightArrow : Boolean);
+ { Init calls the inherited constructor then sets #Right# to RightArrow.
+
+ If an error occurs Init fails. }
+ {#X Load }
+ constructor Load (var S : TStream);
+ { Load calls the inherited constructor then reads #Right# from the
+ stream.
+
+ If an error occurs Load fails. }
+ {#X Init Store }
+ procedure Draw; virtual;
+ { Draw fills the Current / Max percent of the view with arrows. }
+ {#X Right }
+ procedure GetData (var Rec); virtual;
+ { GetData assumes Rec is a #TArrowGaugeRec# and returns the current
+ settings of the views variables. }
+ {#X SetData }
+ procedure SetData (var Rec); virtual;
+ { SetData assumes Rec is a #TArrowGaugeRec# and sets the view's
+ variables accordingly. }
+ {#X GetData }
+ procedure Store (var S : TStream); { store should never be virtual;}
+ { Store calls the inherited Store method then writes #Right# to the
+ stream. }
+ {#X Load }
+ end; { of TArrowGauge }
+
+
+ {#Z+}
+ PArrowGaugeRec = ^TArrowGaugeRec;
+ {#Z-}
+ TArrowGaugeRec = record
+ { A TArrowGaugeRec is used to set and get the variables of a
+ #TArrowGauge#. }
+ {#X TArrowGauge.GetData TArrowGauge.SetData }
+ Min, Max, Count : LongInt;
+ Right : Boolean;
+ end; { of TGaugeRec }
+
+
+ {#Z+}
+ PPercentGauge = ^TPercentGauge;
+ {#Z-}
+ TPercentGauge = Object(TGauge)
+ { A TPercentGauge displays a numerical percentage as returned by
+ #Percent# followed by a '%' sign. }
+ function Percent : Integer; virtual;
+ { Percent returns the whole number value of (Current / Max) * 100. }
+ {#X TGauge.Current TGauge.Max }
+ procedure Draw; virtual;
+ { Draw writes the current percentage to the screen. }
+ {#X Percent }
+ end; { of TPercentGauge }
+
+
+ {#Z+}
+ PBarGauge = ^TBarGauge;
+ {#Z-}
+ TBarGauge = Object(TPercentGauge)
+ { A TBarGauge displays a bar which increases in size from the left to
+ the right of the view as Current increases. A numeric percentage
+ representing the value of (Current / Max) * 100 is displayed in the
+ center of the bar. }
+ {#x TPercentGauge.Percent }
+ procedure Draw; virtual;
+ { Draw draws the bar and percentage to the screen representing the
+ current status of the view's variables. }
+ {#X TGauge.Update }
+ function GetPalette : PPalette; virtual;
+ { GetPalette returns a pointer to the default status view palette,
+ #CBarStatus#. }
+ end; { of TBarGauge }
+
+
+ {#Z+}
+ PSpinnerGauge = ^TSpinnerGauge;
+ {#Z-}
+ TSpinnerGauge = Object(TGauge)
+ { A TSpinnerGauge displays a series of characters in one spot on the
+ screen giving the illusion of a spinning line. }
+ constructor Init (X, Y : Integer; ACommand : Word);
+ { Init calls the inherited constructor with AMin set to 0 and AMax set
+ to 4. }
+ procedure Draw; virtual;
+ { Draw uses the #SpinChars# variable to draw the view's Current
+ character. }
+ {#X Update }
+ procedure HandleEvent (var Event : TEvent); virtual;
+ { HandleEvent calls TStatus.HandleEvent so that a cmStatusDone event
+ is not generated when Current equals Max. }
+ {#X TGauge.Current TGauge.Max }
+ procedure Update (Data : Pointer); virtual;
+ { Update increments Current until Current equals Max, when it resets
+ Current to Min. }
+ {#X Draw HandleEvent }
+ end; { of TSpinnerGauge }
+
+
+ {#Z+}
+ PAppStatus = ^TAppStatus;
+ {#Z-}
+ TAppStatus = Object(TStatus)
+ { TAppStatus is a base object which implements color control for status
+ views that are normally inserted in the Application object. }
+ {#X TStatus }
+ function GetPalette : PPalette; virtual;
+ { GetPalette returns a pointer to the default application status view
+ palette, #CAppStatus#. }
+ {#X TStatus CStatus }
+ end; { of TAppStatus }
+
+
+ {#Z+}
+ PHeapMaxAvail = ^THeapMaxAvail;
+ {#Z-}
+ THeapMaxAvail = Object(TAppStatus)
+ { A THeapMaxAvail displays the largest available contiguous area of heap
+ memory. It responds to a cmStatusUpdate event by calling MaxAvail and
+ comparing the result to #Max#, then updating the view if necessary. }
+ {#X THeapMemAvail }
+ constructor Init (X, Y : Integer);
+ { Init creates the view with the following text:
+
+ MaxAvail = xxxx
+
+ where xxxx is the result returned by MaxAvail. }
+ procedure Update (Data : Pointer); virtual;
+ { Update changes #Mem# to the current MemAvail and redraws the status
+ if necessary. }
+ private
+ Max : LongInt;
+ { Max is the last reported value from MaxAvail. }
+ {#X Update }
+ end; { of THeapMaxAvail }
+
+
+ {#Z+}
+ PHeapMemAvail = ^THeapMemAvail;
+ {#Z-}
+ THeapMemAvail = Object(TAppStatus)
+ { A THeapMemAvail displays the total amount of heap memory available to
+ the application. It responds to a cmStatusUpdate event by calling
+ MemAvail and comparing the result to #Max#, then updating the view if
+ necessary. }
+ {#X THeapMaxAvail }
+ constructor Init (X, Y : Integer);
+ { Init creates the view with the following text:
+
+ MemAvail = xxxx
+
+ where xxxx is the result returned by MemAvail. }
+ {#X Load }
+ procedure Update (Data : Pointer); virtual;
+ { Update changes #Mem# to the current MemAvail and redraws the status
+ if necessary. }
+ private
+ Mem : LongInt;
+ { Mem is the last available value reported by MemAvail. }
+ {#X Update }
+ end; { of THeapMemAvail }
+
+
+{$ifndef cdPrintDoc}
+{#Z+}
+{$endif cdPrintDoc}
+const
+ RStatus : TStreamRec = (
+ ObjType : idStatus;
+ VmtLink : Ofs(TypeOf(TStatus)^);
+ Load : @TStatus.Load;
+ Store : @TStatus.Store);
+
+ RStatusDlg : TStreamRec = (
+ ObjType : idStatusDlg;
+ VmtLink : Ofs(TypeOf(TStatusDlg)^);
+ Load : @TStatusDlg.Load;
+ Store : @TStatusDlg.Store);
+
+ RStatusMessageDlg : TStreamRec = (
+ ObjType : idStatusMessageDlg;
+ VmtLink : Ofs(TypeOf(TStatusMessageDlg)^);
+ Load : @TStatusMessageDlg.Load;
+ Store : @TStatusMessageDlg.Store);
+
+ RGauge : TStreamRec = (
+ ObjType : idGauge;
+ VmtLink : Ofs(TypeOf(TGauge)^);
+ Load : @TGauge.Load;
+ Store : @TGauge.Store);
+
+ RArrowGauge : TStreamRec = (
+ ObjType : idArrowGauge;
+ VmtLink : Ofs(TypeOf(TArrowGauge)^);
+ Load : @TArrowGauge.Load;
+ Store : @TArrowGauge.Store);
+
+ RBarGauge : TStreamRec = (
+ ObjType : idBarGauge;
+ VmtLink : Ofs(TypeOf(TBarGauge)^);
+ Load : @TBarGauge.Load;
+ Store : @TBarGauge.Store);
+
+ RPercentGauge : TStreamRec = (
+ ObjType : idPercentGauge;
+ VmtLink : Ofs(TypeOf(TPercentGauge)^);
+ Load : @TPercentGauge.Load;
+ Store : @TPercentGauge.Store);
+
+ RSpinnerGauge : TStreamRec = (
+ ObjType : idSpinnerGauge;
+ VmtLink : Ofs(TypeOf(TSpinnerGauge)^);
+ Load : @TSpinnerGauge.Load;
+ Store : @TSpinnerGauge.Store);
+
+ RAppStatus : TStreamRec = (
+ ObjType : idAppStatus;
+ VmtLink : Ofs(TypeOf(TAppStatus)^);
+ Load : @TAppStatus.Load;
+ Store : @TAppStatus.Store);
+
+ RHeapMinAvail : TStreamRec = (
+ ObjType : idHeapMinAvail;
+ VmtLink : Ofs(TypeOf(THeapMaxAvail)^);
+ Load : @THeapMaxAvail.Load;
+ Store : @THeapMaxAvail.Store);
+
+ RHeapMemAvail : TStreamRec = (
+ ObjType : idHeapMemAvail;
+ VmtLink : Ofs(TypeOf(THeapMemAvail)^);
+ Load : @THeapMemAvail.Load;
+ Store : @THeapMemAvail.Store);
+{$ifndef cdPrintDoc}
+{#Z-}
+{$endif cdPrintDoc}
+
+procedure RegisterStatuses;
+{$ifndef cdPrintDoc}
+{#F+}
+{ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
+ÝRegisterStatuses procedure (Statuses unit)Þ
+ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß}
+{#F-}
+{$endif cdPrintDoc}
+ { RegisterStatuses calls RegisterType for each of the status view and
+ status dialog object types defined in the tvStatus unit. After calling
+ RegisterStatuses, your application can read or write any of those types
+ with streams. }
+
+
+implementation
+
+uses
+ MsgBox, App;
+
+{****************************************************************************}
+{ Local procedures and functions }
+{****************************************************************************}
+
+{****************************************************************************}
+{ TAppStatus Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TAppStatus.GetPalette }
+{****************************************************************************}
+function TAppStatus.GetPalette : PPalette;
+const P : String[Length(CAppStatus)] = CAppStatus;
+begin
+ GetPalette := PPalette(@P);
+end;
+
+{****************************************************************************}
+{ TArrowGauge Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TArrowGauge.Init }
+{****************************************************************************}
+constructor TArrowGauge.Init (R : TRect; ACommand : Word; AMin, AMax : Word;
+ RightArrow : Boolean);
+begin
+ if not TGauge.Init(R,ACommand,AMin,AMax) then
+ Fail;
+ Right := RightArrow;
+end;
+
+{****************************************************************************}
+{ TArrowGauge.Load }
+{****************************************************************************}
+constructor TArrowGauge.Load (var S : TStream);
+begin
+ if not TGauge.Load(S) then
+ Fail;
+ S.Read(Right,SizeOf(Right));
+ if (S.Status <> stOk) then
+ begin
+ TGauge.Done;
+ Fail;
+ end;
+end;
+
+{****************************************************************************}
+{ TArrowGauge.Draw }
+{****************************************************************************}
+procedure TArrowGauge.Draw;
+const Arrows : array[0..1] of Char = '<>';
+var
+ B : TDrawBuffer;
+ C : Word;
+ Len : Byte;
+begin
+ C := GetColor(1);
+ Len := Round(Size.X * Current/(Max - Min));
+ MoveChar(B,' ',C,Size.X);
+ if Right then
+ MoveChar(B,Arrows[Byte(Right)],C,Len)
+ else MoveChar(B[Size.X - Len],Arrows[Byte(Right)],C,Len);
+ WriteLine(0,0,Size.X,1,B);
+end;
+
+{****************************************************************************}
+{ TArrowGauge.GetData }
+{****************************************************************************}
+procedure TArrowGauge.GetData (var Rec);
+begin
+ PArrowGaugeRec(Rec)^.Min := Min;
+ PArrowGaugeRec(Rec)^.Max := Max;
+ PArrowGaugeRec(Rec)^.Count := Current;
+ PArrowGaugeRec(Rec)^.Right := Right;
+end;
+
+{****************************************************************************}
+{ TArrowGauge.SetData }
+{****************************************************************************}
+procedure TArrowGauge.SetData (var Rec);
+begin
+ Min := PArrowGaugeRec(Rec)^.Min;
+ Max := PArrowGaugeRec(Rec)^.Max;
+ Current := PArrowGaugeRec(Rec)^.Count;
+ Right := PArrowGaugeRec(Rec)^.Right;
+end;
+
+{****************************************************************************}
+{ TArrowGauge.Store }
+{****************************************************************************}
+procedure TArrowGauge.Store (var S : TStream);
+begin
+ TGauge.Store(S);
+ S.Write(Right,SizeOf(Right));
+end;
+
+{****************************************************************************}
+{ TBarGauge Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TBarGauge.Draw }
+{****************************************************************************}
+procedure TBarGauge.Draw;
+var
+ B : TDrawBuffer;
+ C : Word;
+ FillSize : Word;
+ PercentDone : LongInt;
+ S : String[4];
+begin
+ { fill entire view }
+ MoveChar(B,' ',GetColor(4),Size.X);
+ { make progress bar }
+ C := GetColor(5);
+ FillSize := Round(Size.X * (Current / Max));
+ MoveChar(B,' ',C,FillSize);
+ { display percent done }
+ PercentDone := Percent;
+ FormatStr(S,'%d%%',PercentDone);
+ if PercentDone < 50 then
+ C := GetColor(4);
+ FillSize := (Size.X - Length(S)) div 2;
+ MoveStr(B[FillSize],S,C);
+ WriteLine(0,0,Size.X,Size.Y,B);
+end;
+
+{****************************************************************************}
+{ TBarGauge.GetPalette }
+{****************************************************************************}
+function TBarGauge.GetPalette : PPalette;
+const
+ S : String[Length(CBarGauge)] = CBarGauge;
+begin
+ GetPalette := PPalette(@S);
+end;
+
+{****************************************************************************}
+{ TGauge Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TGauge.Init }
+{****************************************************************************}
+constructor TGauge.Init (R : TRect; ACommand : Word; AMin, AMax : LongInt);
+begin
+ if not TStatus.Init(R,ACommand,'',1) then
+ Fail;
+ Min := AMin;
+ Max := AMax;
+ Current := Min;
+end;
+
+{****************************************************************************}
+{ TGauge.Load }
+{****************************************************************************}
+constructor TGauge.Load (var S : TStream);
+begin
+ if not TStatus.Load(S) then
+ Fail;
+ S.Read(Min,SizeOf(Min));
+ S.Read(Max,SizeOf(Max));
+ S.Read(Current,SizeOf(Current));
+ if S.Status <> stOk then
+ begin
+ TStatus.Done;
+ Fail;
+ end;
+end;
+
+{****************************************************************************}
+{ TGauge.Draw }
+{****************************************************************************}
+procedure TGauge.Draw;
+var
+ S : String;
+ B : TDrawBuffer;
+begin
+ { Blank the gauge }
+ MoveChar(B,' ',GetColor(1),Size.X);
+ WriteBuf(0,0,Size.X,Size.Y,B);
+ { write current status }
+ FormatStr(S,'%d',Current);
+ MoveStr(B,S,GetColor(1));
+ WriteBuf(0,0,Size.X,Size.Y,B);
+end;
+
+{****************************************************************************}
+{ TGauge.GetData }
+{****************************************************************************}
+procedure TGauge.GetData (var Rec);
+begin
+ TGaugeRec(Rec).Min := Min;
+ TGaugeRec(Rec).Max := Max;
+ TGaugeRec(Rec).Current := Current;
+end;
+
+{****************************************************************************}
+{ TGauge.Reset }
+{****************************************************************************}
+procedure TGauge.Reset;
+begin
+ Current := Min;
+ DrawView;
+end;
+
+{****************************************************************************}
+{ TGauge.SetData }
+{****************************************************************************}
+procedure TGauge.SetData (var Rec);
+begin
+ Min := TGaugeRec(Rec).Min;
+ Max := TGaugeRec(Rec).Max;
+ Current := TGaugeRec(Rec).Current;
+end;
+
+{****************************************************************************}
+{ TGauge.Store }
+{****************************************************************************}
+procedure TGauge.Store (var S : TStream);
+begin
+ TStatus.Store(S);
+ S.Write(Min,SizeOf(Min));
+ S.Write(Max,SizeOf(Max));
+ S.Write(Current,SizeOf(Current));
+end;
+
+{****************************************************************************}
+{ TGauge.Update }
+{****************************************************************************}
+procedure TGauge.Update (Data : Pointer);
+begin
+ if Current < Max then
+ begin
+ Inc(Current);
+ DrawView;
+ end
+ else Message(@Self,evStatus,cmStatusDone,@Self);
+end;
+
+{****************************************************************************}
+{ THeapMaxAvail Object }
+{****************************************************************************}
+{****************************************************************************}
+{ THeapMaxAvail.Init }
+{****************************************************************************}
+constructor THeapMaxAvail.Init (X, Y : Integer);
+var
+ R : TRect;
+begin
+ R.Assign(X,Y,X+20,Y+1);
+ if not TAppStatus.Init(R,cmStatusUpdate,' MaxAvail = %d',1) then
+ Fail;
+ Max := -1;
+end;
+
+{****************************************************************************}
+{ THeapMaxAvail.Update }
+{****************************************************************************}
+procedure THeapMaxAvail.Update (Data : Pointer);
+var
+ M : LongInt;
+begin
+ M := MaxAvail;
+ if (Max <> M) then
+ begin
+ Max := MaxAvail;
+ SetData(Max);
+ end;
+end;
+
+{****************************************************************************}
+{ THeapMemAvail Object }
+{****************************************************************************}
+{****************************************************************************}
+{ THeapMemAvail.Init }
+{****************************************************************************}
+constructor THeapMemAvail.Init (X, Y : Integer);
+var
+ R : TRect;
+begin
+ R.Assign(X,Y,X+20,Y+1);
+ if not TAppStatus.Init(R,cmStatusUpdate,' MemAvail = %d',1) then
+ Fail;
+ Mem := -1;
+end;
+
+{****************************************************************************}
+{ THeapMemAvail.Update }
+{****************************************************************************}
+procedure THeapMemAvail.Update (Data : Pointer);
+ { Total bytes available on the heap. May not be contiguous. }
+var
+ M : LongInt;
+begin
+ M := MemAvail;
+ if (Mem <> M) then
+ begin
+ Mem := M;
+ SetData(Mem);
+ end;
+end;
+
+{****************************************************************************}
+{ TPercentGauge Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TPercentGauge.Draw }
+{****************************************************************************}
+procedure TPercentGauge.Draw;
+var
+ B : TDrawBuffer;
+ C : Word;
+ S : String;
+ PercentDone : LongInt;
+ FillSize : Integer;
+begin
+ C := GetColor(1);
+ MoveChar(B,' ',C,Size.X);
+ WriteLine(0,0,Size.X,Size.Y,B);
+ PercentDone := Percent;
+ FormatStr(S,'%d%%',PercentDone);
+ MoveStr(B[(Size.X - Byte(S[0])) div 2],S,C);
+ WriteLine(0,0,Size.X,Size.Y,B);
+end;
+
+{****************************************************************************}
+{ TPercentGauge.Percent }
+{****************************************************************************}
+function TPercentGauge.Percent : Integer;
+ { Returns percent as a whole integer Current of Max }
+begin
+ Percent := Round((Current/Max) * 100);
+end;
+
+{****************************************************************************}
+{ TSpinnerGauge Object }
+{****************************************************************************}
+
+{****************************************************************************}
+{ TSpinnerGauge.Init }
+{****************************************************************************}
+constructor TSpinnerGauge.Init (X, Y : Integer; ACommand : Word);
+var R : TRect;
+begin
+ R.Assign(X,Y,X+1,Y+1);
+ if not TGauge.Init(R,ACommand,1,4) then
+ Fail;
+end;
+
+{****************************************************************************}
+{ TSpinnerGauge.Draw }
+{****************************************************************************}
+procedure TSpinnerGauge.Draw;
+var
+ B : TDrawBuffer;
+ C : Word;
+begin
+ C := GetColor(1);
+ MoveChar(B,' ',C,Size.X);
+ WriteLine(0,0,Size.X,Size.Y,B);
+ MoveChar(B[Size.X div 2],SpinChars[Current],C,1);
+ WriteLine(0,0,Size.X,Size.Y,B);
+end;
+
+{****************************************************************************}
+{ TSpinnerGauge.HandleEvent }
+{****************************************************************************}
+procedure TSpinnerGauge.HandleEvent (var Event : TEvent);
+begin
+ TStatus.HandleEvent(Event);
+end;
+
+{****************************************************************************}
+{ TSpinnerGauge.Update }
+{****************************************************************************}
+procedure TSpinnerGauge.Update (Data : Pointer);
+begin
+ if Current = Max then
+ Current := Min
+ else Inc(Current);
+ DrawView;
+end;
+
+{****************************************************************************}
+{ TStatus Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TStatus.Init }
+{****************************************************************************}
+constructor TStatus.Init (R : TRect; ACommand : Word; AText : String;
+ AParamCount : Integer);
+begin
+ if (not TParamText.Init(R,AText,AParamCount)) then
+ Fail;
+ EventMask := EventMask or evStatus;
+ Command := ACommand;
+end;
+
+{****************************************************************************}
+{ TStatus.Load }
+{****************************************************************************}
+constructor TStatus.Load (var S : TStream);
+begin
+ if not TParamText.Load(S) then
+ Fail;
+ S.Read(Command,SizeOf(Command));
+ if (S.Status <> stOk) then
+ begin
+ TParamText.Done;
+ Fail;
+ end;
+end;
+
+{****************************************************************************}
+{ TStatus.Cancel }
+{****************************************************************************}
+function TStatus.Cancel : Boolean;
+begin
+ Cancel := True;
+end;
+
+{****************************************************************************}
+{ TStatus.GetPalette }
+{****************************************************************************}
+function TStatus.GetPalette : PPalette;
+const
+ P : String[Length(CStatus)] = CStatus;
+begin
+ GetPalette := PPalette(@P);
+end;
+
+{****************************************************************************}
+{ TStatus.HandleEvent }
+{****************************************************************************}
+procedure TStatus.HandleEvent (var Event : TEvent);
+begin
+ if (Event.What = evCommand) and (Event.Command = cmStatusPause) then
+ begin
+ Pause;
+ ClearEvent(Event);
+ end;
+ case Event.What of
+ evStatus :
+ case Event.Command of
+ cmStatusDone :
+ if (Event.InfoPtr = @Self) then
+ begin
+ Message(Owner,evStatus,cmStatusDone,@Self);
+ ClearEvent(Event);
+ end;
+ cmStatusUpdate :
+ if (Event.InfoWord = Command) and ((State and sfPause) = 0) then
+ begin
+ Update(Event.InfoPtr);
+ { ClearEvent(Event); } { don't clear the event so multiple }
+ { status views can respond to the same event }
+ end;
+ cmStatusResume :
+ if (Event.InfoWord = Command) and
+ ((State and sfPause) = sfPause) then
+ begin
+ Resume;
+ ClearEvent(Event);
+ end;
+ cmStatusPause :
+ if (Event.InfoWord = Command) and ((State and sfPause) = 0) then
+ begin
+ Pause;
+ ClearEvent(Event);
+ end;
+ end;
+ end;
+ TParamText.HandleEvent(Event);
+end;
+
+{****************************************************************************}
+{ TStatus.Pause }
+{****************************************************************************}
+procedure TStatus.Pause;
+begin
+ SetState(sfPause,True);
+end;
+
+{****************************************************************************}
+{ TStatus.Reset }
+{****************************************************************************}
+procedure TStatus.Reset;
+begin
+ DrawView;
+end;
+
+{****************************************************************************}
+{ TStatus.Resume }
+{****************************************************************************}
+procedure TStatus.Resume;
+begin
+ SetState(sfPause,False);
+end;
+
+{****************************************************************************}
+{ TStatus.Store }
+{****************************************************************************}
+procedure TStatus.Store (var S : TStream);
+begin
+ TParamText.Store(S);
+ S.Write(Command,SizeOf(Command));
+end;
+
+{****************************************************************************}
+{ TStatus.Update }
+{****************************************************************************}
+procedure TStatus.Update (Data : Pointer);
+begin
+ DisposeStr(Text);
+ Text := NewStr(String(Data^));
+ DrawView;
+end;
+
+{****************************************************************************}
+{ TStatusDlg Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TStatusDlg.Init }
+{****************************************************************************}
+constructor TStatusDlg.Init (ATitle : TTitleStr; AStatus : PStatus;
+ AFlags : Word);
+var
+ R : TRect;
+ i : LongInt;
+ Buttons : Byte;
+begin
+ if (AStatus = nil) then
+ Fail;
+ R.A := AStatus^.Origin;
+ R.B := AStatus^.Size;
+ Inc(R.B.Y,R.A.Y+4);
+ Inc(R.B.X,R.A.X+5);
+ if not TDialog.Init(R,ATitle) then
+ Fail;
+ EventMask := EventMask or evStatus;
+ Status := AStatus;
+ Status^.MoveTo(2,2);
+ Insert(Status);
+ InsertButtons(AFlags);
+end;
+
+{****************************************************************************}
+{ TStatusDlg.Load }
+{****************************************************************************}
+constructor TStatusDlg.Load (var S : TStream);
+begin
+ if not TDialog.Load(S) then
+ Fail;
+ GetSubViewPtr(S,Status);
+ if (S.Status <> stOk) then
+ begin
+ if (Status <> nil) then
+ Dispose(Status,Done);
+ TDialog.Done;
+ Fail;
+ end;
+end;
+
+{****************************************************************************}
+{ TStatusDlg.Cancel }
+{****************************************************************************}
+procedure TStatusDlg.Cancel (ACommand : Word);
+begin
+ if Status^.Cancel then
+ TDialog.Cancel(ACommand);
+end;
+
+{****************************************************************************}
+{ TStatusDlg.HandleEvent }
+{****************************************************************************}
+procedure TStatusDlg.HandleEvent (var Event : TEvent);
+begin
+ case Event.What of
+ evStatus :
+ case Event.Command of
+ cmStatusDone :
+ if Event.InfoPtr = Status then
+ begin
+ TDialog.Cancel(cmOk);
+ ClearEvent(Event);
+ end;
+ end;
+ { else let TDialog.HandleEvent send to all subviews for handling }
+ evBroadcast, evCommand :
+ case Event.Command of
+ cmCancel, cmClose :
+ begin
+ Cancel(cmCancel);
+ ClearEvent(Event);
+ end;
+ cmStatusPause :
+ begin
+ Status^.Pause;
+ ClearEvent(Event);
+ end;
+ cmStatusResume :
+ begin
+ Status^.Resume;
+ ClearEvent(Event);
+ end;
+ end;
+ end;
+ TDialog.HandleEvent(Event);
+end;
+
+{****************************************************************************}
+{ TStatusDlg.InsertButtons }
+{****************************************************************************}
+procedure TStatusDlg.InsertButtons (AFlags : Word);
+var
+ R : TRect;
+ P : PButton;
+ Buttons : Byte;
+ X, Y, Gap : Integer;
+ i : Word;
+begin
+ Buttons := Byte(((AFlags and sdCancelButton) = sdCancelButton));
+ { do this Inc twice, once for Pause and once for Resume buttons }
+ Inc(Buttons,2 * Byte(((AFlags and sdPauseButton) = sdPauseButton)));
+ if Buttons > 0 then
+ begin
+ Status^.GrowMode := gfGrowHiX;
+ { resize dialog to hold all requested buttons }
+ if Size.X < ((Buttons * 12) + 2) then
+ GrowTo((Buttons * 12) + 2,Size.Y + 2)
+ else GrowTo(Size.X,Size.Y + 2);
+ { find correct starting position for first button }
+ Gap := Size.X - (Buttons * 10) - 2;
+ Gap := Gap div Succ(Buttons);
+ X := Gap;
+ if X < 2 then
+ X := 2;
+ Y := Size.Y - 3;
+ { insert buttons }
+ if ((AFlags and sdCancelButton) = sdCancelButton) then
+ begin
+ P := NewButton(X,Y,10,2,'Cancel',cmCancel,hcCancel,bfDefault);
+ P^.GrowMode := gfGrowHiY or gfGrowLoY;
+ Inc(X,12 + Gap);
+ end;
+ if ((AFlags and sdPauseButton) = sdPauseButton) then
+ begin
+ P := NewButton(X,Y,10,2,'~P~ause',cmStatusPause,hcStatusPause,bfNormal);
+ P^.GrowMode := gfGrowHiY or gfGrowLoY;
+ Inc(X,12 + Gap);
+ P := NewButton(X,Y,10,2,'~R~esume',cmStatusResume,hcStatusResume,
+ bfBroadcast);
+ P^.GrowMode := gfGrowHiY or gfGrowLoY;
+ end;
+ end; { of if }
+ SelectNext(False);
+end;
+
+{****************************************************************************}
+{ TStatusDlg.Store }
+{****************************************************************************}
+procedure TStatusDlg.Store (var S : TStream);
+begin
+ TDialog.Store(S);
+ PutSubViewPtr(S,Status);
+end;
+
+{****************************************************************************}
+{ TStatusMessageDlg Object }
+{****************************************************************************}
+{****************************************************************************}
+{ TStatusMessageDlg.Init }
+{****************************************************************************}
+constructor TStatusMessageDlg.Init (ATitle : TTitleStr; AStatus : PStatus;
+ AFlags : Word; AMessage : String);
+var
+ P : PStaticText;
+ X, Y : Integer;
+ R : TRect;
+begin
+ if not TStatusDlg.Init(ATitle,AStatus,AFlags) then
+ Fail;
+ Status^.GrowMode := gfGrowLoY or gfGrowHiY;
+ GetExtent(R);
+ X := R.B.X - R.A.X;
+ if X < Size.X then
+ X := Size.X;
+ Y := R.B.Y - R.A.Y;
+ if Y < Size.Y then
+ Y := Size.Y;
+ GrowTo(X,Y);
+ R.Assign(2,2,Size.X-2,Size.Y-3);
+ P := New(PStaticText,Init(R,AMessage));
+ if (P = nil) then
+ begin
+ TStatusDlg.Done;
+ Fail;
+ end;
+ GrowTo(Size.X,Size.Y + P^.Size.Y + 1);
+ Insert(P);
+end;
+
+{****************************************************************************}
+{ Global procedures and functions }
+{****************************************************************************}
+
+{****************************************************************************}
+{ RegisterStatuses }
+{****************************************************************************}
+procedure RegisterStatuses;
+begin
+{ RegisterType(RStatus);
+ RegisterType(RStatusDlg);
+ RegisterType(RGauge);
+ RegisterType(RArrowGauge);
+ RegisterType(RPercentGauge);
+ RegisterType(RBarGauge);
+ RegisterType(RSpinnerGauge); }
+end;
+
+{****************************************************************************}
+{ Unit Initialization }
+{****************************************************************************}
+begin
+end.