{**********************************************}
{   TPenDialog                                 }
{   Copyright (c) 1996-2020 by Steema Software }
{**********************************************}
unit TeePenDlg;
{$I TeeDefs.inc}

interface

uses {$IFNDEF LINUX}
     {$IFNDEF LCL}
     Windows, Messages,
     {$ENDIF}
     {$ENDIF}
     SysUtils, Classes,

     Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls,
     {$IFNDEF LCL}
     FileCtrl,
     {$ENDIF}

     {$IFDEF D16}
     System.UITypes,
     {$ENDIF}

     {$IFDEF LCL}
     Buttons,
     {$ENDIF}

     TeCanvas, TeeProcs, TeeGalleryPanel, TeeEdiGrad;

type
  TPenDialog = class(TForm)
    PanelButtons: TPanel;
    Panel2: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabGradient: TTabSheet;
    Label1: TLabel;
    Label2: TLabel;
    CBEndStyle: TComboFlat;
    CBJoinStyle: TComboFlat;
    CBVisible: TCheckBox;
    BColor: TButtonColor;
    LWidth: TLabel;
    TBSize: TTrackBar;
    LSize: TLabel;
    TabStyle: TTabSheet;
    Panel1: TPanel;
    CBStyle: TComboFlat;
    Styles: TChartGalleryPanel;
    LSpace: TLabel;
    ESpace: TEdit;
    UDSpace: TUpDown;
    Panel3: TPanel;
    BOk: TButton;
    BCancel: TButton;
    LTransp: TLabel;
    TBTransp: TTrackBar;
    CBDefColor: TCheckBox;
    procedure FormShow(Sender: TObject);
    procedure CBVisibleClick(Sender: TObject);
    procedure BCancelClick(Sender: TObject);
    procedure CBStyleChange(Sender: TObject);
    procedure CBStyleDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure BColorClick(Sender: TObject);
    procedure CBEndStyleChange(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ESpaceChange(Sender: TObject);
    procedure CBJoinStyleChange(Sender: TObject);
    procedure TBSizeChange(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure StylesChangeChart(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TBTranspChange(Sender: TObject);
    procedure CBDefColorClick(Sender: TObject);
  private
    { Private declarations }
    BackupPen   : TTeePen;
    FOnChangedPen : TNotifyEvent;
    ModifiedPen : Boolean;

    IGradient : TTeeGradientEditor;
    ISelecting: Boolean;

    procedure ChangedPen;
    procedure EnablePenStyle;
    procedure PrepareDefColor;
    function SelectedSmallDots:Boolean;
    procedure SelectStyleGallery;
    procedure StyleChartDraw(Sender: TObject);
  public
    { Public declarations }
    ThePen : TPen;

    class function InsertForm(const APen:TPen; const AParent:TWinControl):TPenDialog;
    class procedure LoadSize(const AForm:TForm; const APrefix:String);
    class procedure SaveSize(const AForm:TForm; const APrefix:String);

    procedure RefreshPen(const APen:TPen);
    property OnChangedPen:TNotifyEvent read FOnChangedPen write FOnChangedPen;
  end;

Function EditChartPen(const AOwner:TComponent; const APen:TTeePen; HideColor:Boolean=False):Boolean;

{ Show / Hide controls in array }
Procedure ShowControls(Show:Boolean; Const AControls:Array of TControl);

{ Asks the user a question and returns Yes or No }
Function TeeYesNo(Const Message:String; Owner:TControl=nil):Boolean;
{ Same as above, but using predefined "Sure to Delete?" message }
Function TeeYesNoDelete(Const Message:String; Owner:TControl=nil):Boolean;

type
  TButtonPen=class(TTeeButton)
  private
    FEditor     : TPenDialog;
    FOldDestroy : TNotifyEvent;

    procedure EditorDestroy(Sender:TObject);
    function GetPen:TTeePen;
    function GetEditor:TPenDialog;
  protected
    procedure DrawSymbol(const ACanvas:TTeeCanvas); override;
  public
    HideColor : Boolean;
    procedure Click; override;
    procedure LinkPen(const APen:TTeePen);

    property Editor:TPenDialog read GetEditor;
    property Pen:TTeePen read GetPen write LinkPen;
  end;

Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl); overload;
Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl; const ATag:TObject); overload;
Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl; ATag:TeeNativeInt); overload;

