View Issue Details

IDProjectCategoryView StatusLast Update
0001497JEDI VCL00 JVCL Componentspublic2004-03-20 01:22
ReporterglchapmanAssigned Touser72 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version 
Target VersionFixed in Version 
Summary0001497: TJvBitmapButton should respond to changes in Bitmap property
DescriptionTJvBitmapButton does not respond to changes in its Bitmap property, except for assignments to that property. This is because it does not set the OnChange handler for its Bitmap. Attached diff adds a method to catch Bitmap's OnChange.
TagsNo tags attached.

Activities

2004-03-19 05:32

 

JvBitmapButton.pas.1.diff (1,305 bytes)
--- JvBitmapButton.pas.orig	2004-02-27 06:13:08.000000000 -0800
+++ JvBitmapButton.pas	2004-03-19 04:07:14.000000000 -0800
@@ -57,10 +57,11 @@
     FCaptionLeft: Integer;
     FCaptionTop: Integer;
     FLighterFontColor: TColor;
     FDarkerFontColor: TColor;
     procedure SetBitmap(const Value: TBitmap);
+    procedure BitmapChanged(Sender: TObject);
     procedure MakeNormal;
     procedure MakeDarker;
     procedure MakeLighter;
     procedure SetLatching(const Value: Boolean);
     procedure SetDown(const Value: Boolean);
@@ -119,10 +120,11 @@
   FBitmap := TBitmap.Create;
   FBitmap.Width := 24;
   FBitmap.Height := 24;
   FBitmap.Canvas.Brush.Color := clGray;
   FBitmap.Canvas.FillRect(Rect(1, 1, 23, 23));
+  FBitmap.OnChange:= BitmapChanged;
   FLighter := TBitmap.Create;
   FDarker := TBitmap.Create;
   FNormal := TBitmap.Create;
   FFont := TFont.Create;
 end;
@@ -199,10 +201,14 @@
 procedure TJvBitmapButton.SetBitmap(const Value: TBitmap);
 begin
   FBitmap.Assign(Value);
   FBitmap.Transparent := True;
   FBitmap.TransparentColor := FBitmap.Canvas.Pixels[0, FBitmap.Height - 1];
+end;
+
+procedure TJvBitmapButton.BitmapChanged(Sender: TObject);
+begin
   Width := FBitmap.Width;
   Height := FBitmap.Height;
   UpdateBitmaps;
 end;
 

2004-03-19 05:47

 

JvBitmapButton.pas.2.diff (10,473 bytes)
*** JvBitmapButton.pas.orig	Fri Feb 27 06:13:08 2004
--- JvBitmapButton.pas	Fri Mar 19 06:01:36 2004
***************
*** 39,48 ****
--- 39,51 ----
    {$ENDIF VisualCLX}
    SysUtils, Classes,
    JvComponent, JvTypes;
  
  type
+   PJvRGBTriple = ^TJvRGBTriple;
+   TPixelTransform = procedure(dest, source: PJvRGBTriple);
+ 
    TJvBitmapButton = class(TJvGraphicControl)
    private
      FBitmap: TBitmap;
      FLighter: TBitmap;
      FDarker: TBitmap;
***************
*** 57,69 ****
--- 60,75 ----
      FCaptionLeft: Integer;
      FCaptionTop: Integer;
      FLighterFontColor: TColor;
      FDarkerFontColor: TColor;
      procedure SetBitmap(const Value: TBitmap);
+     procedure BitmapChanged(Sender: TObject);
      procedure MakeNormal;
      procedure MakeDarker;
      procedure MakeLighter;
+     procedure MakeHelperBitmap(Target: TBitmap; Transform: TPixelTransform);
+     procedure MakeCaption(Target: TBitmap; FontColor: TColor);
      procedure SetLatching(const Value: Boolean);
      procedure SetDown(const Value: Boolean);
      procedure SetHotTrack(const Value: Boolean);
      procedure SetCaption(const Value: string);
      procedure SetFont(const Value: TFont);
***************
*** 119,128 ****
--- 125,136 ----
    FBitmap := TBitmap.Create;
    FBitmap.Width := 24;
    FBitmap.Height := 24;
    FBitmap.Canvas.Brush.Color := clGray;
    FBitmap.Canvas.FillRect(Rect(1, 1, 23, 23));
