1 {
2  *****************************************************************************
3   See the file COPYING.modifiedLGPL.txt, included in this distribution,
4   for details about the license.
5  *****************************************************************************
6 
7   Author: Andrew Johnson, Mattias Gaertner
8 
9   Abstract:
10     This unit defines the property editors for graphic types.
11 }
12 unit GraphPropEdits;
13 
14 {$mode objfpc}{$H+}
15 
16 interface
17 
18 uses
19   Classes, TypInfo, SysUtils, LCLProc, Forms, Controls, LCLType, GraphType,
20   LazFileUtils, Graphics, Buttons, Menus, ExtCtrls, Dialogs, Grids,
21   LCLIntf, PropEdits, PropEditUtils, ImgList, EditBtn, Math,
22   GraphicPropEdit; // defines TGraphicPropertyEditorForm
23 
24 type
25 { TGraphicPropertyEditor
26   The default property editor for all TGraphic's and sub types (e.g. TBitmap,
27   TPixmap, TIcon, etc.). }
28 
29   TGraphicPropertyEditor = class(TClassPropertyEditor)
30   public
31     procedure Edit; override;
GetAttributesnull32     function GetAttributes: TPropertyAttributes; override;
33   end;
34 
35 { TPicturePropertyEditor
36   The default property editor for TPicture}
37 
38   TPicturePropertyEditor = class(TGraphicPropertyEditor)
39   public
40     procedure Edit; override;
41   end;
42 
43 { TButtonGlyphPropEditor
44   The default property editor for the Glyphs of TSpeedButton and TBitBtn }
45   TButtonGlyphPropEditor = class(TGraphicPropertyEditor)
46   public
47     procedure Edit; override;
48   end;
49 
50 { TColorPropertyEditor
51   PropertyEditor editor for the TColor type. Displays the color as a clXXX value
52   if one exists, otherwise displays the value as hex.  Also allows the
53   clXXX value to be picked from a list. }
54 
55   TColorPropertyEditor = class(TIntegerPropertyEditor)
56   public
57     procedure Edit; override;
GetAttributesnull58     function GetAttributes: TPropertyAttributes; override;
OrdValueToVisualValuenull59     function OrdValueToVisualValue(OrdValue: longint): string; override;
60     procedure GetValues(Proc: TGetStrProc); override;
61     procedure SetValue(const NewValue: ansistring); override;
62     procedure ListMeasureWidth(const {%H-}CurValue: ansistring; {%H-}Index: integer;
63       ACanvas: TCanvas; var AWidth: Integer);  override;
64     procedure ListDrawValue(const CurValue: ansistring; Index: integer;
65       ACanvas: TCanvas; const ARect:TRect; AState: TPropEditDrawState); override;
66     procedure PropDrawValue(ACanvas: TCanvas; const ARect: TRect;
67       AState: TPropEditDrawState); override;
68   end;
69 
70 { TBrushStylePropertyEditor
71   PropertyEditor editor for TBrush's Style. Provides custom render. }
72 
73   TBrushStylePropertyEditor = class(TEnumPropertyEditor)
74   public
GetAttributesnull75     function GetAttributes: TPropertyAttributes; override;
76     procedure ListMeasureWidth(const {%H-}CurValue: ansistring; {%H-}Index:integer;
77       {%H-}ACanvas: TCanvas;  var AWidth: Integer); override;
78     procedure ListDrawValue(const CurValue: ansistring; Index:integer;
79       ACanvas: TCanvas;  const ARect: TRect; AState: TPropEditDrawState); override;
80     procedure PropDrawValue(ACanvas: TCanvas; const ARect: TRect;
81       AState: TPropEditDrawState); override;
82   end;
83 
84 { TPenStylePropertyEditor
85   PropertyEditor editor for TPen's Style. Simply provides custom render. }
86 
87   TPenStylePropertyEditor = class(TEnumPropertyEditor)
88   public
GetAttributesnull89     function GetAttributes: TPropertyAttributes; override;
90     procedure ListMeasureWidth(const {%H-}CurValue: ansistring; {%H-}Index:integer;
91       {%H-}ACanvas: TCanvas;  var AWidth: Integer); override;
92     procedure ListDrawValue(const CurValue: ansistring; {%H-}Index:integer;
93       ACanvas: TCanvas;  const ARect: TRect; AState: TPropEditDrawState); override;
94     procedure PropDrawValue(ACanvas: TCanvas; const ARect: TRect;
95       AState:TPropEditDrawState); override;
96   end;
97 
98 { TFontPropertyEditor
99   PropertyEditor editor for the Font property.
100   Brings up the font dialog as well as allowing the properties of the object to
101   be edited. }
102 
103   TFontPropertyEditor = class(TClassPropertyEditor)
104   public
105     procedure Edit; override;
GetAttributesnull106     function GetAttributes: TPropertyAttributes; override;
107   end;
108 
109 { TFontNamePropertyEditor
110   PropertyEditor editor for TFont.Name. Simply provides listing font names. }
111 
112   TFontNamePropertyEditor = class(TStringPropertyEditor)
113   public
GetAttributesnull114     function GetAttributes: TPropertyAttributes; override;
115     procedure GetValues(Proc: TGetStrProc); override;
116   end;
117 
118 { TFontCharsetPropertyEditor
119   PropertyEditor editor for the TFontCharset properties.
120   Displays Charset as constant name if exists, otherwise an integer. }
121 
122   TFontCharsetPropertyEditor = class(TIntegerPropertyEditor)
123   public
GetAttributesnull124     function GetAttributes: TPropertyAttributes; override;
OrdValueToVisualValuenull125     function OrdValueToVisualValue(OrdValue: longint): string; override;
126     procedure GetValues(Proc: TGetStrProc); override;
127     procedure SetValue(const NewValue: ansistring); override;
128   end;
129 
130 { TImageIndexPropertyEditor
131   PropertyEditor editor for ImageIndex. Provides list of glyphs. }
132 
133   TImageIndexPropertyEditor = class(TIntegerPropertyEditor)
134   protected
GetImageListnull135     function GetImageList: TCustomImageList; virtual;
136   public
GetAttributesnull137     function GetAttributes: TPropertyAttributes; override;
138     procedure GetValues(Proc: TGetStrProc); override;
139     procedure ListMeasureHeight(const {%H-}AValue: ansistring; {%H-}Index:integer;
140       ACanvas:TCanvas; var AHeight: Integer); override;
141     procedure ListDrawValue(const CurValue: ansistring; Index:integer;
142       ACanvas: TCanvas;  const ARect: TRect; AState: TPropEditDrawState); override;
143   end;
144 
145 { TGridImageIndexPropertyEditor
146   ImageIndex property editor specialized for a grid's title and sort images. }
147 
148   TGridImageIndexPropertyEditor = class(TImageIndexPropertyEditor)
149   protected
GetImageListnull150     function GetImageList: TCustomImageList; override;
151   end;
152 
153 //==============================================================================
154 // Delphi Compatible Property Editor Classnames
155 
156 type
157   TFontNameProperty =       TFontNamePropertyEditor;
158   //TFontCharsetProperty =    TFontCharsetPropertyEditor;
159   TColorProperty =          TColorPropertyEditor;
160   TBrushStyleProperty =     TBrushStylePropertyEditor;
161   TPenStyleProperty =       TPenStylePropertyEditor;
162   TFontProperty =           TFontPropertyEditor;
163 
164 implementation
165 
166 { TGraphicPropertyEditor }
167 
168 procedure TGraphicPropertyEditor.Edit;
169 var
170   TheDialog: TGraphicPropertyEditorForm;
171   AGraphic: TGraphic;
172   FreeGraphic: Boolean;
173 begin
174   AGraphic := TGraphic(GetObjectValue(TGraphic));
175   TheDialog := TGraphicPropertyEditorForm.Create(nil);
176   FreeGraphic:=false;
177   try
178     TheDialog.CaptionDetail := GetComponent(0).GetNamePath + '.' + GetName();
179     if (AGraphic <> nil) then
180       TheDialog.Graphic := AGraphic;
181 
182     if (TheDialog.ShowModal = mrOK) and TheDialog.Modified then
183     begin
184       if (TheDialog.Graphic <> nil) and (not TheDialog.Graphic.Empty) then
185       begin
186         if AGraphic = nil then
187         begin
188           AGraphic := TGraphicClass(GetTypeData(GetPropType)^.ClassType).Create;
189           FreeGraphic := True;
190         end;
191 
192         AGraphic.Assign(TheDialog.Graphic);
193 
194         if (AGraphic.ClassType = TheDialog.Graphic.ClassType)
195           and not AGraphic.Equals(TheDialog.Graphic) then
196         begin
197           if (TheDialog.FileName <> '') and FileExistsUTF8(TheDialog.FileName) then
198           begin
199             AGraphic.LoadFromFile(TheDialog.FileName);
200             //MessageDlg('Differences detected, file reloaded', mtInformation, [mbOK], 0);
201           end
202           else
203             //MessageDlg('Image may be different', mtWarning, [mbOK], 0);
204         end;
205 
206         SetPtrValue(AGraphic);
207       end
208       else
209       if AGraphic <> nil then
210         AGraphic.Clear;
211       Modified;
212     end;
213   finally
214     if FreeGraphic then
215       AGraphic.Free;
216     TheDialog.Free;
217   end;
218 end;
219 
GetAttributesnull220 function TGraphicPropertyEditor.GetAttributes: TPropertyAttributes;
221 begin
222   Result := [paDialog, paRevertable, paReadOnly];
223 end;
224 
225 { TPicturePropertyEditor }
226 
227 procedure TPicturePropertyEditor.Edit;
228 
229   procedure AddPackage(Picture: TPicture);
230   begin
231     if (Picture.Graphic=nil) or (GlobalDesignHook=nil) then exit;
232     //DebugLn(['AddPackage ',dbgsname(Picture.Graphic)]);
233     GlobalDesignHook.AddDependency(Picture.Graphic.ClassType,'');
234   end;
235 
236 var
237   TheDialog: TGraphicPropertyEditorForm;
238   Picture: TPicture;
239 begin
240   Picture := TPicture(GetObjectValue(TPicture));
241   TheDialog := TGraphicPropertyEditorForm.Create(nil);
242   try
243     TheDialog.CaptionDetail := GetComponent(0).GetNamePath + '.' + GetName();
244     if (Picture.Graphic <> nil) then
245       TheDialog.Graphic := Picture.Graphic;
246     if (TheDialog.ShowModal = mrOK) and TheDialog.Modified then
247     begin
248       if TheDialog.Graphic <> nil then
249       begin
250         Picture.Graphic := TheDialog.Graphic;
251         if not Picture.Graphic.Equals(TheDialog.Graphic) then
252         begin
253           if (TheDialog.FileName <> '') and FileExistsUTF8(TheDialog.FileName) then
254           begin
255             Picture.LoadFromFile(TheDialog.FileName);
256             //MessageDlg('Differences detected, file reloaded', mtInformation, [mbOK], 0);
257           end
258           else
259             //MessageDlg('Image may be different', mtWarning, [mbOK], 0);
260         end;
261         AddPackage(Picture);
262       end
263       else
264         Picture.Graphic := nil;
265       Modified;
266     end;
267   finally
268     TheDialog.Free;
269   end;
270 end;
271 
272 { TButtonGlyphPropEditor }
273 
274 procedure TButtonGlyphPropEditor.Edit;
275 var
276   TheDialog: TGraphicPropertyEditorForm;
277   ABitmap: TBitmap;
278 begin
279   ABitmap := TBitmap(GetObjectValue(TBitmap));
280   TheDialog := TGraphicPropertyEditorForm.Create(nil);
281   try
282     TheDialog.CaptionDetail := GetComponent(0).GetNamePath + '.' + GetName();
283     if not ABitmap.Empty then
284       TheDialog.Graphic := ABitmap;
285     if (TheDialog.ShowModal = mrOK) and TheDialog.Modified then
286     begin
287       ABitmap.Assign(TheDialog.Graphic);
288       Modified;
289     end;
290   finally
291     TheDialog.Free;
292   end;
293 end;
294 
295 { TColorPropertyEditor }
296 
297 procedure TColorPropertyEditor.Edit;
298 var
299   ColorDialog: TColorDialog;
300 begin
301   ColorDialog := TColorDialog.Create(nil);
302   try
303     ColorDialog.Color := GetOrdValue;
304     if ColorDialog.Execute then
305       SetOrdValue(ColorDialog.Color);
306   finally
307     ColorDialog.Free;
308   end;
309 end;
310 
GetAttributesnull311 function TColorPropertyEditor.GetAttributes: TPropertyAttributes;
312 begin
313   Result := [paMultiSelect,paDialog,paValueList,paCustomDrawn,paRevertable];
314 end;
315 
OrdValueToVisualValuenull316 function TColorPropertyEditor.OrdValueToVisualValue(OrdValue: longint): string;
317 begin
318   Result := ColorToString(TColor(OrdValue));
319 end;
320 
321 procedure TColorPropertyEditor.GetValues(Proc: TGetStrProc);
322 var
323   CValue: Longint;
324 begin
325   if not IdentToColor(GetVisualValue, CValue) then Proc(GetVisualValue);
326   GetColorValues(Proc);
327 end;
328 
329 procedure TColorPropertyEditor.PropDrawValue(ACanvas:TCanvas; const ARect:TRect;
330   AState:TPropEditDrawState);
331 begin
332   if GetVisualValue <> '' then
333     ListDrawValue(GetVisualValue, -1, ACanvas, ARect, [pedsInEdit])
334   else
335     inherited PropDrawValue(ACanvas, ARect, AState);
336 end;
337 
338 procedure TColorPropertyEditor.ListDrawValue(const CurValue:ansistring;
339   Index:integer; ACanvas:TCanvas;  const ARect:TRect;
340   AState: TPropEditDrawState);
341 
ColorToBorderColornull342   function ColorToBorderColor(AColor: TColorRef): TColor;
343   type
344     TColorQuad = record
345       Red,
346       Green,
347       Blue,
348       Alpha: Byte;
349     end;
350   begin
351     if (TColorQuad(AColor).Red > 192) or
352        (TColorQuad(AColor).Green > 192) or
353        (TColorQuad(AColor).Blue > 192) then
354       Result := clBlack
355     else
356       if pedsInEdit in AState then
357       begin
358         if pedsSelected in AState then
359           Result := clWindow
360         else
361          Result := TColor(AColor);
362       end else
363       begin
364         if pedsSelected in AState then
365           Result := clHighlight
366         else
367          Result := clWindow;
368       end;
369   end;
370 var
371   vRight, vBottom: Integer;
372   vOldPenColor, vOldBrushColor: TColor;
373   vOldPenStyle: TPenStyle;
374   noFill: Boolean;
375 begin
376   vRight := (ARect.Bottom - ARect.Top) + ARect.Left - 2;
377   vBottom:=ARect.Bottom-2;
378   with ACanvas do
379   begin
380     // save off things
381     vOldPenStyle := Pen.Style;
382     vOldPenColor := Pen.Color;
383     vOldBrushColor := Brush.Color;
384 
385     // set things up and do the work
386     noFill := CurValue = 'clNone';
387     if noFill then
388       Brush.Color := clWindow
389     else
390       Brush.Color := StringToColorDef(CurValue,clNone);
391     Pen.Color := ColorToBorderColor(ColorToRGB(Brush.Color));
392     Rectangle(ARect.Left + 1, ARect.Top + 1, vRight - 1, vBottom - 1);
393     if noFill then
394     begin
395       Line(ARect.Left + 1, ARect.Top + 1, vRight - 2, vBottom - 2);
396       Line(ARect.Left + 1, vBottom - 2, vRight - 2, ARect.Top + 1);
397     end;
398 
399     // restore the things we twiddled with
400     Brush.Color := vOldBrushColor;
401     Pen.Color := vOldPenColor;
402     Pen.Style := vOldPenStyle;
403   end;
404   inherited ListDrawValue(CurValue, Index, ACanvas,
405                           Rect(vRight, ARect.Top, ARect.Right, ARect.Bottom),
406                           AState);
407 end;
408 
409 procedure TColorPropertyEditor.ListMeasureWidth(const CurValue:ansistring;
410   Index:integer; ACanvas:TCanvas;  var AWidth:Integer);
411 begin
412   AWidth := ACanvas.TextWidth('clGradientInactiveCaption')+25;
413 end;
414 
415 procedure TColorPropertyEditor.SetValue(const NewValue: ansistring);
416 var
417   CValue: Longint;
418 begin
419   if IdentToColor(NewValue, CValue) then
420     SetOrdValue(CValue)
421   else
422     inherited SetValue(NewValue);
423 end;
424 
GetAttributesnull425 function TFontNamePropertyEditor.GetAttributes: TPropertyAttributes;
426 begin
427   Result := [paMultiSelect, paValueList, paRevertable];
428 end;
429 
430 procedure TFontNamePropertyEditor.GetValues(Proc: TGetStrProc);
431 var
432   I: Integer;
433 begin
434   Proc('default');
435   for I := 0 to Screen.Fonts.Count -1 do
436     Proc(Screen.Fonts[I]);
437 end;
438 
439 { TFontCharsetPropertyEditor }
440 
GetAttributesnull441 function TFontCharsetPropertyEditor.GetAttributes: TPropertyAttributes;
442 begin
443   Result:=[paMultiSelect,paSortList,paValueList,paRevertable];
444 end;
445 
OrdValueToVisualValuenull446 function TFontCharsetPropertyEditor.OrdValueToVisualValue(OrdValue: longint
447   ): string;
448 begin
449   Result := CharsetToString(OrdValue);
450 end;
451 
452 procedure TFontCharsetPropertyEditor.GetValues(Proc: TGetStrProc);
453 begin
454   proc(CharsetToString(ANSI_CHARSET));
455   proc(CharsetToString(DEFAULT_CHARSET));
456   proc(CharsetToString(SYMBOL_CHARSET));
457   proc(CharsetToString(MAC_CHARSET));
458   proc(CharsetToString(SHIFTJIS_CHARSET));
459   proc(CharsetToString(HANGEUL_CHARSET));
460   proc(CharsetToString(JOHAB_CHARSET));
461   proc(CharsetToString(GB2312_CHARSET));
462   proc(CharsetToString(CHINESEBIG5_CHARSET));
463   proc(CharsetToString(GREEK_CHARSET));
464   proc(CharsetToString(TURKISH_CHARSET));
465   proc(CharsetToString(VIETNAMESE_CHARSET));
466   proc(CharsetToString(HEBREW_CHARSET));
467   proc(CharsetToString(ARABIC_CHARSET));
468   proc(CharsetToString(BALTIC_CHARSET));
469   proc(CharsetToString(RUSSIAN_CHARSET));
470   proc(CharsetToString(THAI_CHARSET));
471   proc(CharsetToString(EASTEUROPE_CHARSET));
472   proc(CharsetToString(OEM_CHARSET));
473   proc(CharsetToString(FCS_ISO_10646_1));
474 end;
475 
476 procedure TFontCharsetPropertyEditor.SetValue(const NewValue: ansistring);
477 var
478   CValue: Longint;
479 begin
480   if not SameText(NewValue, 'DEFAULT_CHARSET') then
481   begin
482     CValue := StringToCharset(NewValue);
483     if CValue = DEFAULT_CHARSET then
484       inherited SetValue(NewValue)
485     else
486       SetOrdValue(CValue);
487   end
488   else
489     SetOrdValue(DEFAULT_CHARSET);
490 end;
491 
492 { TBrushStylePropertyEditor }
493 
494 procedure TBrushStylePropertyEditor.PropDrawValue(ACanvas: TCanvas;
495   const ARect: TRect;  AState:TPropEditDrawState);
496 begin
497   if GetVisualValue <> '' then
498     ListDrawValue(GetVisualValue, -1, ACanvas, ARect, [pedsInEdit])
499   else
500     inherited PropDrawValue(ACanvas, ARect, AState);
501 end;
502 
503 procedure TBrushStylePropertyEditor.ListDrawValue(const CurValue: ansistring;
504   Index:integer;  ACanvas: TCanvas; const ARect: TRect; AState:TPropEditDrawState);
505 var
506   vRight, vBottom: Integer;
507   vOldPenColor, vOldBrushColor: TColor;
508   vOldBrushStyle: TBrushStyle;
509 begin
510   vRight := (ARect.Bottom - ARect.Top) {* 2} + ARect.Left -2;
511   vBottom:= ARect.Bottom-2;
512   with ACanvas do
513   try
514     // save off things
515     vOldPenColor := Pen.Color;
516     vOldBrushColor := Brush.Color;
517     vOldBrushStyle := Brush.Style;
518 
519     // frame things
520     Pen.Color := Brush.Color;
521     Brush.Color := clWindow;
522     Rectangle(ARect.Left, ARect.Top, vRight, vBottom);
523 
524     // set things up
525     Pen.Color := clWindowText;
526     Brush.Style := TBrushStyle(GetEnumValue(GetPropInfo^.PropType, CurValue));
527 
528     // bsClear hack
529     if Brush.Style = bsClear then begin
530       Brush.Color := clWindow;
531       Brush.Style := bsSolid;
532     end
533     else
534       Brush.Color := clWindowText;
535 
536     // ok on with the show
537     Rectangle(ARect.Left + 1, ARect.Top + 1, vRight - 1, vBottom - 1);
538 
539     // restore the things we twiddled with
540     Brush.Color := vOldBrushColor;
541     Brush.Style := vOldBrushStyle;
542     Pen.Color := vOldPenColor;
543   finally
544     inherited ListDrawValue(CurValue, Index, ACanvas,
545                             Rect(vRight, ARect.Top, ARect.Right, ARect.Bottom),
546                             AState);
547   end;
548 end;
549 
GetAttributesnull550 function TBrushStylePropertyEditor.GetAttributes: TPropertyAttributes;
551 begin
552   Result:=(inherited GetAttributes)+[paCustomDrawn];
553 end;
554 
555 procedure TBrushStylePropertyEditor.ListMeasureWidth(const CurValue: ansistring;
556   Index:integer; ACanvas: TCanvas; var AWidth: Integer);
557 begin
558   AWidth := 130;
559 end;
560 
561 { TPenStylePropertyEditor }
562 
563 procedure TPenStylePropertyEditor.PropDrawValue(ACanvas: TCanvas;
564   const ARect: TRect;  AState:TPropEditDrawState);
565 begin
566   if GetVisualValue <> '' then
567     ListDrawValue(GetVisualValue, -1, ACanvas, ARect, [pedsInEdit])
568   else
569     inherited PropDrawValue(ACanvas, ARect, AState);
570 end;
571 
572 procedure TPenStylePropertyEditor.ListDrawValue(const CurValue: ansistring;
573   Index:integer;  ACanvas: TCanvas;
574   const ARect: TRect; AState:TPropEditDrawState);
575 var
576   vRight, vTop, vBottom: Integer;
577   vOldPenColor, vOldBrushColor: TColor;
578   vOldPenStyle: TPenStyle;
579   i: Integer;
580 begin
581   vRight := (ARect.Bottom - ARect.Top) * 2 + ARect.Left;
582   vTop := (ARect.Bottom - ARect.Top) div 2 + ARect.Top;
583   vBottom := ARect.Bottom-2;
584   with ACanvas do
585   try
586     // save off things
587     vOldPenColor := Pen.Color;
588     vOldBrushColor := Brush.Color;
589     vOldPenStyle := Pen.Style;
590 
591     // frame things
592     Pen.Color := Brush.Color;
593     Rectangle(ARect.Left, ARect.Top, vRight, vBottom);
594 
595     // white out the background
596     Pen.Color := clWindowText;
597     Brush.Color := clWindow;
598     Rectangle(ARect.Left + 1, ARect.Top + 1, vRight - 1, vBottom - 1);
599 
600     // set thing up and do work
601     Pen.Color := clWindowText;
602     i:=GetEnumValue(GetPropInfo^.PropType, CurValue);
603     Pen.Style := TPenStyle(i);
604     MoveTo(ARect.Left + 1, vTop);
605     LineTo(vRight - 1, vTop);
606     MoveTo(ARect.Left + 1, vTop + 1);
607     LineTo(vRight - 1, vTop + 1);
608 
609     // restore the things we twiddled with
610     Brush.Color := vOldBrushColor;
611     Pen.Style := vOldPenStyle;
612     Pen.Color := vOldPenColor;
613   finally
614     inherited ListDrawValue(CurValue, -1, ACanvas,
615                             Rect(vRight, ARect.Top, ARect.Right, ARect.Bottom),
616                             AState);
617   end;
618 end;
619 
GetAttributesnull620 function TPenStylePropertyEditor.GetAttributes: TPropertyAttributes;
621 begin
622   Result:=(inherited GetAttributes)+[paCustomDrawn];
623 end;
624 
625 procedure TPenStylePropertyEditor.ListMeasureWidth(const CurValue: ansistring;
626   Index:integer; ACanvas: TCanvas; var AWidth: Integer);
627 begin
628   AWidth := 130;
629 end;
630 
631 { TFontPropertyEditor }
632 
633 procedure TFontPropertyEditor.Edit;
634 var FontDialog: TFontDialog;
635 begin
636   FontDialog := TFontDialog.Create(nil);
637   try
638     FontDialog.Font := TFont(GetObjectValue(TFont));
639     FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
640     if FontDialog.Execute then
641       SetPtrValue(FontDialog.Font);
642   finally
643     FontDialog.Free;
644   end;
645 end;
646 
GetAttributesnull647 function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
648 begin
649   Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
650 end;
651 
652 
653 //------------------------------------------------------------------------------
654 
655 { TImageIndexPropertyEditor }
656 
657 type
658   TOwnedCollectionHelper = class(TOwnedCollection)
659   end;
660 
TImageIndexPropertyEditor.GetImageListnull661 function TImageIndexPropertyEditor.GetImageList: TCustomImageList;
662 var
663   Persistent: TPersistent;
664   Component: TComponent absolute Persistent;
665   PropInfo: PPropInfo;
666   Obj: TObject;
667 begin
668   Result := nil;
669   Persistent := GetComponent(0);
670 
671   if (Persistent is TCollectionItem) and
672     (TCollectionItem(Persistent).Collection <> nil) and
673     (TCollectionItem(Persistent).Collection is TOwnedCollection) and
674     (TOwnedCollectionHelper(TCollectionItem(Persistent).Collection).Owner <> nil) and
675     (TOwnedCollectionHelper(TCollectionItem(Persistent).Collection).Owner is TComponent) then
676   begin
677     Component := TComponent(TOwnedCollectionHelper(TCollectionItem(Persistent).Collection).Owner);
678     PropInfo := TypInfo.GetPropInfo(Component, 'Images');
679     if PropInfo = nil then
680       Exit;
681     Obj := GetObjectProp(Component, PropInfo);
682     if Obj is TCustomImageList then
683       Exit(TCustomImageList(Obj));
684     Exit;
685   end
686   else
687     if not (Persistent is TComponent) then
688       Exit;
689 
690   if Component is TMenuItem then
691   begin
692     Component := Component.GetParentComponent;
693     while (Component <> nil) do
694     begin
695       if (Component is TMenuItem) and (TMenuItem(Component).SubMenuImages <> nil) then
696         Exit(TMenuItem(Component).SubMenuImages);
697       if (Component is TMenu) then
698         Exit(TMenu(Component).Images);
699       Component := Component.GetParentComponent;
700     end;
701   end
702   else
703   begin
704     if not (
705          (Component is TCustomSpeedButton)
706       or (Component is TCustomBitBtn)
707       or (Component is TCustomEditButton))
708     then
709       Component := Component.GetParentComponent;
710     if Component = nil then
711       Exit;
712     PropInfo := TypInfo.GetPropInfo(Component, 'Images');
713     if PropInfo = nil then
714       Exit;
715     Obj := GetObjectProp(Component, PropInfo);
716     if Obj is TCustomImageList then
717       Exit(TCustomImageList(Obj));
718   end;
719 end;
720 
GetAttributesnull721 function TImageIndexPropertyEditor.GetAttributes: TPropertyAttributes;
722 begin
723   Result := [paValueList, paCustomDrawn, paRevertable];
724 end;
725 
726 procedure TImageIndexPropertyEditor.GetValues(Proc: TGetStrProc);
727 var
728   Images: TCustomImageList;
729   I, DefValue: Integer;
730 begin
731   Proc(IntToStr(-1));
732   DefValue := GetDefaultOrdValue;
733   if (DefValue <> NoDefaultValue) and (DefValue <> -1) then
734     Proc(IntToStr(DefValue));
735   Images := GetImageList;
736   if Assigned(Images) then
737     for I := 0 to Images.Count - 1 do
738       if (I <> DefValue) then
739         Proc(IntToStr(I));
740 end;
741 
742 procedure TImageIndexPropertyEditor.ListMeasureHeight(const AValue: ansistring;
743   Index: integer; ACanvas: TCanvas; var AHeight: Integer);
744 var
745   Images: TCustomImageList;
746 begin
747   AHeight := ACanvas.TextHeight('1');
748   Images := GetImageList;
749   if Assigned(Images) then
750     AHeight := Max(AHeight, Images.Height + 2);
751 end;
752 
753 procedure TImageIndexPropertyEditor.ListDrawValue(const CurValue: ansistring;
754   Index: integer; ACanvas: TCanvas; const ARect: TRect; AState: TPropEditDrawState);
755 var
756   Images: TCustomImageList;
757   R: TRect;
758   OldColor: TColor;
759 begin
760   if GetDefaultOrdValue <> NoDefaultValue then
761     Dec(Index);
762   Images := GetImageList;
763   R := ARect;
764   if Assigned(Images) then
765   begin
766     if (pedsInComboList in AState) and not (pedsInEdit in AState) then
767     begin
768       OldColor := ACanvas.Brush.Color;
769       if pedsSelected in AState then
770         ACanvas.Brush.Color := clHighlight
771       else
772         ACanvas.Brush.Color := clWhite;
773       ACanvas.FillRect(R);
774       ACanvas.Brush.Color := OldColor;
775     end;
776 
777     Images.Draw(ACanvas, R.Left + 1, R.Top + 1, Index, True);
778     R.Left := R.Left + Images.Width + 2;
779   end;
780   inherited ListDrawValue(CurValue, Index, ACanvas, R, AState);
781 end;
782 
783 { TGridImageIndexPropertyEditor }
784 
785 type
786   TCustomGridOpener = class(TCustomGrid);
787 
TGridImageIndexPropertyEditor.GetImagelistnull788 function TGridImageIndexPropertyEditor.GetImagelist: TCustomImagelist;
789 var
790   p: TPersistent;
791 begin
792   Result := nil;
793   p := GetComponent(0);
794   if (p is TGridColumnTitle) then begin
795     p := TGridColumnTitle(p).Column;
796     if not (p is TGridColumn) then exit;
797     p := TGridColumn(p).Collection;
798     if not (p is TGridColumns) then exit;
799     p := TGridColumns(p).Grid;
800   end;
801   if p is TCustomGrid then
802     Result := TCustomGridOpener(p).TitleImageList
803 end;
804 
805 initialization
806   RegisterPropertyEditor(TypeInfo(TGraphicsColor), nil, '', TColorPropertyEditor);
807   RegisterPropertyEditor(TypeInfo(TPenStyle), nil, '', TPenStylePropertyEditor);
808   RegisterPropertyEditor(TypeInfo(TBrushStyle), nil, '', TBrushStylePropertyEditor);
809   RegisterPropertyEditor(TypeInfo(AnsiString), TFont, 'Name', TFontNamePropertyEditor);
810   RegisterPropertyEditor(TypeInfo(TFontCharset), nil, 'CharSet', TFontCharsetPropertyEditor);
811   RegisterPropertyEditor(TypeInfo(TImageIndex), TPersistent, 'ImageIndex', TImageIndexPropertyEditor);
812   RegisterPropertyEditor(TypeInfo(TImageIndex), TPersistent, 'OverlayImageIndex', TImageIndexPropertyEditor);
813   RegisterPropertyEditor(TypeInfo(TImageIndex), TPersistent, 'SelectedImageIndex', TImageIndexPropertyEditor);
814   RegisterPropertyEditor(TypeInfo(TImageIndex), TGridColumnTitle, 'ImageIndex', TGridImageIndexPropertyEditor);
815   RegisterPropertyEditor(TypeInfo(TImageIndex), TCustomGrid, 'ImageIndexSortAsc', TGridImageIndexPropertyEditor);
816   RegisterPropertyEditor(TypeInfo(TImageIndex), TCustomGrid, 'ImageIndexSortDesc', TGridImageIndexPropertyEditor);
817   RegisterPropertyEditor(ClassTypeInfo(TFont), nil,'',TFontPropertyEditor);
818   RegisterPropertyEditor(ClassTypeInfo(TGraphic), nil,'',TGraphicPropertyEditor);
819   RegisterPropertyEditor(ClassTypeInfo(TPicture), nil,'',TPicturePropertyEditor);
820   RegisterPropertyEditor(ClassTypeInfo(TBitmap), TSpeedButton,'Glyph', TButtonGlyphPropEditor);
821   RegisterPropertyEditor(ClassTypeInfo(TBitmap), TBitBtn,'Glyph', TButtonGlyphPropEditor);
822 
823 end.
824 
825