Procedure TeeLoadArrowBitmaps(const AUp,ADown:TBitmap);

{ Helper listbox items routines }
procedure MoveList(const Source,Dest:TCustomListBox);
procedure MoveListAll(const Source,Dest:TStrings);

Const
  TeeFormBorderStyle=bsNone;

// Creates a new form, sets form Align to none, centers it to screen
// or owner.center, and changes Form border style to "bsDialog".
Function TeeCreateForm(const FormClass:TFormClass; const AOwner:TComponent):TForm;

// Sets Form parameter position to center of screen or center of Form.Owner,
// if available and for Delphi v5 and up.
procedure PositionToCenter(const Form:TForm);

// Scales AForm PixelsPerInch to match it's Parent Form, if any
procedure TeeScaleForm(const AForm:TForm);

// Shows Save dialog for Pictures and saves AGraphic
procedure TeeSavePictureDialog(const AOwner:TComponent; const AGraphic:TGraphic);

// Shows a dialog to select a directory, returns True if user clicks Ok
Function TeeSelectFolder(const Caption,Root:String; var Folder:String):Boolean;

// Returns Size formatted as nearest magnitude: Bytes, KBytes, MB, GB etc
function FileSizeToStr(Size:Cardinal):String;

implementation

{$IFNDEF LCL}
{$R *.DFM}
{$ELSE}
{$R *.lfm}
{$ENDIF}

Uses ExtDlgs,
     {$IFDEF LCL}
     LCLType, // Pending to move odSelected to StdCtrls unit
     {$ENDIF}
     {$IFNDEF LINUX}
     Registry,
     {$ENDIF}
     Math, TypInfo, TeEngine, TeeConst, TeeBrushDlg, Chart;

procedure PositionToCenter(const Form:TForm);
begin
  if Assigned(Form.Owner) then
     Form.Position:=poOwnerFormCenter
  else
     Form.Position:=poScreenCenter;
end;

Function TeeCreateForm(const FormClass:TFormClass; const AOwner:TComponent):TForm;

  Function TeeGetParentForm(const AOwner:TComponent):TComponent;
  begin
    result:=AOwner;
    if Assigned(result) and (result is TControl) then
    begin
      result:=GetParentForm(TControl(result));
      if not Assigned(result) then result:=AOwner;
    end;
  end;

begin
  result:=FormClass.Create(TeeGetParentForm(AOwner));

  with result do
  begin
    Align:=alNone;
    PositionToCenter(result);
    BorderStyle:=TeeBorderStyle;
  end;
end;

function CreatePenDialog(AOwner:TComponent; APen:TTeePen; HideColor:Boolean=False):TPenDialog;
begin
  result:=TeeCreateForm(TPenDialog,AOwner) as TPenDialog;

  result.ThePen:=APen;

  if HideColor then
     result.BColor.Hide;
end;

Function EditChartPen(const AOwner:TComponent; const APen:TTeePen; HideColor:Boolean=False):Boolean;
Begin
  with CreatePenDialog(AOwner,APen,HideColor) do
  try
    result:=ShowModal=mrOk;
  finally
    Free;
  end;
end;

procedure TPenDialog.FormDestroy(Sender: TObject);
begin
  BackupPen.Free;
end;

procedure TPenDialog.ESpaceChange(Sender: TObject);
begin
  if Showing and (ThePen is TTeePen) then
  begin
    TTeePen(ThePen).SmallSpace:=UDSpace.Position;
    ChangedPen;
  end;
end;

procedure TPenDialog.FormShow(Sender: TObject);
var tmpFirstTime : Boolean;
begin
  tmpFirstTime:=not Assigned(BackupPen);

  if tmpFirstTime then
     BackupPen:=TTeePen.Create(nil);

  if Assigned(ThePen) then
  begin
    BackupPen.Assign(ThePen);
    RefreshPen(ThePen);
  end;

  if tmpFirstTime then
     TeeTranslateControl(Self);

  ModifiedPen:=False;
