home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d56 / RMCTL.ZIP / rmDiffMap.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-22  |  11KB  |  359 lines

  1. {================================================================================
  2. Copyright (C) 1997-2001 Mills Enterprise
  3.  
  4. Unit     : rmDiffMap
  5. Purpose  : This is a map component primarily used in showing where the
  6.            differences are with in the mapping of the rmDiff Components.
  7. Date     : 04-24-2000
  8. Author   : Ryan J. Mills
  9. Version  : 1.80
  10. Notes    : This component originally came to me from Bernie Caudrey.
  11.            I've only modified the original source to work with my rmDiff
  12.            components.  I would like to go back and rewrite the drawing and
  13.            mapping algorithms because I think they are unnecessarily complex.
  14.            It also doesn't use any resources where it should.
  15. ================================================================================}
  16.  
  17. unit rmDiffMap;
  18.  
  19. interface
  20.  
  21. uses
  22.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  23.   ExtCtrls;
  24.  
  25. type
  26.    TAByte = array of BYTE;
  27.    pAByte = ^TAByte;
  28.  
  29.   TMapClickEvent = procedure(Sender:TObject; IndicatorPos : integer) of object;
  30.  
  31.   TrmDiffMap = class(TCustomControl)
  32.   private
  33.     { Private declarations }
  34.     FColorDeleted     : TColor;
  35.     FColorInserted    : TColor;
  36.     FColorModified    : TColor;
  37.     FShowIndicator    : Boolean;
  38.     FIndicatorPos     : integer;
  39.     FRows             : integer;
  40.     FIndicator        : TBitmap;
  41.     FData             : TAByte;
  42.     FOnMapClick : TMapClickEvent;
  43.     procedure DrawIndicator;
  44.     procedure SetIndicatorPos(Value : integer);
  45.     function  MapHeight : integer;
  46.   protected
  47.     { Protected declarations }
  48.     procedure Paint; override;
  49.   public
  50.     { Public declarations }
  51.     constructor Create(AOwner : TComponent); override;
  52.     destructor  Destroy; override;
  53.     procedure   SetData(Value : TAByte; Size : integer);
  54.     procedure   MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : Integer); override;
  55.     property    Data : TAByte read FData;
  56.   published
  57.     { Published declarations }
  58.     property Color;
  59.     property Caption;
  60.     property Align;
  61.     property BevelInner;
  62.     property BevelOuter;
  63.     property BevelWidth;
  64.     property ColorDeleted     : TColor  read FColorDeleted     write FColorDeleted;
  65.     property ColorInserted    : TColor  read FColorInserted    write FColorInserted;
  66.     property ColorModified    : TColor  read FColorModified    write FColorModified;
  67.     property ShowIndicator    : Boolean read FShowIndicator    write FShowIndicator;
  68.     property IndicatorPos     : integer read FIndicatorPos     write SetIndicatorPos;
  69.     property IndicatorRange   : integer read FRows;
  70.     property OnMapClick : TMapClickEvent read FOnMapClick write FOnMapClick;
  71.   end;
  72.  
  73. implementation
  74.  
  75. const
  76. TOP_MARGIN      = 5;
  77.       BOTTOM_MARGIN   = 5;
  78.       INDICATOR_WIDTH = 4;
  79.  
  80.       // These constants are reproduced here from IntfDifferenceEngine.pas
  81.       RECORD_SAME     = 0;
  82.       RECORD_DELETED  = 1;
  83.       RECORD_INSERTED = 2;
  84.       RECORD_MODIFIED = 3;
  85.  
  86. constructor TrmDiffMap.Create(AOwner : TComponent);
  87. begin
  88.    inherited;
  89.    FShowIndicator      := True;
  90.    FColorDeleted       := clRed;
  91.    FColorInserted      := clLime;
  92.    FColorModified      := clYellow;
  93.    Caption             := '';
  94.    FData               := nil;
  95.    FRows               := 0;
  96.    IndicatorPos        := 0;
  97.  
  98.    FIndicator          := TBitmap.Create;
  99.    FIndicator.Width    := 4;
  100.    FIndicator.Height   := 6;
  101.  
  102.    FIndicator.Canvas.Pixels[0,0] := clBlack;
  103.    FIndicator.Canvas.Pixels[0,1] := clBlack;
  104.    FIndicator.Canvas.Pixels[0,2] := clBlack;
  105.    FIndicator.Canvas.Pixels[0,3] := clBlack;
  106.    FIndicator.Canvas.Pixels[0,4] := clBlack;
  107.    FIndicator.Canvas.Pixels[1,1] := clBlack;
  108.    FIndicator.Canvas.Pixels[1,2] := clBlack;
  109.    FIndicator.Canvas.Pixels[1,3] := clBlack;
  110.    FIndicator.Canvas.Pixels[2,2] := clBlack;
  111.  
  112.    FIndicator.Canvas.Pixels[1,0] := clFuchsia;
  113.    FIndicator.Canvas.Pixels[2,0] := clFuchsia;
  114.    FIndicator.Canvas.Pixels[2,1] := clFuchsia;
  115.    FIndicator.Canvas.Pixels[3,2] := clFuchsia;
  116.    FIndicator.Canvas.Pixels[1,4] := clFuchsia;
  117.    FIndicator.Canvas.Pixels[2,4] := clFuchsia;
  118.  
  119.    FIndicator.TransparentMode  := tmFixed;
  120.    FIndicator.TransparentColor := clFuchsia;
  121.    FIndicator.Transparent      := True;
  122.    fIndicator.SaveToFile('c:\indicator.bmp');
  123. end;
  124.  
  125.  
  126. destructor TrmDiffMap.Destroy;
  127. begin
  128.    if FData <> nil then begin
  129.       FData := nil;
  130.    end;
  131.    FIndicator.Free;
  132.    inherited;
  133. end;
  134.  
  135.  
  136. procedure TrmDiffMap.SetData(Value : TAByte; Size : integer);
  137. begin
  138.    if FData <> nil then begin
  139.       FData := nil;
  140.    end;
  141.  
  142.    FData := Value;
  143.  
  144.    if FData <> nil then begin
  145.       FRows := Size;
  146.    end else begin
  147.       FRows := 0;
  148.    end;
  149. end;
  150.  
  151.  
  152.  
  153. procedure TrmDiffMap.SetIndicatorPos(Value : integer);
  154. begin
  155.    FIndicatorPos := Value;
  156.    Refresh;
  157. end;
  158.  
  159. procedure TrmDiffMap.Paint;
  160. var
  161.    i               : Integer;
  162.    j               : Integer;
  163.    NrOfDataRows    : Integer;
  164.    Ht              : Integer;
  165.    Ct              : Integer;
  166.    CurrIndex       : Integer;
  167.    PixelPos        : Integer;
  168.    PixelHt         : Double;   // amount of pixel height for each row - could be a rather small number
  169.    PixelFrac       : Double;   // Faction part of pixel - left over from previous
  170.    PixelPrevHt     : Double;   // logical height of previous mapped pixel (eg. .92)
  171.    NrOfPixelRows   : Double;   // Number of rows that the current pixel is to represent.
  172.    ExtraPixel      : Double;   // Left over pixel from when calculating number of rows for the next pixel.
  173.                                // eg. 1/.3 = 3 rows, .1 remaining, next 1.1/.3 = 3 rows, .2 remain, next 1.2/.3 = 4 rows.
  174.  
  175.    DrawIt          : Boolean; // Drawing flag for each column
  176.    RowModified     : Boolean;
  177.    RowDeleted      : Boolean;
  178.    RowInserted     : Boolean;
  179.  
  180.    ExitLoop        : Boolean;  // loop control
  181.  
  182.    // Draws the line between two points on the horizonatal line of i.
  183.    procedure DrawLine(X1, X2 : integer);
  184.    var
  185.       k : integer;
  186.    begin
  187.       // What colour?  Black or Background?
  188.       if DrawIt then begin
  189.          if RowModified then begin
  190.             Canvas.Pen.Color := ColorModified;
  191.          end else begin
  192.             if RowInserted then begin
  193.                Canvas.Pen.Color := ColorInserted;
  194.             end else begin
  195.                if RowDeleted then begin
  196.                   Canvas.Pen.Color := ColorDeleted;
  197.                end;
  198.             end;
  199.          end;
  200.       end else begin
  201.          Canvas.Pen.Color := Color;
  202.       end;
  203.       // Draw the pixels for the map here
  204.       for k := 0 to Round(NrOfPixelRows) - 1 do begin
  205.          Canvas.MoveTo(X1, PixelPos + k);
  206.          Canvas.LineTo(X2, PixelPos + k);
  207.       end;
  208.    end;
  209.  
  210. begin
  211.    inherited;
  212.    if csDesigning in ComponentState then begin
  213.       exit;
  214.    end;
  215.  
  216.    Ht         := MapHeight;
  217.    Ct         := FRows;
  218.    if Ct < 1 then begin
  219.       Ct := 1;
  220.    end;
  221.    PixelHt       := Ht / Ct;
  222.    CurrIndex     := 1;
  223.    NrOfPixelRows := 0.0;
  224.    PixelPrevHt   := 0.0;
  225.    PixelPos      := 5;
  226.    i             := 1;
  227.    ExtraPixel    := 0.0;
  228.  
  229.    J := CurrIndex;
  230.    while J < Ct do begin
  231.       NrOfDataRows := 0;
  232.       PixelPrevHt  := PixelPrevHt - NrOfPixelRows; // remainder from prevous pixel row (+ or -)
  233.       PixelFrac    := frac(PixelPrevHt);             // We want just the fractional part!
  234.  
  235.       // Calculate how high the pixel line is to be
  236.       if PixelHt < 1.0 then begin
  237.          NrOfPixelRows := 1.0;                      // Each Pixel line represents one or more rows of data
  238.       end else begin
  239.          NrOfPixelRows := Int(PixelHt + ExtraPixel); // We have several pixel lines for each row of data.
  240.          ExtraPixel    := frac(PixelHt + ExtraPixel);// save frac part for next time
  241.       end;
  242.  
  243.       // Calculate the nr of data rows to be represented by the Pixel Line about to be drawn.
  244.       ExitLoop := False;
  245.       repeat
  246.          // the '.../2.0' checks if half a Pixel Ht will fit, else leave remainder for next row.
  247.          if (PixelFrac + PixelHt <= NrOfPixelRows) or
  248.             (PixelFrac + PixelHt / 2.0 <= NrOfPixelRows) then begin
  249.             PixelFrac := PixelFrac + PixelHt;
  250.             inc(NrOfDataRows);
  251.          end else begin
  252.             ExitLoop := True;
  253.          end;
  254.       until (PixelFrac >= NrOfPixelRows) or (ExitLoop);
  255.  
  256.       // go through each data row, check if a file has been modified.
  257.       // if any file has been modified then we add to the Mapping.
  258.       if NrOfDataRows > 0 then begin
  259.          DrawIt := False;
  260.       end;
  261.  
  262.       RowModified := False;
  263.       RowInserted := False;
  264.       RowDeleted  := False;
  265.  
  266.       for j := j to j + NrOfDataRows - 1 do begin
  267.          if j < ct then begin
  268.             case Data[j] of
  269.                RECORD_MODIFIED :
  270.                begin
  271.                   DrawIt      := True;
  272.                   RowModified := True;
  273.                end;
  274.                RECORD_INSERTED :
  275.                begin
  276.                   DrawIt      := True;
  277.                   RowInserted := True;
  278.                end;
  279.                RECORD_DELETED :
  280.                begin
  281.                   DrawIt     := True;
  282.                   RowDeleted := True;
  283.                end;
  284.             end;
  285.          end else begin
  286.             i := i;
  287.          end;
  288.       end;
  289.  
  290.       // Mapping is drawn here
  291.       if ShowIndicator then begin
  292.          DrawLine(INDICATOR_WIDTH, Width - INDICATOR_WIDTH);
  293.       end else begin
  294.          DrawLine(0, Width);
  295.       end;
  296.       inc(PixelPos, Trunc(NrOfPixelRows));  // the pixel pos on the map.
  297.       PixelPrevHt := int(PixelPrevHt) + PixelFrac;
  298.    end;
  299.  
  300.    if ShowIndicator then begin
  301.       DrawIndicator;
  302.    end;
  303.  
  304. end;
  305.  
  306.  
  307. procedure TrmDiffMap.DrawIndicator;
  308. var
  309.    Y    : integer;
  310. begin
  311.    Canvas.Pen.Color := clBlack;
  312.    if FRows <> 0 then begin
  313.       Y := TOP_MARGIN + Trunc((IndicatorPos / FRows) * MapHeight);
  314.       Canvas.Draw(0, Y - (FIndicator.Height div 2), FIndicator);
  315.    end;
  316. end;
  317.  
  318.  
  319. function TrmDiffMap.MapHeight : integer;
  320. begin
  321.    Result := Height - TOP_MARGIN - BOTTOM_MARGIN;
  322. end;
  323.  
  324.  
  325. procedure TrmDiffMap.MouseDown(Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
  326. var
  327.    NewRow    : Integer;
  328.    NewTopRow : Integer;
  329.    PixelHt   : Double;
  330. begin
  331.    inherited;
  332.    if Assigned(OnMapClick) then begin
  333.       PixelHt := MapHeight / IndicatorRange; // This is how much of a pixel (or how many pixels), each row represents.
  334.       // (the pixel clicked) + Half the Pixel Height + 1.0 / the pixel height
  335.       // eg. Of 1000 rows, in the pixel area height of 500, then pixelHt = .5 (500/1000)
  336.       //     Therefore, if pixel 100 is clicked we get - (100 + .25 + 1) / .5 = 51
  337.       // Y-5, we subtract 5 as we start 5 pixels from the top of lblQuickPickArea.
  338.       NewRow := Round(((Y - TOP_MARGIN) * 1.0 + PixelHt / 2.0 + 1.0) / PixelHt);
  339.  
  340.       if NewRow > IndicatorRange - 1 then begin
  341.          NewRow := IndicatorRange - 1
  342.       end else begin
  343.          if NewRow < 1 then begin
  344.             NewRow := 1;
  345.          end;
  346.       end;
  347.       OnMapClick(self, NewRow);
  348.    end;
  349. end;
  350.  
  351.  
  352. end.
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.