{********************************************************************} { } { Developer Express Visual Component Library } { ExpressEditors } { } { Copyright (c) 1998-2009 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 EXPRESSEDITORS 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 cxImageComboBox; {$I cxVer.inc} interface uses Windows, Messages, ComCtrls, {$IFDEF DELPHI6} Types, Variants, {$ENDIF} cxVariants, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls, Clipbrd, ImgList, cxClasses, cxGraphics, cxControls, cxContainer, cxDataStorage, cxDataUtils, cxEdit, cxDropDownEdit, cxTextEdit, cxFilterControlUtils; type { TcxImageComboBoxItem } TcxImageComboBoxItem = class(TCollectionItem) private FDescription: TCaption; FImageIndex: TImageIndex; FTag: TcxTag; FValue: Variant; function IsStoredValue: Boolean; function IsTagStored: Boolean; procedure SetDescription(const Value: TCaption); procedure SetImageIndex(const Value: TImageIndex); procedure SetValue(const AValue: Variant); public constructor Create(Collection: TCollection); override; procedure Assign(Source: TPersistent); override; published property Description: TCaption read FDescription write SetDescription; property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1; property Tag: TcxTag read FTag write FTag stored IsTagStored; property Value: Variant read FValue write SetValue stored IsStoredValue; end; { TcxImageComboBoxItems } TcxImageComboBoxItems = class(TOwnedCollection) private function GetItems(Index: Integer): TcxImageComboBoxItem; procedure SetItems(Index: Integer; const Value: TcxImageComboBoxItem); protected procedure InternalChanged; procedure Update(Item: TCollectionItem); override; public constructor Create(AOwner: TPersistent); function Add: TcxImageComboBoxItem; property Items[Index: Integer]: TcxImageComboBoxItem read GetItems write SetItems; default; end; { TcxImageComboBoxListBox } TcxCustomImageComboBox = class; TcxCustomImageComboBoxProperties = class; TcxImageComboBoxListBox = class(TcxComboBoxListBox) private FClientWidth: Integer; FHasScrollbar: Boolean; function GetEdit: TcxCustomImageComboBox; function GetProperties: TcxCustomImageComboBoxProperties; protected procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override; procedure MeasureItem(Index: Integer; var Height: Integer); override; procedure RecreateWindow; override; function GetImageRect(const R: TRect): TRect; function GetImages: TCustomImageList; function GetMaxItemWidth: Integer; virtual; property Edit: TcxCustomImageComboBox read GetEdit; property Properties: TcxCustomImageComboBoxProperties read GetProperties; public constructor Create(AOwner: TComponent); override; function GetHeight(ARowCount: Integer; AMaxHeight: Integer): Integer; override; function GetItemWidth(AIndex: Integer): Integer; override; end; { TcxImageComboBoxLookupData } TcxImageComboBoxLookupData = class(TcxComboBoxLookupData) private function GetList: TcxImageComboBoxListBox; protected function GetListBoxClass: TcxCustomEditListBoxClass; override; function GetItem(Index: Integer): string; override; function GetItemCount: Integer; override; property List: TcxImageComboBoxListBox read GetList; public procedure TextChanged; override; end; { TcxImageComboBoxViewData } TcxImageComboBoxViewData = class(TcxCustomDropDownEditViewData) private function GetProperties: TcxCustomImageComboBoxProperties; protected function InternalEditValueToDisplayText(AEditValue: TcxEditValue): string; override; function InternalGetEditConstantPartSize(ACanvas: TcxCanvas; AIsInplace: Boolean; AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo): TSize; override; function IsComboBoxStyle: Boolean; override; public procedure Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); override; procedure DisplayValueToDrawValue(const ADisplayValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); override; procedure EditValueToDrawValue(ACanvas: TcxCanvas; const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); override; property Properties: TcxCustomImageComboBoxProperties read GetProperties; end; { TcxImageComboBoxViewInfo } TcxImageAlign = (iaLeft, iaRight); TcxImageComboBoxViewInfo = class(TcxCustomTextEditViewInfo) protected procedure InternalPaint(ACanvas: TcxCanvas); override; public ImageRect: TRect; ShowDescriptions: Boolean; ImageAlign: TcxImageAlign; ImageIndex: TImageIndex; Images: TCustomImageList; procedure Offset(DX, DY: Integer); override; end; { TcxCustomImageComboBoxProperties } TcxCustomImageComboBoxProperties = class(TcxCustomComboBoxProperties) private FDefaultDescription: string; FDefaultImageIndex: TImageIndex; FImageAlign: TcxImageAlign; FImages: TCustomImageList; FImagesChangeLink: TChangeLink; FItems: TcxImageComboBoxItems; FLargeImages: TCustomImageList; FLargeImagesChangeLink: TChangeLink; FMultiLineText: Boolean; FShowDescriptions: Boolean; procedure ImagesChange(Sender: TObject); procedure LargeImagesChange(Sender: TObject); procedure SetDefaultDescription(const Value: string); procedure SetDefaultImageIndex(const Value: TImageIndex); procedure SetImageAlign(const Value: TcxImageAlign); procedure SetImages(Value: TCustomImageList); procedure SetItems(const Value: TcxImageComboBoxItems); procedure SetLargeImages(Value: TCustomImageList); procedure SetMultiLineText(const Value: Boolean); procedure SetShowDescriptions(const Value: Boolean); protected function FindItemByText(const AText: string): TcxImageComboBoxItem; function FindLookupText(const AText: string): Boolean; override; procedure FreeNotification(Sender: TComponent); override; function GetDisplayFormatOptions: TcxEditDisplayFormatOptions; override; class function GetLookupDataClass: TcxInterfacedPersistentClass; override; class function GetViewDataClass: TcxCustomEditViewDataClass; override; function HasDisplayValue: Boolean; override; procedure InternalGetImageComboBoxDisplayValue(AItem: TcxImageComboBoxItem; out AText: TCaption; out AImageIndex: TImageIndex; AAlwaysShowDescription: Boolean = False); virtual; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function CompareDisplayValues( const AEditValue1, AEditValue2: TcxEditValue): Boolean; override; function FindItemByValue(const AValue: Variant): TcxImageComboBoxItem; class function GetContainerClass: TcxContainerClass; override; function GetDisplayText(const AEditValue: TcxEditValue; AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; override; function GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; override; procedure GetImageComboBoxDisplayValue(const AEditValue: TcxEditValue; out AText: TCaption; out AImageIndex: TImageIndex); function GetSupportedOperations: TcxEditSupportedOperations; override; class function GetViewInfoClass: TcxContainerViewInfoClass; override; function IsEditValueValid(var AEditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override; procedure PrepareDisplayValue(const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; AEditFocused: Boolean); override; // !!! property DefaultDescription: string read FDefaultDescription write SetDefaultDescription; property DefaultImageIndex: TImageIndex read FDefaultImageIndex write SetDefaultImageIndex default -1; property ImageAlign: TcxImageAlign read FImageAlign write SetImageAlign default iaLeft; property Images: TCustomImageList read FImages write SetImages; property Items: TcxImageComboBoxItems read FItems write SetItems; property LargeImages: TCustomImageList read FLargeImages write SetLargeImages; property MultiLineText: Boolean read FMultiLineText write SetMultiLineText default False; property ShowDescriptions: Boolean read FShowDescriptions write SetShowDescriptions default True; end; { TcxImageComboBoxProperties } TcxImageComboBoxProperties = class(TcxCustomImageComboBoxProperties) published property Alignment; property AssignedValues; property ButtonGlyph; property ClearKey; property DefaultDescription; property DefaultImageIndex; property DropDownRows; property ImageAlign; property Images; property ImeMode; property ImeName; property ImmediateDropDown; property ImmediatePost; property ImmediateUpdateText; property Items; property LargeImages; property MultiLineText; property PopupAlignment; property PostPopupValueOnTab; property ReadOnly; property Revertable; property ShowDescriptions; property ValidateOnEnter; property OnButtonClick; property OnChange; property OnCloseQuery; property OnCloseUp; property OnEditValueChanged; property OnInitPopup; property OnPopup; property OnValidate; end; { TcxCustomImageComboBox } TcxCustomImageComboBox = class(TcxCustomComboBox) private function GetProperties: TcxCustomImageComboBoxProperties; function GetActiveProperties: TcxCustomImageComboBoxProperties; function GetLookupData: TcxImageComboBoxLookupData; procedure SetProperties(const Value: TcxCustomImageComboBoxProperties); protected function GetItemObject: TObject; override; function GetPopupWindowClientPreferredSize: TSize; override; function InternalGetEditingValue: TcxEditValue; override; function IsValidChar(AChar: Char): Boolean; override; function LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue; override; procedure SynchronizeDisplayValue; override; procedure UpdateDrawValue; override; property LookupData: TcxImageComboBoxLookupData read GetLookupData; public class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; procedure PrepareEditValue(const ADisplayValue: TcxEditValue; out EditValue: TcxEditValue; AEditFocused: Boolean); override; property ActiveProperties: TcxCustomImageComboBoxProperties read GetActiveProperties; property Properties: TcxCustomImageComboBoxProperties read GetProperties write SetProperties; end; { TcxImageComboBox } TcxImageComboBox = class(TcxCustomImageComboBox) private function GetActiveProperties: TcxImageComboBoxProperties; function GetProperties: TcxImageComboBoxProperties; procedure SetProperties(Value: TcxImageComboBoxProperties); public class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; property ActiveProperties: TcxImageComboBoxProperties read GetActiveProperties; published property Anchors; property AutoSize; property BeepOnEnter; property Constraints; property DragCursor; property DragKind; property DragMode; property EditValue; property Enabled; property ImeMode; property ImeName; property ItemIndex; property ParentColor; property ParentFont; property ParentShowHint; property PopupMenu; property Properties: TcxImageComboBoxProperties read GetProperties write SetProperties; property ShowHint; property Style; property StyleDisabled; property StyleFocused; property StyleHot; property TabOrder; property TabStop; property Visible; property OnClick; {$IFDEF DELPHI5} property OnContextPopup; {$ENDIF} property OnEditing; property OnEnter; property OnExit; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseMove; property OnMouseUp; end; { TcxFilterImageComboBoxHelper } TcxFilterImageComboBoxHelper = class(TcxFilterComboBoxHelper) public class function GetFilterEditClass: TcxCustomEditClass; override; class function GetSupportedFilterOperators( AProperties: TcxCustomEditProperties; AValueTypeClass: TcxValueTypeClass; AExtendedSet: Boolean = False): TcxFilterControlOperators; override; class procedure InitializeProperties(AProperties, AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); override; end; implementation uses Dialogs, Math, cxGeometry, cxButtons, cxEditConsts, cxEditUtils, cxScrollBar, cxLookAndFeelPainters, cxDWMApi; type TcxCustomTextEditAccess = class(TcxCustomTextEdit); { TcxImageComboBoxItem } constructor TcxImageComboBoxItem.Create(Collection: TCollection); var AImages: TCustomImageList; begin FValue := Null; // for D5 variants inherited Create(Collection); AImages := TcxCustomImageComboBoxProperties(TcxImageComboBoxItems(Collection).Owner).Images; if (AImages <> nil) and (AImages.Count >= Collection.Count) then FImageIndex := Collection.Count - 1 else FImageIndex := -1; end; function TcxImageComboBoxItem.IsStoredValue: Boolean; begin Result := not VarIsNull(FValue); end; function TcxImageComboBoxItem.IsTagStored: Boolean; begin Result := FTag <> 0; end; procedure TcxImageComboBoxItem.SetDescription(const Value: TCaption); begin if FDescription <> Value then begin FDescription := Value; TcxImageComboBoxItems(Collection).InternalChanged; end; end; procedure TcxImageComboBoxItem.SetImageIndex(const Value: TImageIndex); begin if FImageIndex <> Value then begin FImageIndex := Value; TcxImageComboBoxItems(Collection).InternalChanged; end; end; procedure TcxImageComboBoxItem.SetValue(const AValue: Variant); begin if not InternalVarEqualsExact(FValue, AValue) then begin FValue := AValue; TcxImageComboBoxItems(Collection).InternalChanged; end; end; procedure TcxImageComboBoxItem.Assign(Source: TPersistent); begin if Source is TcxImageComboBoxItem then with TcxImageComboBoxItem(Source) do begin Self.Description := Description; Self.ImageIndex := ImageIndex; Self.Tag := Tag; Self.Value := Value; end else inherited Assign(Source); end; { TcxImageComboBoxItems } function TcxImageComboBoxItems.GetItems(Index: Integer): TcxImageComboBoxItem; begin Result := TcxImageComboBoxItem(inherited Items[Index]); end; procedure TcxImageComboBoxItems.SetItems(Index: Integer; const Value: TcxImageComboBoxItem); begin inherited Items[Index] := Value; end; procedure TcxImageComboBoxItems.InternalChanged; begin Changed; end; procedure TcxImageComboBoxItems.Update(Item: TCollectionItem); begin with TcxCustomImageComboBoxProperties(Owner) do Changed; end; constructor TcxImageComboBoxItems.Create(AOwner: TPersistent); begin inherited Create(AOwner, TcxImageComboBoxItem); end; function TcxImageComboBoxItems.Add: TcxImageComboBoxItem; begin Result := TcxImageComboBoxItem(inherited Add); end; { TcxImageComboBoxListBox } constructor TcxImageComboBoxListBox.Create(AOwner: TComponent); begin inherited Create(AOwner); BorderStyle := bsNone; Style := lbOwnerDrawVariable; end; function TcxImageComboBoxListBox.GetHeight(ARowCount: Integer; AMaxHeight: Integer): Integer; var I, H: Integer; R: TRect; begin if Properties.MultiLineText then with TcxCustomImageComboBox(Edit) do begin R := GetPopupWindowOwnerControlBounds; FClientWidth := R.Right - R.Left; R := PopupWindow.ViewInfo.GetClientExtent; Dec(FClientWidth, R.Left + R.Right); end else FClientWidth := 0; Result := 0; for I := 0 to ARowCount - 1 do begin H := 0; MeasureItem(I, H); Inc(Result, H); end; if Properties.MultiLineText then begin FHasScrollbar := (Result > AMaxHeight) or (ARowCount < Items.Count); if FHasScrollbar then begin Dec(FClientWidth, GetScrollBarSize.cx); Result := 0; for I := 0 to ARowCount - 1 do begin H := 0; MeasureItem(I, H); Inc(Result, H); end; end; end; end; function TcxImageComboBoxListBox.GetItemWidth(AIndex: Integer): Integer; begin if Properties.MultiLineText then Result := 0 else Result := inherited GetItemWidth(AIndex); end; procedure TcxImageComboBoxListBox.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); var Flags: Longint; Data: string; AImages: TCustomImageList; R: TRect; AImageIndex: Integer; begin if not DoDrawItem(Index, Rect, State) then begin Canvas.FillRect(Rect); if (Index < Items.Count) and (Index > -1) then begin if Properties.MultiLineText then Flags := DrawTextBiDiModeFlags(DT_LEFT or DT_EXPANDTABS or DT_NOPREFIX or DT_WORDBREAK) else Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX); if not UseRightToLeftAlignment then Inc(Rect.Left, 2) else Dec(Rect.Right, 2); Data := Properties.Items[Index].Description; AImages := GetImages; if AImages <> nil then begin R := GetImageRect(Rect); AImageIndex := Properties.Items[Index].ImageIndex; if (AImageIndex > -1) and (AImageIndex < AImages.Count) then with R do AImages.Draw(Canvas.Canvas, Left + 1, (Bottom + Top - AImages.Height) div 2, AImageIndex, Enabled); if R.Left > Rect.Left then Rect.Right := R.Left; if R.Right < Rect.Right then Rect.Left := R.Right; end; if not IsRectEmpty(Rect) then begin SetBkMode(Handle, TRANSPARENT); DrawText(Canvas.Handle, PChar(Data), Length(Data), Rect, Flags); end; end; end; end; procedure TcxImageComboBoxListBox.MeasureItem(Index: Integer; var Height: Integer); var AData: string; AImages: TCustomImageList; W, H, AFlags: Integer; R: TRect; begin W := FClientWidth - 2; AImages := GetImages; if AImages <> nil then begin Dec(W, AImages.Width + 4); H := AImages.Height + 2; end else H := 0; if Properties.MultiLineText and (W > 0) then begin R := Rect(0, 0, W, H); AData := Properties.Items[Index].Description; AFlags := DT_LEFT or DT_EXPANDTABS or DT_NOPREFIX or DT_WORDBREAK or DT_CALCRECT; DrawText(Canvas.Handle, PChar(AData), Length(AData), R, AFlags); H := Max(H, R.Bottom - R.Top + 2); end else H := Max(Canvas.TextHeight('Wg') + 2, H); Height := H; if (Index >= 0) and Edit.IsOnMeasureItemEventAssigned then Edit.DoOnMeasureItem(Index, Canvas, Height); end; procedure TcxImageComboBoxListBox.RecreateWindow; begin InternalRecreateWindow; end; function TcxImageComboBoxListBox.GetImageRect(const R: TRect): TRect; var AImages: TCustomImageList; begin AImages := GetImages; if AImages <> nil then with Properties do begin Result := R; with Result do if ImageAlign = iaLeft then Right := Left + AImages.Width + 4 else Left := Right - AImages.Width - 4; end else Result := cxEmptyRect; end; function TcxImageComboBoxListBox.GetImages: TCustomImageList; begin Result := Properties.LargeImages; if Result = nil then Result := Properties.Images; end; function TcxImageComboBoxListBox.GetMaxItemWidth: Integer; var AImages: TCustomImageList; I, W, J: Integer; begin AImages := GetImages; if AImages <> nil then Result := AImages.Width + 8 else Result := 4; with Properties do begin J := Result; for I := 0 to Items.Count - 1 do begin W := Canvas.TextWidth(Items[I].Description) + J; if W > Result then Result := W; end; end; if Properties.DropDownRows < Items.Count then Inc(Result, GetScrollBarSize.cx); end; function TcxImageComboBoxListBox.GetEdit: TcxCustomImageComboBox; begin Result := TcxCustomImageComboBox(inherited Edit); end; function TcxImageComboBoxListBox.GetProperties: TcxCustomImageComboBoxProperties; begin Result := TcxCustomImageComboBox(Edit).ActiveProperties; end; { TcxImageComboBoxLookupData } function TcxImageComboBoxLookupData.GetListBoxClass: TcxCustomEditListBoxClass; begin Result := TcxImageComboBoxListBox; end; function TcxImageComboBoxLookupData.GetItem(Index: Integer): string; begin with TcxCustomImageComboBox(Edit).ActiveProperties do if (Index > -1) and (Index < Items.Count) then Result := Items[Index].Description else Result := '' end; function TcxImageComboBoxLookupData.GetItemCount: Integer; begin Result := TcxCustomImageComboBox(Edit).ActiveProperties.Items.Count; end; function TcxImageComboBoxLookupData.GetList: TcxImageComboBoxListBox; begin Result := TcxImageComboBoxListBox(inherited List); end; procedure TcxImageComboBoxLookupData.TextChanged; var AItem: TcxImageComboBoxItem; begin if TcxCustomImageComboBox(Edit).EditModeSetting then Exit; with TcxCustomImageComboBoxProperties(ActiveProperties) do AItem := FindItemByValue(Edit.EditValue); if AItem <> nil then InternalSetCurrentKey(AItem.Index) else InternalSetCurrentKey(-1); end; { TcxImageComboBoxViewData } procedure TcxImageComboBoxViewData.Calculate(ACanvas: TcxCanvas; const ABounds: TRect; const P: TPoint; Button: TcxMouseButton; Shift: TShiftState; AViewInfo: TcxCustomEditViewInfo; AIsMouseEvent: Boolean); var R: TRect; ATextOffset: Integer; begin inherited Calculate(ACanvas, ABounds, P, Button, Shift, AViewInfo, AIsMouseEvent); with TcxImageComboBoxViewInfo(AViewInfo) do begin ImageAlign := TcxCustomImageComboBoxProperties(Properties).ImageAlign; Images := TcxCustomImageComboBoxProperties(Properties).Images; ShowDescriptions := TcxCustomImageComboBoxProperties(Properties).ShowDescriptions; if IsInplace then R := TextRect else R := ClientRect; if Assigned(Images) then begin ImageRect := cxRectInflate(ClientRect, -cxTextOffset, 0); if IsInplace then ATextOffset := 2 * cxTextOffset else ATextOffset := cxTextOffset; with ImageRect do begin if cxRectWidth(ImageRect) > Images.Width then begin if ShowDescriptions then if ImageAlign = iaLeft then begin Right := Left + Images.Width; R.Left := Right + ATextOffset; end else begin Left := Right - Images.Width; R.Right := Left - ATextOffset; end else begin Left := Left + (cxRectWidth(ImageRect) - Images.Width) div 2; Right := Left + Images.Width; end; end else R.Left := R.Right; if cxRectHeight(ImageRect) > Images.Height then begin Top := Top + (cxRectHeight(ImageRect) - Images.Height) div 2; Bottom := Top + Images.Height; end; end; end; if not IsInplace then begin ClientRect := R; InflateRect(R, -cxTextOffset, -1); DrawSelectionBar := False; end; TextRect := R; if not ShowDescriptions then Text := ''; end; end; procedure TcxImageComboBoxViewData.EditValueToDrawValue(ACanvas: TcxCanvas; const AEditValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); var AText: string; ACaption: TCaption; AImageIndex: TImageIndex; begin PrepareSelection(AViewInfo); Properties.GetImageComboBoxDisplayValue(AEditValue, ACaption, AImageIndex); TcxImageComboBoxViewInfo(AViewInfo).ImageIndex := AImageIndex; AText := ACaption; DoOnGetDisplayText(AText); TcxImageComboBoxViewInfo(AViewInfo).Text := AText; end; procedure TcxImageComboBoxViewData.DisplayValueToDrawValue( const ADisplayValue: TcxEditValue; AViewInfo: TcxCustomEditViewInfo); var ACurrentKey: TcxEditValue; AItem: TcxImageComboBoxItem; ACaption: TCaption; AImageIndex: TImageIndex; begin if Edit = nil then Exit; ACurrentKey := TcxCustomImageComboBox(Edit).ILookupData.CurrentKey; if ACurrentKey = -1 then AItem := Properties.FindItemByValue(Edit.EditValue) else AItem := Properties.Items[ACurrentKey]; Properties.InternalGetImageComboBoxDisplayValue(AItem, ACaption, AImageIndex); TcxImageComboBoxViewInfo(AViewInfo).Text := ACaption; TcxImageComboBoxViewInfo(AViewInfo).ImageIndex := AImageIndex; end; function TcxImageComboBoxViewData.InternalEditValueToDisplayText( AEditValue: TcxEditValue): string; var AIndex: TImageIndex; ACaption: TCaption; begin Properties.GetImageComboBoxDisplayValue(AEditValue, ACaption, AIndex); Result := ACaption; end; function TcxImageComboBoxViewData.InternalGetEditConstantPartSize( ACanvas: TcxCanvas; AIsInplace: Boolean; AEditSizeProperties: TcxEditSizeProperties; var MinContentSize: TSize; AViewInfo: TcxCustomEditViewInfo): TSize; begin Result := inherited InternalGetEditConstantPartSize(ACanvas, AIsInplace, AEditSizeProperties, MinContentSize, AViewInfo); with TcxCustomImageComboBoxProperties(Properties) do begin if Assigned(Images) then begin if Images.Height > MinContentSize.cy then MinContentSize.cy := Images.Height; Result.cx := Result.cx + Images.Width + 5; end else Result.cx := Result.cx + 1; end; end; function TcxImageComboBoxViewData.IsComboBoxStyle: Boolean; begin Result := IsCompositionEnabled; end; function TcxImageComboBoxViewData.GetProperties: TcxCustomImageComboBoxProperties; begin Result := TcxCustomImageComboBoxProperties(FProperties); end; { TcxImageComboBoxViewInfo } procedure TcxImageComboBoxViewInfo.Offset(DX, DY: Integer); begin inherited Offset(DX, DY); OffsetRect(ImageRect, DX, DY); end; procedure TcxImageComboBoxViewInfo.InternalPaint(ACanvas: TcxCanvas); var R: TRect; begin if not RectVisible(ACanvas.Handle, Bounds) then Exit; inherited InternalPaint(ACanvas); if Assigned(Images) and (ImageIndex > -1) and (ImageIndex < Images.Count) then begin ACanvas.SaveClipRegion; try IntersectRect(R, ImageRect, BorderRect); ACanvas.SetClipRegion(TcxRegion.Create(R), roIntersect); if Transparent or IsCompositionEnabled and NativeStyle then Images.Draw(ACanvas.Canvas, ImageRect.Left, ImageRect.Top, ImageIndex, Enabled) else cxEditUtils.DrawGlyph(ACanvas, Images, ImageIndex, ImageRect, BackgroundColor, Enabled); finally ACanvas.RestoreClipRegion; end; end; end; { TcxCustomImageComboBoxProperties } constructor TcxCustomImageComboBoxProperties.Create(AOwner: TPersistent); begin inherited Create(AOwner); FShowDescriptions := True; FDefaultImageIndex := -1; FImageAlign := iaLeft; FItems := TcxImageComboBoxItems.Create(Self); DropDownListStyle := lsFixedList; FImagesChangeLink := TChangeLink.Create; FImagesChangeLink.OnChange := ImagesChange; FLargeImagesChangeLink := TChangeLink.Create; FLargeImagesChangeLink.OnChange := LargeImagesChange; end; destructor TcxCustomImageComboBoxProperties.Destroy; begin FImagesChangeLink.Free; FLargeImagesChangeLink.Free; FItems.Free; inherited Destroy; end; procedure TcxCustomImageComboBoxProperties.ImagesChange(Sender: TObject); begin Changed; end; procedure TcxCustomImageComboBoxProperties.LargeImagesChange(Sender: TObject); begin Changed; end; procedure TcxCustomImageComboBoxProperties.SetDefaultDescription( const Value: string); begin if FDefaultDescription <> Value then begin FDefaultDescription := Value; Changed; end; end; procedure TcxCustomImageComboBoxProperties.SetDefaultImageIndex( const Value: TImageIndex); begin if FDefaultImageIndex <> Value then begin FDefaultImageIndex := Value; Changed; end; end; procedure TcxCustomImageComboBoxProperties.SetImageAlign( const Value: TcxImageAlign); begin if FImageAlign <> Value then begin FImageAlign := Value; Changed; end; end; procedure TcxCustomImageComboBoxProperties.SetImages(Value: TCustomImageList); begin cxSetImageList(Value, FImages, FImagesChangeLink, FreeNotificator); end; procedure TcxCustomImageComboBoxProperties.SetLargeImages(Value: TCustomImageList); begin cxSetImageList(Value, FLargeImages, FLargeImagesChangeLink, FreeNotificator); end; procedure TcxCustomImageComboBoxProperties.SetItems( const Value: TcxImageComboBoxItems); begin FItems.Assign(Value); Changed; end; procedure TcxCustomImageComboBoxProperties.SetMultiLineText( const Value: Boolean); begin if FMultiLineText <> Value then begin FMultiLineText := Value; Changed; end; end; procedure TcxCustomImageComboBoxProperties.SetShowDescriptions( const Value: Boolean); begin if FShowDescriptions <> Value then begin FShowDescriptions := Value; Changed; end; end; function TcxCustomImageComboBoxProperties.FindItemByText(const AText: string): TcxImageComboBoxItem; var I: Integer; begin Result := nil; if ShowDescriptions then for I := 0 to Items.Count - 1 do if InternalCompareString(Items[I].Description, AText, False) then begin Result := Items[I]; Break; end; end; function TcxCustomImageComboBoxProperties.FindLookupText(const AText: string): Boolean; begin Result := FindItemByText(AText) <> nil; end; procedure TcxCustomImageComboBoxProperties.FreeNotification(Sender: TComponent); begin inherited FreeNotification(Sender); if Sender = FImages then FImages := nil; if Sender = FLargeImages then FLargeImages := nil; end; function TcxCustomImageComboBoxProperties.GetDisplayFormatOptions: TcxEditDisplayFormatOptions; begin Result := []; end; class function TcxCustomImageComboBoxProperties.GetLookupDataClass: TcxInterfacedPersistentClass; begin Result := TcxImageComboBoxLookupData; end; class function TcxCustomImageComboBoxProperties.GetViewDataClass: TcxCustomEditViewDataClass; begin Result := TcxImageComboBoxViewData; end; function TcxCustomImageComboBoxProperties.HasDisplayValue: Boolean; begin Result := False; end; procedure TcxCustomImageComboBoxProperties.InternalGetImageComboBoxDisplayValue( AItem: TcxImageComboBoxItem; out AText: TCaption; out AImageIndex: TImageIndex; AAlwaysShowDescription: Boolean = False); begin if AAlwaysShowDescription or ShowDescriptions then if AItem = nil then AText := DefaultDescription else AText := AItem.Description else AText := ''; if AItem = nil then AImageIndex := DefaultImageIndex else AImageIndex := AItem.ImageIndex; end; procedure TcxCustomImageComboBoxProperties.Assign(Source: TPersistent); begin if Source is TcxCustomImageComboBoxProperties then begin BeginUpdate; try inherited Assign(Source); with TcxCustomImageComboBoxProperties(Source) do begin Self.DefaultDescription := DefaultDescription; Self.DefaultImageIndex := DefaultImageIndex; Self.ImageAlign := ImageAlign; Self.Images := Images; Self.Items.Assign(Items); Self.LargeImages := LargeImages; Self.MultiLineText := MultiLineText; Self.ShowDescriptions := ShowDescriptions; end; finally EndUpdate end end else inherited Assign(Source); end; function TcxCustomImageComboBoxProperties.CompareDisplayValues( const AEditValue1, AEditValue2: TcxEditValue): Boolean; var AImageIndex1, AImageIndex2: TImageIndex; AText1, AText2: TCaption; begin GetImageComboBoxDisplayValue(AEditValue1, AText1, AImageIndex1); GetImageComboBoxDisplayValue(AEditValue2, AText2, AImageIndex2); Result := InternalCompareString(AText1, AText2, True) and ((Images = nil) or (AImageIndex1 = AImageIndex2)); end; function TcxCustomImageComboBoxProperties.FindItemByValue( const AValue: Variant): TcxImageComboBoxItem; var I: Integer; begin Result := nil; for I := 0 to Items.Count - 1 do with Items[I] do if VarEqualsExact(AValue, Value) then begin Result := Items[I]; Break; end; end; class function TcxCustomImageComboBoxProperties.GetContainerClass: TcxContainerClass; begin Result := TcxImageComboBox; end; function TcxCustomImageComboBoxProperties.GetDisplayText( const AEditValue: TcxEditValue; AFullText: Boolean = False; AIsInplace: Boolean = True): WideString; var ADisplayValue: TcxEditValue; begin PrepareDisplayValue(AEditValue, ADisplayValue, False); Result := ADisplayValue; end; function TcxCustomImageComboBoxProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; begin Result := evsValue; end; procedure TcxCustomImageComboBoxProperties.GetImageComboBoxDisplayValue( const AEditValue: TcxEditValue; out AText: TCaption; out AImageIndex: TImageIndex); begin InternalGetImageComboBoxDisplayValue(FindItemByValue(AEditValue), AText, AImageIndex); end; function TcxCustomImageComboBoxProperties.GetSupportedOperations: TcxEditSupportedOperations; begin Result := [esoEditing, esoFiltering, esoHorzAlignment, esoSorting, esoSortingByDisplayText]; if Buttons.Count > 0 then Include(Result, esoHotTrack); if ShowDescriptions then Include(Result, esoIncSearch); end; class function TcxCustomImageComboBoxProperties.GetViewInfoClass: TcxContainerViewInfoClass; begin Result := TcxImageComboBoxViewInfo; end; function TcxCustomImageComboBoxProperties.IsEditValueValid( var AEditValue: TcxEditValue; AEditFocused: Boolean): Boolean; begin Result := True; end; procedure TcxCustomImageComboBoxProperties.PrepareDisplayValue( const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; AEditFocused: Boolean); var AImageIndex: TImageIndex; AText: TCaption; begin InternalGetImageComboBoxDisplayValue(FindItemByValue(AEditValue), AText, AImageIndex, True); DisplayValue := AText; end; { TcxCustomImageComboBox } function TcxCustomImageComboBox.GetProperties: TcxCustomImageComboBoxProperties; begin Result := TcxCustomImageComboBoxProperties(FProperties); end; function TcxCustomImageComboBox.GetActiveProperties: TcxCustomImageComboBoxProperties; begin Result := TcxCustomImageComboBoxProperties(InternalGetActiveProperties); end; function TcxCustomImageComboBox.GetLookupData: TcxImageComboBoxLookupData; begin Result := TcxImageComboBoxLookupData(inherited LookupData); end; procedure TcxCustomImageComboBox.SetProperties(const Value: TcxCustomImageComboBoxProperties); begin FProperties.Assign(Value); end; function TcxCustomImageComboBox.IsValidChar(AChar: Char): Boolean; begin Result := IsTextChar(AChar); end; function TcxCustomImageComboBox.GetItemObject: TObject; begin Result := nil; end; function TcxCustomImageComboBox.GetPopupWindowClientPreferredSize: TSize; begin Result := inherited GetPopupWindowClientPreferredSize; if not ActiveProperties.MultiLineText then begin if (LookupData.ActiveControl <> nil) and (LookupData.ActiveControl is TcxImageComboBoxListBox) then with TcxImageComboBoxListBox(LookupData.ActiveControl) do Result.cx := Max(GetMaxItemWidth, Result.cx); end else begin Result.cx := 0; if LookupData <> nil then LookupData.List.RecreateWindow; end; end; function TcxCustomImageComboBox.InternalGetEditingValue: TcxEditValue; begin PrepareEditValue(Null, Result, True); end; function TcxCustomImageComboBox.LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue; begin if not VarEqualsExact(AKey, -1) then Result := ActiveProperties.Items[AKey].Value else Result := Null; end; procedure TcxCustomImageComboBox.SynchronizeDisplayValue; var APrevLookupKey: TcxEditValue; begin SaveModified; try APrevLookupKey := ILookupData.CurrentKey; LockClick(True); try ILookupData.TextChanged; finally LockClick(False); if (*ModifiedAfterEnter and *)not VarEqualsExact(APrevLookupKey, ILookupData.CurrentKey) then DoClick; end; finally RestoreModified; ResetOnNewDisplayValue; UpdateDrawValue; end; end; procedure TcxCustomImageComboBox.UpdateDrawValue; begin inherited UpdateDrawValue; SetInternalDisplayValue(ViewInfo.Text); end; class function TcxCustomImageComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxCustomImageComboBoxProperties; end; procedure TcxCustomImageComboBox.PrepareEditValue( const ADisplayValue: TcxEditValue; out EditValue: TcxEditValue; AEditFocused: Boolean); begin if VarEqualsExact(LookupData.CurrentKey, -1) then EditValue := Null else EditValue := ActiveProperties.Items[LookupData.CurrentKey].Value; end; { TcxImageComboBox } class function TcxImageComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass; begin Result := TcxImageComboBoxProperties; end; function TcxImageComboBox.GetActiveProperties: TcxImageComboBoxProperties; begin Result := TcxImageComboBoxProperties(InternalGetActiveProperties); end; function TcxImageComboBox.GetProperties: TcxImageComboBoxProperties; begin Result := TcxImageComboBoxProperties(FProperties); end; procedure TcxImageComboBox.SetProperties(Value: TcxImageComboBoxProperties); begin FProperties.Assign(Value); end; { TcxFilterImageComboBoxHelper } class function TcxFilterImageComboBoxHelper.GetFilterEditClass: TcxCustomEditClass; begin Result := TcxImageComboBox; end; class function TcxFilterImageComboBoxHelper.GetSupportedFilterOperators( AProperties: TcxCustomEditProperties; AValueTypeClass: TcxValueTypeClass; AExtendedSet: Boolean = False): TcxFilterControlOperators; begin Result := [fcoEqual, fcoNotEqual, fcoBlanks, fcoNonBlanks]; if AExtendedSet then Result := Result + [fcoInList, fcoNotInList]; end; class procedure TcxFilterImageComboBoxHelper.InitializeProperties(AProperties, AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); begin inherited InitializeProperties(AProperties, AEditProperties, AHasButtons); TcxImageComboBoxProperties(AProperties).DropDownListStyle := lsFixedList; TcxImageComboBoxProperties(AProperties).ImmediateDropDown := True; TcxImageComboBoxProperties(AProperties).ShowDescriptions := True; end; initialization GetRegisteredEditProperties.Register(TcxImageComboBoxProperties, scxSEditRepositoryImageComboBoxItem); FilterEditsController.Register(TcxImageComboBoxProperties, TcxFilterImageComboBoxHelper); finalization FilterEditsController.Unregister(TcxImageComboBoxProperties, TcxFilterImageComboBoxHelper); end.