end;

procedure TPenDialog.ChangedPen;
begin
  ModifiedPen:=True;

  if Assigned(FOnChangedPen) then
     FOnChangedPen(Self);
end;

Procedure TPenDialog.EnablePenStyle;
begin
  if not IsWindowsNT then
     CBStyle.Enabled:=ThePen.Width=1;
end;

procedure TPenDialog.RefreshPen(const APen:TPen);
begin
  ThePen:=APen;

  if Assigned(ThePen) then
  begin
    if ThePen is TTeePen then
    begin
      CBVisible.Checked:=TTeePen(ThePen).Visible;

      if Assigned(BackupPen) then
         BackupPen.Visible:=CBVisible.Checked;

      if IsWindowsNT then
         if CBStyle.Items.IndexOf(TeeMsg_SmallDotsPen)=-1 then
            CBStyle.Items.Add(TeeMsg_SmallDotsPen);

      if TTeePen(ThePen).SmallDots then
      begin
        CBStyle.ItemIndex:=CBStyle.Items.Count-1;

        TBSize.Enabled:=False;
        LSize.Enabled:=False;

        UDSpace.Enabled:=True;
        ESpace.Enabled:=True;
      end
      else
        CBStyle.ItemIndex:=Ord(ThePen.Style);

      if IsWindowsNT then
      begin
        CBEndStyle.ItemIndex:=Ord(TTeePen(ThePen).EndStyle);
        CBJoinStyle.ItemIndex:=Ord(TTeePen(ThePen).JoinStyle);
      end
      else
      begin
        CBEndStyle.Visible:=False;
        CBJoinStyle.Visible:=False;
      end;

      UDSpace.Position:=TTeePen(ThePen).SmallSpace;

      if Assigned(IGradient) then
         IGradient.RefreshGradient(TTeePen(ThePen).Fill.Gradient);
    end
    else
    begin
      CBVisible.Visible:=False;
      CBStyle.ItemIndex:=Ord(ThePen.Style);
      TabGradient.TabVisible:=False;
    end;

    TBSize.Position:=ThePen.Width;
    LSize.Caption:=IntToStr(ThePen.Width);

    if ThePen.Color=clTeeColor then
       TBTransp.Position:=0
    else
       TBTransp.Position:=TTeeCanvas.ColorAlpha(ThePen.Color);

    EnablePenStyle;
    SelectStyleGallery;

    BColor.LinkProperty(ThePen,'Color');

    PrepareDefColor;
  end
  else
    BColor.LinkProperty(nil,'');

  // Last thing to do:
  Panel2.Enabled:=Assigned(ThePen);
end;

procedure TPenDialog.CBEndStyleChange(Sender: TObject);
begin
  TTeePen(ThePen).EndStyle:=TPenEndStyle(CBEndStyle.ItemIndex);
  ChangedPen;
end;

procedure TPenDialog.CBVisibleClick(Sender: TObject);
begin
  if Showing then
  begin
    TTeePen(ThePen).Visible:=CBVisible.Checked;
    ChangedPen;
  end;
end;

procedure TPenDialog.BCancelClick(Sender: TObject);
begin
  if ModifiedPen then
  begin
    ThePen.Assign(BackupPen);

    if ThePen is TTeePen then
    begin
      TTeePen(ThePen).Visible:=BackupPen.Visible;

      if Assigned(ThePen.OnChange) then
         ThePen.OnChange(Self);
    end;
  end;

  ModalResult:=mrCancel;
end;

function TPenDialog.SelectedSmallDots:Boolean;
begin
  result:=(ThePen is TTeePen) and IsWindowsNT and
          (CBStyle.ItemIndex=CBStyle.Items.Count-1)
end;

