1 {
2  /***************************************************************************
3                                extdlgs.pas
4                                -----------
5                 Component Library Extended dialogs Controls
6 
7 
8  ***************************************************************************/
9 
10  *****************************************************************************
11   This file is part of the Lazarus Component Library (LCL)
12 
13   See the file COPYING.modifiedLGPL.txt, included in this distribution,
14   for details about the license.
15  *****************************************************************************
16 }
17 unit ExtDlgs;
18 
19 {$mode objfpc}{$H+}
20 
21 interface
22 
23 uses
24   Types, Classes, SysUtils, LCLProc, LResources, LCLType, LCLStrConsts,
25   FileUtil, LazFileUtils, Controls, Dialogs, GraphType, Graphics, ExtCtrls,
26   StdCtrls, Forms, Calendar, Buttons, Masks, CalcForm;
27 
28 type
29 
30   { TPreviewFileControl }
31 
32   TPreviewFileDialog = class;
33 
34   TPreviewFileControl = class(TWinControl)
35   private
36     FPreviewFileDialog: TPreviewFileDialog;
37   protected
38     class procedure WSRegisterClass; override;
GetControlClassDefaultSizenull39     class function GetControlClassDefaultSize: TSize; override;
40     procedure SetPreviewFileDialog(const AValue: TPreviewFileDialog);
41     procedure CreateParams(var Params: TCreateParams); override;
42   public
43     constructor Create(TheOwner: TComponent); override;
44     property PreviewFileDialog: TPreviewFileDialog read FPreviewFileDialog
45                                                    write SetPreviewFileDialog;
46   end;
47 
48   { TPreviewFileDialog }
49 
50   TPreviewFileDialog = class(TOpenDialog)
51   private
52     FPreviewFileControl: TPreviewFileControl;
GetPreviewFileControlnull53     function GetPreviewFileControl:TPreviewFileControl;
54   protected
55     class procedure WSRegisterClass; override;
56     procedure CreatePreviewControl; virtual;
57     procedure InitPreviewControl; virtual;
DoExecutenull58     function DoExecute: boolean; override;
59   public
60     constructor Create(TheOwner: TComponent); override;
61     property PreviewFileControl: TPreviewFileControl read GetPreviewFileControl;
62   end;
63 
64   { TOpenPictureDialog }
65 
66   TOpenPictureDialog = class(TPreviewFileDialog)
67   private
68     FDefaultFilter: string;
69     FImageCtrl: TImage;
70     FPictureGroupBox: TGroupBox;
71     FPreviewFilename: string;
72   protected
73     class procedure WSRegisterClass; override;
IsFilterStorednull74     function  IsFilterStored: Boolean; virtual;
75     property ImageCtrl: TImage read FImageCtrl;
76     property PictureGroupBox: TGroupBox read FPictureGroupBox;
77     procedure InitPreviewControl; override;
78     procedure ClearPreview; virtual;
79     procedure UpdatePreview; virtual;
80   public
81     constructor Create(TheOwner: TComponent); override;
82     procedure DoClose; override;
83     procedure DoSelectionChange; override;
84     procedure DoShow; override;
GetFilterExtnull85     function GetFilterExt: String;
86     property DefaultFilter: string read FDefaultFilter;
87   published
88     property Filter stored IsFilterStored;
89   end;
90 
91   { TSavePictureDialog }
92 
93   TSavePictureDialog = class(TOpenPictureDialog)
94   protected
95     class procedure WSRegisterClass; override;
DefaultTitlenull96     function DefaultTitle: string; override;
97   public
98     constructor Create(TheOwner: TComponent); override;
99   end;
100 
101   { TExtCommonDialog }
102 
103   // A common base class for custom drawn dialogs (Calculator and Calendar).
104   TExtCommonDialog = class(TCommonDialog)
105   private
106     FDialogPosition: TPosition;
107     FLeft: Integer;
108     FTop: Integer;
109     FDlgForm: TCustomForm;
110   protected
GetLeftnull111     function GetLeft: Integer; virtual;
GetHeightnull112     function GetHeight: Integer; override;
GetTopnull113     function GetTop: Integer; virtual;
GetWidthnull114     function GetWidth: Integer; override;
115     procedure SetLeft(AValue: Integer); virtual;
116     procedure SetTop(AValue: Integer); virtual;
117     property DlgForm: TCustomForm read FDlgForm write FDlgForm;
118   public
119     constructor Create(AOwner: TComponent); override;
120     destructor Destroy; override;
121     property Left: Integer read GetLeft write SetLeft;
122     property Top: Integer read GetTop write SetTop;
123   published
124     property DialogPosition: TPosition read FDialogPosition write FDialogPosition default poMainFormCenter;
125   end;
126 
127   { TCalculatorDialog }
128 
129   TCalculatorDialog = class(TExtCommonDialog)
130   private
131     FLayout: TCalculatorLayout;
132     FValue: Double;
133     FMemory: Double;
134     FPrecision: Byte;
135     FBeepOnError: Boolean;
136     FOnChange: TNotifyEvent;
137     FOnCalcKey: TKeyPressEvent;
138     FOnDisplayChange: TNotifyEvent;
139     FDialogScale: integer;
140     FColorBtnDigits,
141     FColorBtnOthers,
142     FColorBtnMemory,
143     FColorBtnOk,
144     FColorBtnCancel,
145     FColorBtnClear,
146     FColorDisplayText,
147     FColorDisplayBack: TColor;
GetDisplaynull148     function GetDisplay: Double;
149     procedure SetDialogScale(AValue: integer);
150   protected
151     class procedure WSRegisterClass; override;
152     procedure OnDialogClose(Sender: TObject; var CloseAction: TCloseAction);
153     procedure OnDialogShow(Sender: TObject);
154     procedure OnDialogCloseQuery(Sender : TObject; var CanClose : boolean);
155     procedure Change; virtual;
156     procedure CalcKey(var Key: char); virtual;
DefaultTitlenull157     function DefaultTitle: string; override;
158     procedure DisplayChange; virtual;
159   public
160     constructor Create(AOwner: TComponent); override;
161     destructor Destroy; override;
Executenull162     function Execute: Boolean; override;
163     property CalcDisplay: Double read GetDisplay;
164     property Memory: Double read FMemory;
165   published
166     property BeepOnError: Boolean read FBeepOnError write FBeepOnError default True;
167     property CalculatorLayout: TCalculatorLayout read FLayout write FLayout default clNormal;
168     property Precision: Byte read FPrecision write FPrecision default CalcDefPrecision;
169     property Title;
170     property Value: Double read FValue write FValue;
171     property OnCalcKey: TKeyPressEvent read FOnCalcKey write FOnCalcKey;
172     property OnChange: TNotifyEvent read FOnChange write FOnChange;
173     property OnDisplayChange: TNotifyEvent read FOnDisplayChange write FOnDisplayChange;
174     property DialogScale: integer read FDialogScale write SetDialogScale default 100;
175     property ColorBtnDigits: TColor read FColorBtnDigits write FColorBtnDigits;
176     property ColorBtnMemory: TColor read FColorBtnMemory write FColorBtnMemory;
177     property ColorBtnOk: TColor read FColorBtnOk write FColorBtnOk;
178     property ColorBtnCancel: TColor read FColorBtnCancel write FColorBtnCancel;
179     property ColorBtnClear: TColor read FColorBtnClear write FColorBtnClear;
180     property ColorBtnOthers: TColor read FColorBtnOthers write FColorBtnOthers;
181     property ColorDisplayText: TColor read FColorDisplayText write FColorDisplayText;
182     property ColorDisplayBack: TColor read FColorDisplayBack write FColorDisplayBack;
183   end;
184 
185   { TCalendarDialog }
186 
187   TCalendarDialog = class(TExtCommonDialog)
188   private
189     FDate: TDateTime;
190     FDayChanged: TNotifyEvent;
191     FDisplaySettings: TDisplaySettings;
192     FMonthChanged: TNotifyEvent;
193     FYearChanged: TNotifyEvent;
194     FOnChange: TNotifyEvent;
195     FOKCaption: TCaption;
196     FCancelCaption: TCaption;
197     FCalendar: TCalendar;
198     procedure OnDialogClose(Sender: TObject; var CloseAction: TCloseAction);
199     procedure OnDialogCloseQuery(Sender : TObject; var CanClose : boolean);
200     procedure OnDialogShow(Sender: TObject);
201     procedure OnCalendarDayChanged(Sender: TObject);
202     procedure OnCalendarMonthChanged(Sender: TObject);
203     procedure OnCalendarYearChanged(Sender: TObject);
204     procedure OnCalendarChange(Sender: TObject);
205   protected
206     class procedure WSRegisterClass; override;
207     procedure GetNewDate(Sender:TObject);//or onClick
208     procedure CalendarDblClick(Sender: TObject);
DefaultTitlenull209     function DefaultTitle: string; override;
210   public
211     constructor Create(AOwner: TComponent); override;
Executenull212     function Execute: Boolean; override;
213     property Left: Integer read GetLeft write SetLeft;
214     property Top: Integer read GetTop write SetTop;
215   published
216     property Date: TDateTime read FDate write FDate;
217     property DisplaySettings: TDisplaySettings read FDisplaySettings write FDisplaySettings default DefaultDisplaySettings;
218     property OnDayChanged: TNotifyEvent read FDayChanged write FDayChanged;
219     property OnMonthChanged: TNotifyEvent read FMonthChanged write FMonthChanged;
220     property OnYearChanged: TNotifyEvent read FYearChanged write FYearChanged;
221     property OnChange: TNotifyEvent read FOnChange write FOnChange;
222     property OKCaption: TCaption read FOKCaption write FOKCaption;
223     property CancelCaption: TCaption read FCancelCaption write FCancelCaption;
224   end;
225 
226 procedure Register;
227 
228 implementation
229 
230 //no need as buttons don't have glyphs now
231 //{$R lcl_calc_images.res}
232 
233 uses
234   WSExtDlgs, Math;
235 
236 procedure Register;
237 begin
238   RegisterComponents('Dialogs',[TOpenPictureDialog,TSavePictureDialog,
239                                 TCalendarDialog,TCalculatorDialog]);
240 end;
241 
242 { TPreviewFileControl }
243 
244 class procedure TPreviewFileControl.WSRegisterClass;
245 begin
246   inherited WSRegisterClass;
247   RegisterPreviewFileControl;
248 end;
249 
250 procedure TPreviewFileControl.SetPreviewFileDialog(
251   const AValue: TPreviewFileDialog);
252 begin
253   if FPreviewFileDialog=AValue then exit;
254   FPreviewFileDialog:=AValue;
255 end;
256 
257 procedure TPreviewFileControl.CreateParams(var Params: TCreateParams);
258 begin
259   inherited CreateParams(Params);
260   if Params.WndParent = 0 then
261     Params.Style := Params.Style and not WS_CHILD;
262 end;
263 
264 class function TPreviewFileControl.GetControlClassDefaultSize: TSize;
265 begin
266   Result.CX := 200;
267   Result.CY := 200;
268 end;
269 
270 constructor TPreviewFileControl.Create(TheOwner: TComponent);
271 begin
272   inherited Create(TheOwner);
273   FCompStyle:=csPreviewFileControl;
274   SetInitialBounds(0, 0, GetControlClassDefaultSize.CX, GetControlClassDefaultSize.CY);
275 end;
276 
277 { TPreviewFileDialog }
278 
GetPreviewFileControlnull279 function TPreviewFileDialog.GetPreviewFileControl: TPreviewFileControl;
280 begin
281   if not Assigned(fPreviewFileControl) then
282     Self.CreatePreviewControl;
283   Result:=fPreviewFileControl;
284 end;
285 
286 class procedure TPreviewFileDialog.WSRegisterClass;
287 begin
288   inherited WSRegisterClass;
289   RegisterPreviewFileDialog;
290 end;
291 
292 procedure TPreviewFileDialog.CreatePreviewControl;
293 begin
294   if FPreviewFileControl<>nil then exit;
295   FPreviewFileControl:=TPreviewFileControl.Create(Self);
296   FPreviewFileControl.PreviewFileDialog:=Self;
297   InitPreviewControl;
298 end;
299 
300 procedure TPreviewFileDialog.InitPreviewControl;
301 begin
302   FPreviewFileControl.Name:='PreviewFileControl';
303 end;
304 
DoExecutenull305 function TPreviewFileDialog.DoExecute: boolean;
306 begin
307   CreatePreviewControl;
308   Result:=inherited DoExecute;
309 end;
310 
311 constructor TPreviewFileDialog.Create(TheOwner: TComponent);
312 begin
313   inherited Create(TheOwner);
314   FCompStyle:=csPreviewFileDialog;
315 end;
316 
317 { TOpenPictureDialog }
318 
319 class procedure TOpenPictureDialog.WSRegisterClass;
320 begin
321   inherited WSRegisterClass;
322   RegisterOpenPictureDialog;
323 end;
324 
IsFilterStorednull325 function TOpenPictureDialog.IsFilterStored: Boolean;
326 begin
327   Result := (Filter<>FDefaultFilter);
328 end;
329 
330 procedure TOpenPictureDialog.DoClose;
331 begin
332   ClearPreview;
333   inherited DoClose;
334 end;
335 
336 procedure TOpenPictureDialog.DoSelectionChange;
337 begin
338   UpdatePreview;
339   inherited DoSelectionChange;
340 end;
341 
342 procedure TOpenPictureDialog.DoShow;
343 begin
344   ClearPreview;
345   inherited DoShow;
346 end;
347 
348 procedure TOpenPictureDialog.InitPreviewControl;
349 begin
350   inherited InitPreviewControl;
351   FPictureGroupBox.Parent:=PreviewFileControl;
352 end;
353 
354 procedure TOpenPictureDialog.ClearPreview;
355 begin
356   FPictureGroupBox.Caption:='None';
357   FImageCtrl.Picture:=nil;
358 end;
359 
360 procedure TOpenPictureDialog.UpdatePreview;
361 var
362   CurFilename: String;
363   FileIsValid: boolean;
364 begin
365   CurFilename := FileName;
366   if CurFilename = FPreviewFilename then exit;
367 
368   FPreviewFilename := CurFilename;
369   FileIsValid := FileExistsUTF8(FPreviewFilename)
370                  and (not DirPathExists(FPreviewFilename))
371                  and FileIsReadable(FPreviewFilename);
372   if FileIsValid then
373     try
374       FImageCtrl.Picture.LoadFromFile(FPreviewFilename);
375       FPictureGroupBox.Caption := Format('(%dx%d)',
376         [FImageCtrl.Picture.Width, FImageCtrl.Picture.Height]);
377     except
378       FileIsValid := False;
379     end;
380   if not FileIsValid then
381     ClearPreview;
382 end;
383 
384 constructor TOpenPictureDialog.Create(TheOwner: TComponent);
385 begin
386   inherited Create(TheOwner);
387   FDefaultFilter := GraphicFilter(TGraphic)+'|'+
388                        Format(rsAllFiles,[GetAllFilesMask, GetAllFilesMask,'']);
389   Filter:=FDefaultFilter;
390 
391   FPictureGroupBox:=TGroupBox.Create(Self);
392   with FPictureGroupBox do begin
393     Name:='FPictureGroupBox';
394     Align:=alClient;
395   end;
396 
397   FImageCtrl:=TImage.Create(Self);
398   with FImageCtrl do begin
399     Name:='FImageCtrl';
400     Parent:=FPictureGroupBox;
401     Align:=alClient;
402     Center:=true;
403     Proportional:=true;
404   end;
405 end;
406 
GetFilterExtnull407 function TOpenPictureDialog.GetFilterExt: String;
408 var
409   ParsedFilter: TParseStringList;
410 begin
411   Result := '';
412 
413   ParsedFilter := TParseStringList.Create(Filter, '|');
414   try
415     if (FilterIndex > 0) and (FilterIndex * 2 <= ParsedFilter.Count) then
416     begin
417       Result := AnsiLowerCase(ParsedFilter[FilterIndex * 2 - 1]);
418       // remove *.*
419       if (Result <> '') and (Result[1] = '*') then Delete(Result, 1, 1);
420       if (Result <> '') and (Result[1] = '.') then Delete(Result, 1, 1);
421       if (Result <> '') and (Result[1] = '*') then Delete(Result, 1, 1);
422       // remove all after ;
423       if Pos(';', Result) > 0 then Delete(Result, Pos(';', Result), MaxInt);
424     end;
425 
426     if Result = '' then Result := DefaultExt;
427   finally
428     ParsedFilter.Free;
429   end;
430 end;
431 
432 { TSavePictureDialog }
433 
434 class procedure TSavePictureDialog.WSRegisterClass;
435 begin
436   inherited WSRegisterClass;
437   RegisterSavePictureDialog;
438 end;
439 
DefaultTitlenull440 function TSavePictureDialog.DefaultTitle: string;
441 begin
442   Result := rsfdFileSaveAs;
443 end;
444 
445 constructor TSavePictureDialog.Create(TheOwner: TComponent);
446 begin
447   inherited Create(TheOwner);
448   fCompStyle:=csSaveFileDialog;
449 end;
450 
451 { ---------------------------------------------------------------------
452   Auxiliary
453   ---------------------------------------------------------------------}
454 
455 procedure SetDefaultFont(AFont: TFont; Layout: TCalculatorLayout);
456 
457 begin
458   with AFont do
459   begin
460     Color := clWindowText;
461     Name := 'MS Sans Serif';
462     Size := 8;
463     Style := [fsBold];
464   end;
465 end;
466 
467 
468 { TExtCommonDialog }
469 
GetLeftnull470 function TExtCommonDialog.GetLeft: Integer;
471 begin
472   if Assigned(FDlgForm) then FLeft := FDlgForm.Left;
473   Result := FLeft;
474 end;
475 
GetHeightnull476 function TExtCommonDialog.GetHeight: Integer;
477 begin
478   if Assigned(DlgForm) then
479     Result := DlgForm.Height
480   else
481     Result := inherited GetHeight;
482 end;
483 
GetTopnull484 function TExtCommonDialog.GetTop: Integer;
485 begin
486   if Assigned(FDlgForm) then FTop := FDlgForm.Top;
487   Result := FTop;
488 end;
489 
GetWidthnull490 function TExtCommonDialog.GetWidth: Integer;
491 begin
492   if Assigned(DlgForm) then
493     Result := DlgForm.Width
494   else
495     Result := inherited GetWidth;
496 end;
497 
498 procedure TExtCommonDialog.SetLeft(AValue: Integer);
499 begin
500   if Assigned(FDlgForm) then FDlgForm.Left := AValue;
501   FLeft := AValue;
502 end;
503 
504 procedure TExtCommonDialog.SetTop(AValue: Integer);
505 begin
506   if Assigned(FDlgForm) then FDlgForm.Top := AValue;
507   FTop := AValue;
508 end;
509 
510 constructor TExtCommonDialog.Create(AOwner: TComponent);
511 begin
512   inherited Create(AOwner);
513   FDialogPosition := poMainFormCenter;     // Set the initial location on screen.
514 end;
515 
516 destructor TExtCommonDialog.Destroy;
517 begin
518   inherited Destroy;
519 end;
520 
521 
522 { TCalculatorDialog }
523 
524 constructor TCalculatorDialog.Create(AOwner: TComponent);
525 begin
526   inherited Create(AOwner);
527   FPrecision:=CalcDefPrecision;
528   FBeepOnError:=True;
529   FDialogScale:=100;
530   FLayout:=clNormal;
531 
532   FColorBtnDigits:=cColorBtnDigits;
533   FColorBtnOthers:=cColorBtnOthers;
534   FColorBtnMemory:=cColorBtnMemory;
535   FColorBtnOk:=cColorBtnOk;
536   FColorBtnCancel:=cColorBtnCancel;
537   FColorBtnClear:=cColorBtnClear;
538   FColorDisplayText:=cColorDisplayText;
539   FColorDisplayBack:=cColorDisplayBack;
540 end;
541 
542 destructor TCalculatorDialog.Destroy;
543 begin
544   FOnChange:=nil;
545   FOnDisplayChange:=nil;
546   inherited Destroy;
547 end;
548 
549 class procedure TCalculatorDialog.WSRegisterClass;
550 begin
551   inherited WSRegisterClass;
552   RegisterCalculatorDialog;
553 end;
554 
555 procedure TCalculatorDialog.OnDialogClose(Sender: TObject;
556   var CloseAction: TCloseAction);
557 begin
558   DoClose;
559 end;
560 
561 procedure TCalculatorDialog.OnDialogShow(Sender: TObject);
562 begin
563   DoShow;
564 end;
565 
566 procedure TCalculatorDialog.OnDialogCloseQuery(Sender: TObject;
567   var CanClose: boolean);
568 begin
569   UserChoice := DlgForm.ModalResult;
570   DoCanClose(CanClose);
571 end;
572 
GetDisplaynull573 function TCalculatorDialog.GetDisplay: Double;
574 begin
575   if Assigned(DlgForm) then
576     Result:=TCalculatorForm(DlgForm).CalcPanel.DisplayValue
577   else Result:=FValue;
578 end;
579 
580 procedure TCalculatorDialog.SetDialogScale(AValue: integer);
581 const
582   cMinSize = 80;
583   cMaxSize = 400;
584 begin
585   if FDialogScale=AValue then Exit;
586   FDialogScale:=Max(cMinSize, Min(cMaxSize, AValue));
587 end;
588 
589 procedure TCalculatorDialog.CalcKey(var Key: char);
590 begin
591   if Assigned(FOnCalcKey) then FOnCalcKey(Self, Key);
592 end;
593 
DefaultTitlenull594 function TCalculatorDialog.DefaultTitle: string;
595 begin
596   Result := rsCalculator;
597 end;
598 
599 procedure TCalculatorDialog.DisplayChange;
600 begin
601   if Assigned(FOnDisplayChange) then FOnDisplayChange(Self);
602 end;
603 
604 
605 procedure TCalculatorDialog.Change;
606 begin
607   if Assigned(FOnChange) then FOnChange(Self);
608 end;
609 
Executenull610 function TCalculatorDialog.Execute: Boolean;
611 var
612   CPanel: TCalculatorPanel;
613 begin
614   cColorBtnDigits:=FColorBtnDigits;
615   cColorBtnOthers:=FColorBtnOthers;
616   cColorBtnMemory:=FColorBtnMemory;
617   cColorBtnOk:=FColorBtnOk;
618   cColorBtnCancel:=FColorBtnCancel;
619   cColorBtnClear:=FColorBtnClear;
620   cColorDisplayText:=FColorDisplayText;
621   cColorDisplayBack:=FColorDisplayBack;
622 
623   DlgForm:=CreateCalculatorForm(Application, FLayout, HelpContext);
624   try
625     ResetShowCloseFlags;
626     (DlgForm as TCalculatorForm).OnCalcKey:= @Self.CalcKey;
627     (DlgForm as TCalculatorForm).OnDisplayChange:= @Self.DisplayChange;
628     (DlgForm as TCalculatorForm).OnShow := @Self.OnDialogShow;
629     (DlgForm as TCalculatorForm).OnClose := @Self.OnDialogClose;
630     (DlgForm as TCalculatorForm).OnCloseQuery :=@Self.OnDialogCloseQuery;
631 
632     if FDialogScale<>100 then
633       DlgForm.ScaleBy(FDialogScale,100);
634     if (csDesigning in ComponentState) then
635       DlgForm.Position:=poScreenCenter
636     else
637       DlgForm.Position:=DialogPosition;
638     if (DlgForm.Position=poDesigned) then begin
639       DlgForm.Left:=FLeft;
640       DlgForm.Top:=FTop;
641     end else begin
642       FLeft:=DlgForm.Left;
643       FTop:=DlgForm.Top;
644     end;
645     CPanel:=TCalculatorForm(DlgForm).CalcPanel;
646 
647     DlgForm.Caption:=Title;
648     CPanel.Memory:=FMemory;
649     CPanel.UpdateMemoryLabel;
650     If Precision>2 then
651       CPanel.Precision:=Precision
652     else
653       CPanel.Precision:=2;
654     CPanel.BeepOnError:=BeepOnError;
655     if FValue <> 0 then begin
656       CPanel.DisplayValue:=FValue;
657       CPanel.Status:=csFirst;
658       CPanel.OperatorChar:='=';
659     end;
660     Result := (DlgForm.ShowModal = mrOk);
661     FLeft := DlgForm.Left;
662     FTop := DlgForm.Top;
663     //update private fields FHeight and FWidth of ancestor
664     SetHeight(DlgForm.Height);
665     SetWidth(DlgForm.Width);
666     if Result then begin
667       FMemory:=CPanel.Memory;
668       if CPanel.DisplayValue <> FValue then begin
669         FValue:=CPanel.DisplayValue;
670         Change;
671       end;
672     end;
673   finally
674     DlgForm.Free;
675     DlgForm:=nil;
676   end;
677 end;
678 
679 
680 { ---------------------------------------------------------------------
681   TCalendarDialog
682   ---------------------------------------------------------------------}
683 
684 { TCalendarDialog }
685 
686 constructor TCalendarDialog.Create(AOwner: TComponent);
687 begin
688   inherited Create(AOwner);
689   DisplaySettings := DefaultDisplaySettings;
690   Date := trunc(Now);
691   OKCaption := rsMbOK;
692   CancelCaption := rsMbCancel;
693 end;
694 
695 procedure TCalendarDialog.GetNewDate(Sender:TObject);//or onClick
696 begin
697   Date:=FCalendar.DateTime;
698 end;
699 
700 procedure TCalendarDialog.CalendarDblClick(Sender: TObject);
701 var
702   CalendarForm: TForm;
703   P: TPoint;
704   htRes: TCalendarPart;
705 begin
706   P := FCalendar.ScreenToClient(Mouse.CursorPos);
707   //if FCalendar.HitTest(P) in [cpNoWhere, cpDate] then
708   htRes := FCalendar.HitTest(P);
709   if {(htRes = cpNoWhere) or }((htRes = cpDate) and (FCalendar.GetCalendarView = cvMonth)) then
710   begin
711     GetNewDate(Sender);
712     CalendarForm:=TForm(TComponent(Sender).Owner);
713     // close the calendar dialog
714     CalendarForm.ModalResult:=mrOk;
715   end;
716 end;
717 
DefaultTitlenull718 function TCalendarDialog.DefaultTitle: string;
719 begin
720   Result := rsPickDate;
721 end;
722 
723 procedure TCalendarDialog.OnDialogClose(Sender: TObject;
724   var CloseAction: TCloseAction);
725 begin
726   //if Assigned(OnClose) then OnClose(Self);
727   DoClose;
728 end;
729 
730 procedure TCalendarDialog.OnDialogCloseQuery(Sender: TObject;
731   var CanClose: boolean);
732 begin
733   //if Assigned(OnCanClose) then OnCanClose(Sender, CanClose);
734   if DlgForm.ModalResult = mrOK then
735     UserChoice := mrOk
736   else
737     UserChoice := mrCancel;
738   DoCanClose(CanClose);
739 end;
740 
741 procedure TCalendarDialog.OnDialogShow(Sender: TObject);
742 begin
743   DoShow;
744 end;
745 
746 procedure TCalendarDialog.OnCalendarDayChanged(Sender: TObject);
747 begin
748   GetNewDate(Self);
749   if Assigned(FDayChanged) then FDayChanged(Self);
750 end;
751 
752 procedure TCalendarDialog.OnCalendarMonthChanged(Sender: TObject);
753 begin
754   GetNewDate(Self);
755   if Assigned(FMonthChanged) then FMonthChanged(Self);
756 end;
757 
758 procedure TCalendarDialog.OnCalendarYearChanged(Sender: TObject);
759 begin
760   GetNewDate(Self);
761   if Assigned(FYearChanged) then FYearChanged(Self);
762 end;
763 
764 procedure TCalendarDialog.OnCalendarChange(Sender: TObject);
765 begin
766   //Date already updated in OnCalendarXXXChanged
767   if Assigned(FOnChange) then FOnChange(Self);
768 end;
769 
770 
771 class procedure TCalendarDialog.WSRegisterClass;
772 begin
773   inherited WSRegisterClass;
774   RegisterCalendarDialog;
775 end;
776 
Executenull777 function TCalendarDialog.Execute:boolean;
778 const
779   dw=8;
780   bbs=2;
781 var
782   okButton,cancelButton: TButton;
783   panel: TPanel;
784 begin
785   DlgForm:=TForm.CreateNew(Application, 0);
786   try
787     ResetShowCloseFlags;
788     DlgForm.DisableAlign;
789     DlgForm.Caption:=Title;
790     if (csDesigning in ComponentState) then
791       DlgForm.Position:=poScreenCenter
792     else
793       DlgForm.Position:=DialogPosition;
794     if (DlgForm.Position=poDesigned) then begin
795       DlgForm.Left:=FLeft;
796       DlgForm.Top:=FTop;
797     end else begin
798       FLeft:=DlgForm.Left;
799       FTop:=DlgForm.Top;
800     end;
801     DlgForm.BorderStyle:=bsDialog;
802     DlgForm.AutoScroll:=false;
803     DlgForm.AutoSize:=true;
804     DlgForm.OnShow := @OnDialogShow;
805     DlgForm.OnClose:=@OnDialogClose;
806     DlgForm.OnCloseQuery:=@OnDialogCloseQuery;
807 
808     FCalendar:=TCalendar.Create(DlgForm);
809     with FCalendar do begin
810       Parent:=DlgForm;
811       Align:=alTop;
812       DateTime:=Self.Date;
813       TabStop:=True;
814       DisplaySettings:=Self.DisplaySettings;
815       OnDayChanged:=@Self.OnCalendarDayChanged;
816       OnMonthChanged:=@Self.OnCalendarMonthChanged;
817       OnYearChanged:=@Self.OnCalendarYearChanged;
818       OnChange:=@Self.OnCalendarChange;
819       OnDblClick:=@CalendarDblClick;
820     end;
821 
822     panel:=TPanel.Create(DlgForm);
823     with panel do begin
824       Parent:=DlgForm;
825       Caption:='';
826       Height:=32;
827       AnchorToCompanion(akTop, 0, FCalendar);
828       BevelOuter:=bvLowered;
829     end;
830 
831     okButton:=TButton.Create(DlgForm);
832     with okButton do begin
833       Parent:=panel;
834       Caption:=OKCaption;
835       Constraints.MinWidth:=75;
836       Constraints.MaxWidth:=FCalendar.Width div 2 - bbs;
837       Width:=DlgForm.Canvas.TextWidth(OKCaption)+2*dw;
838       ModalResult:=mrOK;
839       OnClick:=@GetNewDate;
840       //Align:=alRight;
841       Anchors := [akTop,akRight];
842       BorderSpacing.Right:=bbs;
843       AnchorSide[akRight].Side:=asrRight;
844       AnchorSide[akRight].Control:=panel;
845       AnchorVerticalCenterTo(panel);
846       Default:=True;
847     end;
848 
849     cancelButton:=TButton.Create(DlgForm);
850     with cancelButton do begin
851       Parent:=panel;
852       Caption:=CancelCaption;
853       Constraints.MinWidth:=75;
854       Constraints.MaxWidth:=FCalendar.Width div 2;
855       Width:=DlgForm.Canvas.TextWidth(CancelCaption)+2*dw;;
856       ModalResult:=mrCancel;
857       //Align:=alLeft;
858       BorderSpacing.Left:=bbs;
859       Anchors:=[akLeft,akTop];
860       AnchorSide[akLeft].Side:=asrLeft;
861       AnchorSide[akLeft].Control:=panel;
862       AnchorVerticalCenterTo(panel);
863       Cancel:=True;
864     end;
865     DlgForm.ClientWidth := FCalendar.Width;
866     DlgForm.ClientHeight := panel.Top+panel.Height;
867 
868     DlgForm.EnableAlign;
869     Result:=DlgForm.ShowModal=mrOK;
870     FLeft:=DlgForm.Left;
871     FTop:=DlgForm.Top;
872     //update private fields FHeight and FWidth of ancestor
873     SetHeight(DlgForm.Height);
874     SetWidth(DlgForm.Width);
875   finally
876     DlgForm.Free;
877     DlgForm := nil;
878   end;
879 end;
880 
881 
882 end.
883