{********************************************************************} { } { Developer Express Visual Component Library } { ExpressSkins Library } { } { Copyright (c) 2006-2008 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSSKINS AND ALL ACCOMPANYING } { VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {********************************************************************} unit dxSkinsdxLCPainter; {$I cxVer.inc} interface uses Windows, Classes, Controls, Graphics, cxGraphics, dxLayoutCommon, dxLayoutLookAndFeels, dxLayoutControl, cxLookAndFeels, cxClasses, dxSkinsLookAndFeelPainter, dxSkinsCore, cxLookAndFeelPainters; type { TdxLayoutSkinLookAndFeel } TdxLayoutSkinLookAndFeel = class(TdxLayoutStandardLookAndFeel) private FLookAndFeel: TcxLookAndFeel; FPainterData: TdxSkinLookAndFeelPainterInfo; function GetSkinNameAssigned: Boolean; function GetSkinName: TdxSkinName; function IsSkinNameStored: Boolean; procedure SetSkinNameAssigned(AValue: Boolean); procedure SetSkinName(const AValue: TdxSkinName); protected function ForceControlArrangement: Boolean; override; function GetInternalName: string; override; procedure SetInternalName(const AValue: string); override; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); procedure UpdateSkinInfo; property PainterData: TdxSkinLookAndFeelPainterInfo read FPainterData; public class function Description: String; override; constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetEmptyAreaColor: TColor; override; function GetGroupBorderWidth(AControl: TControl; ASide: TdxLayoutSide; AHasCaption: Boolean): Integer; override; function GetGroupPainterClass: TClass; override; function GetGroupViewInfoClass: TClass; override; function GetItemPainterClass: TClass; override; property LookAndFeel: TcxLookAndFeel read FLookAndFeel; published property SkinName: TdxSkinName read GetSkinName write SetSkinName stored IsSkinNameStored; property SkinNameAssigned: Boolean read GetSkinNameAssigned write SetSkinNameAssigned default False; end; { TdxLayoutGroupCaptionSkinPainter } TdxLayoutGroupCaptionSkinPainter = class(TdxLayoutGroupCaptionPainter) protected procedure BeforeDrawText; override; procedure DrawBackground; override; end; { TdxLayoutGroupSkinViewInfo } TdxLayoutGroupSkinViewInfo = class(TdxLayoutGroupStandardViewInfo) private function GetCaptionBorderSize: TRect; function IsSkinAvalaible: Boolean; protected function CalculateCaptionViewInfoBounds: TRect; override; function GetClientBounds: TRect; override; function GetColor: TColor; override; function GetFrameBounds: TRect; override; function GetIsTransparent: Boolean; override; function HasSkinBackground: Boolean; virtual; end; { TdxLayoutGroupSkinPainter } TdxLayoutGroupSkinPainter = class(TdxLayoutGroupStandardPainter) private procedure DrawBorderCaptionPart(ACanvas: TcxCanvas; const ABounds: TRect; ACaptionElement: TdxSkinElement); protected function GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; override; function GetPainerData(var AData: TdxSkinLookAndFeelPainterInfo): Boolean; function IsParentBackground: Boolean; virtual; procedure DrawBorders; override; procedure DrawCaption; override; procedure DrawItemsArea; override; public procedure Paint; override; end; { TdxLayoutItemCaptionSkinPainter } TdxLayoutItemCaptionSkinPainter = class(TdxLayoutItemCaptionPainter) protected procedure BeforeDrawText; override; procedure DrawBackground; override; end; { TdxLayoutItemSkinPainter } TdxLayoutItemSkinPainter = class(TdxLayoutItemPainter) protected function GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; override; function GetPainterData(var AData: TdxSkinLookAndFeelPainterInfo): Boolean; public procedure Paint; override; end; TdxLayoutItemViewInfoAccess = class(TdxLayoutItemViewInfo); TdxLayoutGroupViewInfoAccess = class(TdxLayoutGroupViewInfo); TdxLayoutControlViewInfoAccess = class(TdxLayoutControlViewInfo); implementation { TdxLayoutSkinLookAndFeel } constructor TdxLayoutSkinLookAndFeel.Create(AOwner: TComponent); begin inherited Create(AOwner); FLookAndFeel := TcxLookAndFeel.Create(Self); FLookAndFeel.OnChanged := LookAndFeelChanged; UpdateSkinInfo; end; destructor TdxLayoutSkinLookAndFeel.Destroy; begin FLookAndFeel.Free; inherited Destroy; end; procedure TdxLayoutSkinLookAndFeel.LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin UpdateSkinInfo; if lfvSkinName in AChangedValues then Changed; end; procedure TdxLayoutSkinLookAndFeel.UpdateSkinInfo; begin GetExtendedStylePainters.GetPainterData(LookAndFeel.SkinPainter, FPainterData); end; class function TdxLayoutSkinLookAndFeel.Description: String; begin Result := 'Skin'; end; function TdxLayoutSkinLookAndFeel.GetEmptyAreaColor: TColor; var AElement: TdxSkinColor; begin if PainterData <> nil then AElement := PainterData.LayoutControlColor else AElement := nil; if AElement = nil then Result := inherited GetEmptyAreaColor else Result := AElement.Value; if Result = clDefault then Result := clBtnFace; end; function TdxLayoutSkinLookAndFeel.GetGroupBorderWidth(AControl: TControl; ASide: TdxLayoutSide; AHasCaption: Boolean): Integer; var AGroupBox: TdxSkinElement; AFont: TFont; begin if PainterData <> nil then AGroupBox := PainterData.GroupBoxCaptionElements[cxgpTop] else AGroupBox := nil; if AGroupBox <> nil then begin AFont := GetGroupCaptionFont(AControl); if ASide in [sdTop, sdBottom] then begin Result := DLUToPixels(AFont, 4); if (ASide = sdTop) and AHasCaption then Inc(Result, VDLUToPixels(AFont, 11)); end else Result := DLUToPixels(AFont, 2); if AHasCaption then with AGroupBox.ContentOffset.Rect do Result := Top + Bottom + Result; end else Result := inherited GetGroupBorderWidth(AControl, ASide, AHasCaption); end; function TdxLayoutSkinLookAndFeel.GetGroupPainterClass: TClass; begin Result := TdxLayoutGroupSkinPainter; end; function TdxLayoutSkinLookAndFeel.GetGroupViewInfoClass: TClass; begin Result := TdxLayoutGroupSkinViewInfo; end; function TdxLayoutSkinLookAndFeel.GetItemPainterClass: TClass; begin Result := TdxLayoutItemSkinPainter; end; function TdxLayoutSkinLookAndFeel.ForceControlArrangement: Boolean; begin Result := True; end; function TdxLayoutSkinLookAndFeel.GetInternalName: string; begin Result := FLookAndFeel.SkinName; end; procedure TdxLayoutSkinLookAndFeel.SetInternalName(const AValue: string); var I: Integer; begin FLookAndFeel.SkinName := AValue; for I := 0 to UserCount - 1 do Users[I].LookAndFeelChanged; end; function TdxLayoutSkinLookAndFeel.IsSkinNameStored: Boolean; begin Result := SkinNameAssigned; end; function TdxLayoutSkinLookAndFeel.GetSkinName: TdxSkinName; begin Result := InternalName; end; procedure TdxLayoutSkinLookAndFeel.SetSkinName(const AValue: TdxSkinName); begin InternalName := AValue; end; function TdxLayoutSkinLookAndFeel.GetSkinNameAssigned: Boolean; begin Result := lfvSkinName in FLookAndFeel.AssignedValues end; procedure TdxLayoutSkinLookAndFeel.SetSkinNameAssigned(AValue: Boolean); begin if AValue then FLookAndFeel.AssignedValues := FLookAndFeel.AssignedValues + [lfvSkinName] else FLookAndFeel.AssignedValues := FLookAndFeel.AssignedValues - [lfvSkinName]; end; { TdxLayoutGroupCaptionSkinPainter } procedure TdxLayoutGroupCaptionSkinPainter.BeforeDrawText; begin Canvas.Font := ViewInfo.Font; Canvas.Font.Color := ViewInfo.TextColor; if ViewInfo.IsTextUnderlined then Canvas.Font.Style := Canvas.Font.Style + [fsUnderline]; Canvas.Brush.Style := bsClear; end; procedure TdxLayoutGroupCaptionSkinPainter.DrawBackground; begin end; { TdxLayoutGroupSkinViewInfo } function TdxLayoutGroupSkinViewInfo.CalculateCaptionViewInfoBounds: TRect; var ACaptionWidth: Integer; begin if IsSkinAvalaible then begin Result := BorderBounds[sdTop]; with GetCaptionBorderSize do begin Inc(Result.Top, Top); Dec(Result.Bottom, Bottom); end; ACaptionWidth := CaptionViewInfo.CalculateWidth; with Result do begin case Item.CaptionOptions.AlignHorz of taLeftJustify: begin Inc(Left, CaptionViewInfoOffset); Right := Left + ACaptionWidth; end; taRightJustify: begin Dec(Right, CaptionViewInfoOffset); Left := Right - ACaptionWidth; end; taCenter: begin Left := (Left + Right - ACaptionWidth) div 2; Right := Left + ACaptionWidth; end; end; Top := (Result.Bottom + Result.Top - CaptionViewInfo.CalculateHeight) div 2; end; end else Result := inherited CalculateCaptionViewInfoBounds; end; function TdxLayoutGroupSkinViewInfo.GetCaptionBorderSize: TRect; var ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; AGroupBoxCaption: TdxSkinElement; begin ASkinPainterInfo := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData; if ASkinPainterInfo <> nil then AGroupBoxCaption := ASkinPainterInfo.GroupBoxCaptionElements[cxgpTop] else AGroupBoxCaption := nil; if AGroupBoxCaption <> nil then Result := AGroupBoxCaption.ContentOffset.Rect else Result := cxEmptyRect; end; function TdxLayoutGroupSkinViewInfo.IsSkinAvalaible: Boolean; begin Result := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData <> nil; end; function TdxLayoutGroupSkinViewInfo.GetClientBounds: TRect; var ACaptionHeight: Integer; AGroupBox: TdxSkinElement; ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; begin ASkinPainterInfo := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData; if ASkinPainterInfo <> nil then AGroupBox := ASkinPainterInfo.GroupBoxElements[cxgpTop] else AGroupBox := nil; if AGroupBox <> nil then begin Result := Bounds; if HasBorder then begin ACaptionHeight := CaptionViewInfo.CalculateHeight; if ACaptionHeight <> 0 then with GetCaptionBorderSize do ACaptionHeight := ACaptionHeight + Top + Bottom; with AGroupBox.ContentOffset.Rect do begin Inc(Result.Left, Left); Inc(Result.Top, Top + ACaptionHeight); Dec(Result.Right, Right); Dec(Result.Bottom, Bottom); end; end; end else Result := inherited GetClientBounds; end; function TdxLayoutGroupSkinViewInfo.GetColor: TColor; var ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; ALayoutControl: TdxSkinColor; begin ALayoutControl := nil; ASkinPainterInfo := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData; if ASkinPainterInfo <> nil then ALayoutControl := ASkinPainterInfo.LayoutControlColor; if ALayoutControl = nil then Result := inherited GetColor else Result := ALayoutControl.Value; end; function TdxLayoutGroupSkinViewInfo.GetFrameBounds: TRect; begin Result := Bounds; Result.Top := BorderBounds[sdTop].Bottom; end; function TdxLayoutGroupSkinViewInfo.GetIsTransparent: Boolean; begin if IsSkinAvalaible then Result := HasSkinBackground else Result := inherited GetIsTransparent; end; function TdxLayoutGroupSkinViewInfo.HasSkinBackground: Boolean; begin Result := Group.ShowBorder; if not Result and (Group.Parent <> nil) and (ParentViewInfo is TdxLayoutGroupSkinViewInfo) then Result := TdxLayoutGroupSkinViewInfo(ParentViewInfo).HasSkinBackground else if Group.Parent = nil then Result := inherited GetIsTransparent; end; { TdxLayoutGroupSkinPainter } procedure TdxLayoutGroupSkinPainter.DrawBorders; var AGroupBox: TdxSkinElement; ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; begin AGroupBox := nil; if GetPainerData(ASkinPainterInfo) then AGroupBox := ASkinPainterInfo.GroupBoxElements[cxgpTop]; if AGroupBox = nil then inherited DrawBorders else with TdxLayoutGroupSkinViewInfo(ViewInfo) do begin if not IsParentBackground then AGroupBox.Draw(Canvas.Handle, FrameBounds); if not HasCaption then DrawBorderCaptionPart(Canvas, FrameBounds, ASkinPainterInfo.GroupBoxCaptionElements[cxgpTop]); end; end; procedure TdxLayoutGroupSkinPainter.DrawCaption; var ACaption: TdxSkinElement; ACaptionRect: TRect; ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; begin ACaption := nil; if GetPainerData(ASkinPainterInfo) then ACaption := ASkinPainterInfo.GroupBoxCaptionElements[cxgpTop]; if Assigned(ACaption) then with ViewInfo do begin ACaptionRect := Bounds; ACaptionRect.Bottom := FrameBounds.Top; ACaption.Draw(Canvas.Handle, ACaptionRect); end; inherited DrawCaption; end; procedure TdxLayoutGroupSkinPainter.DrawBorderCaptionPart(ACanvas: TcxCanvas; const ABounds: TRect; ACaptionElement: TdxSkinElement); var ACaptionRect: TRect; begin if ACaptionElement <> nil then begin ACanvas.SaveClipRegion; try ACaptionRect := ABounds; ACanvas.SetClipRegion(TcxRegion.Create(ACaptionRect), roIntersect); ACaptionRect.Bottom := ACaptionRect.Top + ACaptionElement.Size.cy; OffsetRect(ACaptionRect, 0, -ACaptionElement.Size.cy + 1); ACaptionElement.Draw(ACanvas.Handle, ACaptionRect); finally ACanvas.RestoreClipRegion; end; end; end; procedure TdxLayoutGroupSkinPainter.DrawItemsArea; var AContent: TdxSkinColor; ASkinPainterInfo: TdxSkinLookAndFeelPainterInfo; begin if not TdxLayoutGroupSkinViewInfo(ViewInfo).IsTransparent then begin AContent := nil; if GetPainerData(ASkinPainterInfo) then AContent := ASkinPainterInfo.LayoutControlColor; if AContent = nil then inherited DrawItemsArea else Canvas.FillRect(ViewInfo.ClientBounds, AContent.Value); end; end; function TdxLayoutGroupSkinPainter.GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; begin Result := TdxLayoutGroupCaptionSkinPainter; end; function TdxLayoutGroupSkinPainter.GetPainerData( var AData: TdxSkinLookAndFeelPainterInfo): Boolean; begin AData := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData; Result := AData <> nil; end; function TdxLayoutGroupSkinPainter.IsParentBackground: Boolean; begin with TdxLayoutGroupSkinViewInfo(ViewInfo) do Result := TdxLayoutControlViewInfoAccess(ContainerViewInfo).HasBackground; end; procedure TdxLayoutGroupSkinPainter.Paint; begin inherited Paint; with TdxLayoutGroupSkinViewInfo(ViewInfo) do if not IsTransparent then Canvas.FillRect(ClientBounds, LookAndFeel.GetEmptyAreaColor) end; { TdxLayoutItemSkinPainter } function TdxLayoutItemSkinPainter.GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; begin Result := TdxLayoutItemCaptionSkinPainter; end; function TdxLayoutItemSkinPainter.GetPainterData( var AData: TdxSkinLookAndFeelPainterInfo): Boolean; begin AData := TdxLayoutSkinLookAndFeel(LookAndFeel).PainterData; Result := AData <> nil; end; procedure TdxLayoutItemSkinPainter.Paint; begin with TdxLayoutItemViewInfoAccess(ViewInfo) do begin with TdxLayoutGroupViewInfoAccess(ParentViewInfo) do if not IsTransparent then Canvas.FillRect(Bounds, LookAndFeel.GetEmptyAreaColor); if HasControl and ControlViewInfo.OpaqueControl then Canvas.ExcludeClipRect(ControlViewInfo.ControlBounds); if HasControl then DrawControl; if HasCaption then DrawCaption; InternalDrawSelection; Canvas.ExcludeClipRect(Bounds); end; end; { TdxLayoutItemCaptionSkinPainter } procedure TdxLayoutItemCaptionSkinPainter.BeforeDrawText; begin Canvas.Font := ViewInfo.Font; Canvas.Font.Color := ViewInfo.TextColor; if ViewInfo.IsTextUnderlined then Canvas.Font.Style := Canvas.Font.Style + [fsUnderline]; Canvas.Brush.Style := bsClear; end; procedure TdxLayoutItemCaptionSkinPainter.DrawBackground; begin end; initialization dxLayoutLookAndFeelDefs.Register(TdxLayoutSkinLookAndFeel); finalization dxLayoutLookAndFeelDefs.Unregister(TdxLayoutStandardLookAndFeel); end.