procedure TPenDialog.CBStyleChange(Sender: TObject);
var tmp : Boolean;
begin
  if SelectedSmallDots then
  begin
    TTeePen(ThePen).SmallDots:=True;
    tmp:=False;
  end
  else
  begin
    tmp:=True;
    ThePen.Style:=TPenStyle(CBStyle.ItemIndex);

    if ThePen is TTeePen then
       TTeePen(ThePen).SmallDots:=False;
  end;

  TBSize.Enabled:=tmp;
  LSize.Enabled:=tmp;

  UDSpace.Enabled:=not tmp;
  ESpace.Enabled:=not tmp;
  LSpace.Enabled:=not tmp;

  SelectStyleGallery;

  ChangedPen;
end;

procedure TPenDialog.SelectStyleGallery;
begin
  if Styles.Charts.Count>0 then
  begin
    ISelecting:=True;
    Styles.SelectChart(Styles.Charts[CBStyle.ItemIndex]);
    ISelecting:=False;
  end;
end;

procedure TPenDialog.BColorClick(Sender: TObject);
begin
  PrepareDefColor;
  CBStyle.Repaint;
  ChangedPen;
end;

procedure TPenDialog.CBJoinStyleChange(Sender: TObject);
begin
  TTeePen(ThePen).JoinStyle:=TPenJoinStyle(CBJoinStyle.ItemIndex);
  ChangedPen;
end;

procedure TPenDialog.CBStyleDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var tmp : TColor;
begin

  if Assigned(ThePen) then
  With TControlCanvas(CBStyle.Canvas) do
  begin
    FillRect(Rect);

    if Index<>CBStyle.Items.Count-1 then
       Pen.Style:=TPenStyle(Index);

    Pen.Color:=ThePen.Color;

    if odSelected in State then tmp:=ColorToRGB(clHighLight)
                           else tmp:=CBStyle.Color;
    if Pen.Color=tmp then
       if Pen.Color=clWhite then Pen.Color:=clBlack
                            else Pen.Color:=clWhite;

    {$IFDEF MSWINDOWS}
    if IsWindowsNT and (Index=CBStyle.Items.Count-1) then
       Pen.Handle:=TeeCreatePenSmallDots(Pen.Color);
    {$ENDIF}

    MoveTo(Rect.Left+2,Rect.Top+8);
    LineTo(Rect.Left+30,Rect.Top+8);
    Brush.Style:=bsClear;

    {$IFDEF LCL}
    if not (odSelected in State) then
       Font.Color:=ColorToRGB(clText);
    {$ELSE}
    UpdateTextFlags;
    {$ENDIF}

    TextOut(Rect.Left+34,Rect.Top+2,CBStyle.Items[Index]);
  end;
end;

{ TButtonPen }
function TButtonPen.GetEditor:TPenDialog;
begin
  if not Assigned(FEditor) then
  begin
    FEditor:=CreatePenDialog(Self,TTeePen(Instance),HideColor);
    FOldDestroy:=FEditor.OnDestroy;
    FEditor.OnDestroy:=EditorDestroy;
  end;

  result:=FEditor;
end;

procedure TButtonPen.EditorDestroy(Sender:TObject);
begin
  if Assigned(FOldDestroy) then
     FOldDestroy(FEditor);

  FEditor:=nil;
end;

procedure TButtonPen.Click;
var tmp : Boolean;
begin
  if Assigned(Instance) then
  begin
    tmp:=Editor.ShowModal=mrOk;
    try
      if tmp then
      begin
        Repaint;
        inherited;
      end;
    finally
      FreeAndNil(FEditor);
    end;
  end
  else inherited;
end;

procedure TButtonPen.DrawSymbol(const ACanvas: TTeeCanvas);
var OldChange : TNotifyEvent;
    OldWidth  : Integer;
    R         : TRect;
