unit MvcGraF;
//*******************************************************
// Form for the bar graph view for example program
// demonstrating the Model/View/Controller (MVC)
// paradigm.
//*******************************************************
// Copyright (C) 1998 John Wiley & Sons, Inc.
// All rights reserved. See additional copyright
// information in Readme.txt.
//*******************************************************

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, StdCtrls, ComCtrls,
  MvcModel;

const
    NUM_COLORS = 13;
type
  TGraphForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    mnuClose: TMenuItem;
    procedure mnuCloseClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure SetValue(x, y : Integer);

    private
      { Private declarations }
      Colors   : array [0..NUM_COLORS - 1] of TColor;
      StartX   : Integer;
      Dragging : Boolean;

    public
      { Public declarations }
      TheModel : TMvcModel;
      TheView  : TMvcView;
  end;

var
    GraphForm: TGraphForm;

implementation

{$R *.DFM}

const
    PI = 3.14159265;
    MARGIN = 10;
    MAX_VALUE = 10000;

procedure TGraphForm.mnuCloseClick(Sender: TObject);
begin
    Close;
end;

procedure TGraphForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    // Destroy the view.
    TheView.Free;

    Action := caFree;
end;

// Draw the data.
procedure TGraphForm.FormPaint(Sender: TObject);
var
    rect               : TRect;
    wid, hgt, i, x, dx : Integer;
begin
    // Erase the form.
    rect.Left := 0;
    rect.Top := 0;
    rect.Right := ClientWidth;
    rect.Bottom := ClientHeight;
    Canvas.Brush.Color := clSilver;
    Canvas.FillRect(rect);

    // Draw the graph.
    wid := ClientWidth - 2 * MARGIN;
    hgt := ClientHeight - 2 * MARGIN;
    dx := wid div TheModel.NumValues;

    rect.Bottom := ClientHeight - MARGIN;
    x := MARGIN;
    for i := 1 to TheModel.NumValues do
    begin
        rect.Left := x;
        rect.Right := x + dx;
        rect.Top := MARGIN + hgt -
            Round(hgt * TheModel.ExpenseValue(i) / MAX_VALUE);
        Canvas.Brush.Color := Colors[i mod NUM_COLORS];
        Canvas.FillRect(rect);
        x := x + dx;
    end;
end;

procedure TGraphForm.FormResize(Sender: TObject);
begin
    Refresh;
end;

// Initialize the list of colors.
procedure TGraphForm.FormCreate(Sender: TObject);
begin
    Colors[0]  := clYellow;
    Colors[1]  := clAqua;
    Colors[2]  := clBlack;
    Colors[3]  := clFuchsia;
    Colors[4]  := clBlue;
    Colors[5]  := clGreen;
    Colors[6]  := clDkGray;
    Colors[7]  := clLime;
    Colors[8]  := clMaroon;
    Colors[9]  := clRed;
    Colors[10] := clTeal;
    Colors[11] := clPurple;
    Colors[12] := clWhite;
end;

// Start dragging.
procedure TGraphForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    if (Button <> mbLeft) then exit;
    Dragging := True;
    StartX := X;
    SetValue(StartX, Y);
end;

// Continue dragging.
procedure TGraphForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
    if (not Dragging) then exit;
    SetValue(StartX, Y);
end;

// Change a value.
procedure TGraphForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    if (not Dragging) then exit;
    Dragging := False;
    SetValue(StartX, Y);
end;

// Set a value given the mouse position.
procedure TGraphForm.SetValue(x, y : Integer);
var
    i, dx, hgt : Integer;
    value      : Single;
begin
    // See which value is being changed.
    dx := (ClientWidth - 2 * MARGIN) div TheModel.NumValues;
    i := 1 + ((x - MARGIN) div dx);
    if ((i < 1) or (i > TheModel.NumValues)) then exit;

    // Calculate the new value.
    hgt := ClientHeight - 2 * MARGIN;
    value := (ClientHeight - MARGIN - y) / hgt * MAX_VALUE;
    TheModel.SetExpenseValue(i, value, nil);
end;

end.