+   FBitmap.PixelFormat:= pf24Bit;
+   FBitmap.OnChange:= BitmapChanged;
    FLighter := TBitmap.Create;
    FDarker := TBitmap.Create;
    FNormal := TBitmap.Create;
    FFont := TFont.Create;
  end;
***************
*** 142,156 ****
    if FPushDown then
      if Assigned(OnClick) then
        inherited Click;
  end;
  
  procedure TJvBitmapButton.MouseDown(Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
!   FPushDown :=
!     FBitmap.Canvas.Pixels[X, Y] <> FBitmap.Canvas.Pixels[0, FBitmap.Height-1];
    Repaint;
    inherited MouseDown(Button, Shift, X, Y);
  end;
  
  procedure TJvBitmapButton.MouseUp(Button: TMouseButton;
--- 150,169 ----
    if FPushDown then
      if Assigned(OnClick) then
        inherited Click;
  end;
  
+ function NonPaletteColor(color: TColor): TColor;
+ begin
+   Result:= color and not $02000000;
+ end;
+ 
  procedure TJvBitmapButton.MouseDown(Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
!   FPushDown := not FBitmap.Transparent or
!     (FBitmap.Canvas.Pixels[X, Y] <> NonPaletteColor(FBitmap.TransparentColor));
    Repaint;
    inherited MouseDown(Button, Shift, X, Y);
  end;
  
  procedure TJvBitmapButton.MouseUp(Button: TMouseButton;
***************
*** 164,188 ****
    Repaint;
    inherited MouseUp(Button, Shift, X, Y);
  end;
  
  procedure TJvBitmapButton.Paint;
- var
-   AColor: TColor;
  begin
    inherited;
    if Assigned(FBitmap) then
    begin
-     AColor := FBitmap.Canvas.Pixels[0, FBitmap.Height - 1];
-     FBitmap.Transparent := True;
-     FBitmap.TransparentColor := AColor;
-     FLighter.Transparent := True;
-     Flighter.TransparentColor := AColor;
-     FDarker.Transparent := True;
-     FDarker.TransparentColor := AColor;
-     FNormal.Transparent := True;
-     FNormal.TransparentColor := AColor;
      if FPushDown then
        Canvas.Draw(1, 1, FDarker)
      else
      begin
        if Down then
--- 177,190 ----
***************
*** 197,208 ****
  end;
  
  procedure TJvBitmapButton.SetBitmap(const Value: TBitmap);
  begin
    FBitmap.Assign(Value);
!   FBitmap.Transparent := True;
!   FBitmap.TransparentColor := FBitmap.Canvas.Pixels[0, FBitmap.Height - 1];
    Width := FBitmap.Width;
    Height := FBitmap.Height;
    UpdateBitmaps;
  end;
  
--- 199,218 ----
  end;
  
  procedure TJvBitmapButton.SetBitmap(const Value: TBitmap);
  begin
    FBitmap.Assign(Value);
! end;
! 
! procedure TJvBitmapButton.BitmapChanged(Sender: TObject);
! begin
!   FBitmap.OnChange:= nil;
!   try
!     FBitmap.PixelFormat:= pf24Bit;
!   finally
!     FBitmap.OnChange:= BitmapChanged;
!   end;
    Width := FBitmap.Width;
    Height := FBitmap.Height;
    UpdateBitmaps;
  end;
  
***************
*** 212,300 ****
    MakeDarker;
    MakeNormal;
    Repaint;
  end;
  
  procedure TJvBitmapButton.MakeLighter;
- var
-   p1, p2: PJvRGBArray;
-   X, Y: Integer;
-   rt, gt, bt: Byte;
-   AColor: TColor;
-   ARect: TRect;
  begin
!   FLighter.Width := FBitmap.Width;
!   FLighter.Height := FBitmap.Height;
!   AColor := ColorToRGB(FBitmap.Canvas.Pixels[0, FBitmap.Height - 1]);
!   rt := GetRValue(AColor);
!   gt := GetGValue(AColor);
!   bt := GetBValue(AColor);
!   FBitmap.PixelFormat := pf24bit;
!   FLighter.PixelFormat := pf24bit;
!   for Y := 0 to FBitmap.Height - 1 do
!   begin
!     p1 := FBitmap.ScanLine[Y];
!     p2 := FLighter.ScanLine[Y];
!     for X := 0 to FBitmap.Width - 1 do
!       if (p1[X].rgbBlue = bt) and (p1[X].rgbGreen = gt) and (p1[X].rgbRed = rt) then
!         p2[X] := p1[X]
!       else
!       begin
!         p2[X].rgbBlue  := $FF - Round(0.8 * Abs($FF - p1[X].rgbBlue));
!         p2[X].rgbGreen := $FF - Round(0.8 * Abs($FF - p1[X].rgbGreen));
!         p2[X].rgbRed   := $FF - Round(0.8 * Abs($FF - p1[X].rgbRed));
!       end;
!   end;
!   if FCaption <> '' then
!   begin
!     Flighter.Canvas.Brush.Style := bsClear;
!     Flighter.Canvas.Font.Assign(FFont);
!     FLighter.Canvas.Font.Color := FLighterFontColor;
!     ARect := Rect(0, 0, Width, Height);
!     FLighter.Canvas.TextRect(ARect, FCaptionLeft, FCaptionTop, FCaption);
!   end;
  end;
  
  procedure TJvBitmapButton.MakeDarker;
  var
!   p1, p2: PJvRGBArray;
    X, Y: Integer;
    rt, gt, bt: Byte;
    AColor: TColor;
-   ARect: TRect;
  begin
!   FDarker.Width := FBitmap.Width;
!   FDarker.Height := FBitmap.Height;
!   AColor := ColorToRGB(FBitmap.Canvas.Pixels[0, FBitmap.Height - 1]);
    rt := GetRValue(AColor);
    gt := GetGValue(AColor);
    bt := GetBValue(AColor);
!   FBitmap.PixelFormat := pf24bit;
!   FDarker.PixelFormat := pf24bit;
    for Y := 0 to FBitmap.Height - 1 do
    begin
      p1 := FBitmap.ScanLine[Y];
!     p2 := FDarker.ScanLine[Y];
!     for X := 0 to FBitmap.Width - 1 do
!     begin
!       if (p1[X].rgbBlue = bt) and (p1[X].rgbGreen = gt) and (p1[X].rgbRed = rt) then
!         p2[X] := p1[X]
        else
!       begin
!         p2[X].rgbBlue  := Round(0.7 * p1[X].rgbBlue);
!         p2[X].rgbGreen := Round(0.7 * p1[X].rgbGreen);
!         p2[X].rgbRed   := Round(0.7 * p1[X].rgbRed);
!       end
      end;
    end;
    if FCaption <> '' then
    begin
!     FDarker.Canvas.Brush.Style := bsClear;
!     FDarker.Canvas.Font.Assign(FFont);
!     FDarker.Canvas.Font.Color := FDarkerFontColor;
      ARect := Rect(0, 0, Width, Height);
!     FDarker.Canvas.TextRect(ARect, FCaptionLeft, FCaptionTop, FCaption);
    end;
  end;
  
  procedure TJvBitmapButton.MouseLeave(AControl: TControl);
  begin
--- 222,303 ----
    MakeDarker;
    MakeNormal;
    Repaint;
  end;
  
+ procedure LighterTransform(dest, source: PJvRGBTriple);
+ begin
+   dest.rgbBlue  := $FF - Round(0.8 * Abs($FF - source.rgbBlue));
+   dest.rgbGreen := $FF - Round(0.8 * Abs($FF - source.rgbGreen));
+   dest.rgbRed   := $FF - Round(0.8 * Abs($FF - source.rgbRed));
+ end;
+ 
  procedure TJvBitmapButton.MakeLighter;
  begin
!   MakeHelperBitmap(FLighter, LighterTransform);
!   MakeCaption(FLighter, FLighterFontColor);
! end;
! 
! procedure DarkerTransform(dest, source: PJvRGBTriple);
! begin
!   dest.rgbBlue  := Round(0.7 * source.rgbBlue);
!   dest.rgbGreen := Round(0.7 * source.rgbGreen);
!   dest.rgbRed   := Round(0.7 * source.rgbRed);
  end;
  
  procedure TJvBitmapButton.MakeDarker;
+ begin
+   MakeHelperBitmap(FDarker, DarkerTransform);
+   MakeCaption(FDarker, FDarkerFontColor);
+ end;
+ 
+ procedure TJvBitmapButton.MakeHelperBitmap(Target: TBitmap; Transform: TPixelTransform);
  var
!   p1, p2: PJvRGBTriple;
    X, Y: Integer;
    rt, gt, bt: Byte;
    AColor: TColor;
  begin
!   Target.Width := FBitmap.Width;
!   Target.Height := FBitmap.Height;
!   Target.Transparent:= FBitmap.Transparent;
!   if FBitmap.Transparent then begin
!     AColor := FBitmap.TransparentColor;
!     Target.TransparentColor:= AColor;
!   end
!   else
!     AColor:= clNone;
    rt := GetRValue(AColor);
    gt := GetGValue(AColor);
    bt := GetBValue(AColor);
!   Target.PixelFormat := pf24bit;
!   assert(FBitmap.PixelFormat = pf24Bit);
    for Y := 0 to FBitmap.Height - 1 do
    begin
      p1 := FBitmap.ScanLine[Y];
!     p2 := Target.ScanLine[Y];
!     for X := 1 to FBitmap.Width do begin
!       if (AColor <> clNone) and
!            (p1.rgbBlue = bt) and (p1.rgbGreen = gt) and (p1.rgbRed = rt) then
!         p2^ := p1^
        else
!         Transform(p2, p1);
!       Inc(p1); Inc(p2);
      end;
    end;
+ end;
+ 
+ procedure TJvBitmapButton.MakeCaption(Target: TBitmap; FontColor: TColor);
+ var ARect: TRect;
+ begin
    if FCaption <> '' then
    begin
!     Target.Canvas.Brush.Style := bsClear;
!     Target.Canvas.Font.Assign(FFont);
!     Target.Canvas.Font.Color := FontColor;
      ARect := Rect(0, 0, Width, Height);
!     Target.Canvas.TextRect(ARect, FCaptionLeft, FCaptionTop, FCaption);
    end;
  end;
  
  procedure TJvBitmapButton.MouseLeave(AControl: TControl);
  begin
***************
*** 402,422 ****
      UpdateBitmaps;
    end;
  end;
  
  procedure TJvBitmapButton.MakeNormal;
- var
-   ARect: TRect;
  begin
    FNormal.Assign(FBitmap);
!   if FCaption <> '' then
!   begin
!     FNormal.Canvas.Brush.Style := bsclear;
!     FNormal.Canvas.Font.Assign(FFont);
!     ARect := Rect(0, 0, Width, Height);
!     FNormal.Canvas.TextRect(ARect, FCaptionLeft, FCaptionTop, FCaption);
!   end;
  end;
  
  procedure TJvBitmapButton.SetDarkerFontColor(const Value: TColor);
  begin
    if Value <> FDarkerFontColor then
--- 405,417 ----
      UpdateBitmaps;
    end;
  end;
  
  procedure TJvBitmapButton.MakeNormal;
  begin
    FNormal.Assign(FBitmap);
!   MakeCaption(FNormal, Font.Color);
  end;
  
  procedure TJvBitmapButton.SetDarkerFontColor(const Value: TColor);
  begin
    if Value <> FDarkerFontColor then
JvBitmapButton.pas.2.diff (10,473 bytes)

glchapman

2004-03-19 05:52

reporter   ~0003390

JvBitmapButton.pas.2.diff has a large set of changes which are not really bug fixes. They change the control to allow a non-Transparent Bitmap. Also, if the Bitmap is Transparent, they use the value of Bitmap.TransparentColor (rather than using Pixels[0, Height-1]) as the transparent color. This is the way I would prefer the control to work.

user72

2004-03-19 11:08

  ~0003396

Thanks. BTW, it's better to submit the entire changed unit (in a zip archive) than diffs since not all developers have diff tools that supports diff files

user72

2004-03-20 01:22

  ~0003400

Fixed and updated in CVS

Issue History

Date Modified Username Field Change
2004-03-19 05:32 glchapman New Issue
2004-03-19 05:32 glchapman File Added: JvBitmapButton.pas.1.diff
2004-03-19 05:47 glchapman File Added: JvBitmapButton.pas.2.diff
2004-03-19 05:52 glchapman Note Added: 0003390
2004-03-19 11:08 user72 Note Added: 0003396
2004-03-20 01:22 user72 Status new => resolved
2004-03-20 01:22 user72 Resolution open => fixed
2004-03-20 01:22 user72 Assigned To => user72
2004-03-20 01:22 user72 Note Added: 0003400