begin
  if Enabled and Assigned(Instance) then
  begin
    // allow maximum 6 pixels for symbol height...
    with TTeePen(Instance) do
    if Width>6 then
    begin
      OldChange:=OnChange;
      OnChange:=nil;
      OldWidth:=Width;
      Width:=6;
    end
    else
    begin
      OldChange:=nil;
      OldWidth:=0;
    end;

    // draw line
    With ACanvas do
    begin
      Brush.Style:=bsClear;
      AssignVisiblePen(TTeePen(Instance));

      R:=SymbolRectangle;
      MoveTo(R.Left,Height div 2);
      LineTo(R.Right,Height div 2);
    end;

    // reset back old pen width
    if Assigned(OldChange) then
    with TTeePen(Instance) do
    begin
      Width:=OldWidth;
      OnChange:=OldChange;
    end;
  end;
end;

procedure TButtonPen.LinkPen(const APen: TTeePen);
begin
  LinkProperty(APen,'');
  Invalidate;
end;

function TButtonPen.GetPen:TTeePen;
begin
  result:=TTeePen(Instance);
end;

{ Utility functions }
Procedure ShowControls(Show:Boolean; Const AControls:Array of TControl);
var t : Integer;
begin
  for t:=Low(AControls) to High(AControls) do AControls[t].Visible:=Show;
end;

Function TeeYesNo(Const Message:String; Owner:TControl=nil):Boolean;
var x : Integer;
    y : Integer;
Begin
  Screen.Cursor:=crDefault;
  if Assigned(Owner) then
  begin
    x:=Owner.ClientOrigin.X+20;
    y:=Owner.ClientOrigin.Y+30;
    result:=MessageDlgPos(Message,mtConfirmation,[mbYes,mbNo],0,x,y)=mrYes;
  end
  else result:=MessageDlg(Message,mtConfirmation,[mbYes,mbNo],0)=mrYes;
End;

Function TeeYesNoDelete(Const Message:String; Owner:TControl=nil):Boolean;
begin
  result:=TeeYesNo(Format(TeeMsg_SureToDelete,[Message]),Owner);
end;

Function TeeSelectFolder(const Caption,Root:String; var Folder:String):Boolean;
var tmpDir : String;
begin
  tmpDir:=Folder;

  result:=SelectDirectory(Caption,Root,tmpDir); // Available also in FMX D20 (FMX.Dialogs.pas)

  if result then
     Folder:=tmpDir;
end;

Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl);
begin
  AddFormTo(AForm,AParent,AForm.Tag);
end;

Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl; ATag:TeeNativeInt);
begin
  AddFormTo(AForm,AParent,TObject(ATag));
end;

type
  TCustomFormAccess=class(TCustomForm);
  TWinControlAccess=class(TWinControl);
  
Procedure AddFormTo(const AForm:TForm; const AParent:TWinControl; const ATag:TObject);
var OldVisibleFlag : Boolean;
begin
  with TCustomFormAccess(AForm) do
  begin
    {$IFNDEF LCL}
    {$IFDEF D7}
    ParentBackground:=True;

    // This is to avoid "cannot focus" exceptions due to VCL trying to obtain
    // the Monitor.Handle for the "dmActiveForm" default setting:
    DefaultMonitor:=dmDesktop;
    {$ENDIF}
    {$ENDIF}

    ParentColor:=True;
  end;

  With AForm do
  begin
    Position:=poDesigned;
    BorderStyle:=TeeFormBorderStyle;
    BorderIcons:=[];
    Tag:=ObjectToTag(ATag);

    Parent:=AParent;

    OldVisibleFlag:=Parent.Visible;
    Parent.Visible:=True;

    if Align=alNone then
    begin
      Left:=4; { ((AParent.ClientWidth-ClientWidth) div 2); }
      Top:=Math.Min(4,Abs(AParent.ClientHeight-ClientHeight) div 2);
    end;

    // dont here: TeeTranslateControl(AForm);

    TeeScaleForm(AForm);

    if ParentFont then
       Font:=TWinControlAccess(Parent).Font;

    Show;

    Parent.Visible:=OldVisibleFlag;
  end;
end;

{ Utils }
Procedure TeeLoadArrowBitmaps(const AUp,ADown: TBitmap);
begin
  TeeLoadBitmap(AUp,'TeeArrowUp');
  TeeLoadBitmap(ADown,'TeeArrowDown');
end;

{ Helper Listbox methods... }
procedure MoveList(const Source,Dest:TCustomListBox);
var t:Integer;
begin
  with Source do
  begin
    for t:=0 to Items.Count-1 do
        if Selected[t] then Dest.Items.AddObject(Items[t],Items.Objects[t]);
    t:=0;
    While t<Items.Count do
    begin
      if Selected[t] then Items.Delete(t)
                     else Inc(t);
    end;
  end;
end;

procedure MoveListAll(const Source,Dest:TStrings);
var t : Integer;
begin
  With Source do
  for t:=0 to Count-1 do Dest.AddObject(Strings[t],Objects[t]);
  Source.Clear;
end;

// Scales AForm PixelsPerInch to match it's Parent Form, if any
procedure TeeScaleForm(const AForm:TForm);

  function GetFirstParentForm(Control:TControl):TCustomForm;
  begin
    result:=nil;

    while Assigned(Control.Parent) do
    begin
      Control:=Control.Parent;

      if Control is TCustomForm then
      begin
        result:=TCustomForm(Control);
        break;
      end;
    end;
  end;

var tmpForm : TCustomForm;
begin
  tmpForm:=GetFirstParentForm(AForm);

  if Assigned(tmpForm) and (tmpForm is TForm) and
     (TForm(tmpForm).PixelsPerInch<>AForm.PixelsPerInch) then
  begin
    {$IFNDEF LCL} // No ScaleBy method in LCL

    AForm.ScaleBy(TForm(tmpForm).PixelsPerInch,AForm.PixelsPerInch);

    {$ENDIF}

    AForm.PixelsPerInch:=TForm(tmpForm).PixelsPerInch;
  end;
end;

// Shows Save dialog for Pictures and saves AGraphic
procedure TeeSavePictureDialog(const AOwner:TComponent; const AGraphic:TGraphic);
begin
  with TSavePictureDialog.Create(AOwner) do
  try
    Filter:=GraphicFilter(TGraphicClass(AGraphic.ClassType));

    Options:=Options+[ofOverwritePrompt];
    
    if Execute then
       AGraphic.SaveToFile(FileName);
  finally
    Free;
  end;
end;

procedure TPenDialog.TBSizeChange(Sender: TObject);
begin
  if Assigned(ThePen) then
  begin
    ThePen.Width:=TBSize.Position;
    LSize.Caption:=IntToStr(ThePen.Width);

    EnablePenStyle;
    ChangedPen;
  end;
end;

procedure TPenDialog.StyleChartDraw(Sender: TObject);
var w,y : Integer;
begin
  with Sender as TGalleryChart do
  begin
    Canvas.AssignVisiblePen(Walls.Back.Pen);
    y:=(ChartRect.Top+ChartRect.Bottom) div 2;
    w:=ChartWidth div 2;
    Canvas.DoHorizLine(w div 2,w+(w div 2),y);
  end;
end;

procedure TPenDialog.PageControl1Change(Sender: TObject);
var t : Integer;
    tmp : TGalleryChart;
begin
  if PageControl1.ActivePage=TabStyle then
  begin
    if Styles.Charts.Count=0 then
    begin
      Styles.NumCols:=3;
      //Styles.NumRows:=2;
      Styles.AspectRatio:=0.5;

      for t:=0 to CBStyle.Items.Count-1 do
      begin
        tmp:=TGalleryChart.Create(Styles);
        Styles.Charts.Add(tmp);
        tmp.Parent:=Styles;

        tmp.Hint:=CBStyle.Items[t];
        tmp.ShowHint:=True;

        Styles.FinishAdd(tmp);
        tmp.OnEnter:=nil;

        tmp.AutoRepaint:=False;
        tmp.Title.Caption:=tmp.Hint;

        tmp.View3D:=False;
        tmp.Axes.Hide;
        tmp.Walls.Hide;

        tmp.Walls.Back.Pen.Visible:=True;

        if t=CBStyle.Items.Count-1 then
           tmp.Walls.Back.Pen.SmallDots:=True
        else
        begin
          tmp.Walls.Back.Pen.Width:=3;
          tmp.Walls.Back.Pen.Style:=TPenStyle(t);
        end;

        tmp.AutoRepaint:=True;
        
        tmp.OnAfterDraw:=StyleChartDraw;
      end;

      Styles.ResizeCharts;

      Styles.SelectedChart:=Styles.Charts[CBStyle.ItemIndex];
    end;
  end
  else
  if PageControl1.ActivePage=TabGradient then
  begin
    if not Assigned(IGradient) then
       IGradient:=TTeeGradientEditor.InsertForm(TTeePen(ThePen).Fill.Gradient,TabGradient);
  end;
end;

procedure TPenDialog.StylesChangeChart(Sender: TObject);
begin
  if not ISelecting then
  begin
    CBStyle.ItemIndex:=Styles.Charts.IndexOf(Styles.SelectedChart);
    CBStyleChange(Self);
  end;
end;

procedure TPenDialog.FormCreate(Sender: TObject);
begin
  {$IFDEF D7}
  PageControl1.DoubleBuffered:=True;
  {$ENDIF}

  PageControl1.ActivePageIndex:=0;
end;

procedure TPenDialog.TBTranspChange(Sender: TObject);
begin
  if Assigned(ThePen) then
     ThePen.Color:=TTeeCanvas.ColorFrom(ThePen.Color,TBTransp.Position);
end;

class function TPenDialog.InsertForm(const APen:TPen; const AParent:TWinControl):TPenDialog;
begin
  result:=TPenDialog.Create(AParent.Owner);
  result.PanelButtons.Hide;
  result.Align:=alClient;
  result.RefreshPen(APen);
  AddFormTo(result,AParent);
end;

procedure TPenDialog.PrepareDefColor;
begin
  CBDefColor.Checked:=ThePen.Color=clTeeColor;
  CBDefColor.Enabled:=not CBDefColor.Checked;
end;

procedure TPenDialog.CBDefColorClick(Sender: TObject);
begin
  if CBDefColor.Checked then
  begin
    ThePen.Color:=clTeeColor;
    BColor.Invalidate;
    CBDefColor.Enabled:=False;
  end;
end;

class procedure TPenDialog.LoadSize(const AForm:TForm; const APrefix:String);
{$IFNDEF LINUX}
var tmpWidth,
    tmpHeight : Integer;
{$ENDIF}
begin
  {$IFNDEF LINUX}
  with TRegistry.Create(KEY_READ) do
  try
    if OpenKeyReadOnly(TeeMsg_EditorKey) then
    begin
      if ValueExists(APrefix+'Width') then
         tmpWidth:=Math.Max(100,ReadInteger(APrefix+'Width'))
      else
         tmpWidth:=AForm.Width;

      if ValueExists(APrefix+'Height') then
         tmpHeight:=Math.Max(100,ReadInteger(APrefix+'Height'))
      else
         tmpHeight:=AForm.Height;

      // Call SetBounds to pass width and height at the same time,
      // to avoid resizing events:

      AForm.SetBounds(AForm.Left,AForm.Top,tmpWidth,tmpHeight);
    end;
  finally
    Free;
  end;
  {$ENDIF}
end;

class procedure TPenDialog.SaveSize(const AForm:TForm; const APrefix:String);
begin
  {$IFNDEF LINUX}
  with TRegistry.Create do
  try
    if OpenKey(TeeMsg_EditorKey,True) then
    begin
      WriteInteger(APrefix+'Width',AForm.Width);
      WriteInteger(APrefix+'Height',AForm.Height);
    end;
  finally
    Free;
  end;
  {$ENDIF}
end;

function FileSizeToStr(Size:Cardinal):String;
const
  Mega=1024*1024;
  Giga=Mega*1024;
  Tera=1.0*Giga*1024;

begin
  if Size<Mega then
     result:=Format(TeeMsg_FileSize,[Size])
  else
  if Size<Giga then
     result:=Format('%d KB',[Size div 1024])
  else
  if Size<Tera then
     result:=Format('%d MB',[Size div Mega])
  else
     result:=IntToStr(Size);
end;

end.
