unit EasyListview; // Version 1.7.0 // // The contents of this file are subject to the Mozilla Public License // Version 1.1 (the "License"); you maynot use this file except in compliance // with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ // // Alternatively, you may redistribute this library, use and/or modify it under the terms of the // GNU Lesser General Public License as published by the Free Software Foundation; // either version 2.1 of the License, or (at your option) any later version. // You may obtain a copy of the LGPL at http://www.gnu.org/copyleft/. // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the // specific language governing rights and limitations under the License. // // The initial developer of this code is Jim Kueneman // // Special thanks to the following in no particular order for their help/support/code // Danijel Malik, Robert Lee, Werner Lehmann, Alexey Torgashin, Milan Vandrovec, // Stanly Xu // // NOTES: // 1) If new properties are added to the TCollectionItems and published they // need to be manually written/read from the stream. The items are not automatically // saved to the DFM file. This was because mimicing TCollectionItem was not // practical do to the way the VCL was designed. //---------------------------------------------------------------------------- interface {$IFDEF TNTSUPPORT} // IMPORTANT - PLEASE READ then comment this line out. // If using TNT you MUST include the TNT package for your specific compiler in the // Requires section of this package. It may be possible to compile without doing // this but you WILL eventually have strange crashes in your application that will // be difficult to understand. The best way to do this in my opinion is to create // a new folder in the package install directory called "Delphi_TNT" (or CBuilder_TNT) // and copy all the files from the Delphi (or CBuilder) folder into it. Now open the // EasyListviewDx.dpk (or bpk) file in the "Delphi_TNT" (or CBuilder_TNT) based on your compiler // version in a text editor. In the "Requires" section add "TNTUnicodeVcl_Rx0", where // the "x" is the version of Delphi you are using. Open the dpk (bpk) file in your // IDE. Select the menu option Projects>Options>Directories/Conditionals>Conditional // and enter TNTSUPPORT. Compile the package, then open the EasyListviewDxD.dpk (or bpk) // and compile and press the Install button. // Now when you update the packages you won't have to redo all this. Just install // the update then compile the packages in the "Delphi_TNT" (or CBuilder_TNT) folders // an you are done. {$ENDIF} {$B-} {$I Compilers.inc} {$I ..\Include\Debug.inc} {$I Options.inc} {$I ..\Include\Addins.inc} {.$DEFINE GXDEBUG} {$IFDEF GXDEBUG} {$DEFINE LOADGXUNIT} {$ENDIF} {$IFDEF GXDEBUG_PAINT} {$DEFINE LOADGXUNIT} {$ENDIF GXDEBUG_PAINT} {$IFDEF GXDEBUG_HINT} {$DEFINE LOADGXUNIT} {$ENDIF GXDEBUG_HINT} uses {$IFDEF COMPILER_9_UP} Types, // This MUST come before Windows {$ENDIF} {$IFDEF COMPILER_6_UP} Variants, {$ENDIF} Windows, Messages, SysUtils, Classes, Graphics, Controls, {$IFDEF LOADGXUNIT} DbugIntf, {$ENDIF LOADGXUNIT} {$IFDEF COMPILER_7_UP} Themes, UxTheme, {$ELSE} {$IFDEF USETHEMES} TmSchema, UxTheme, {$ENDIF} {$ENDIF} ExtCtrls, Forms, ImgList, CommCtrl, ActiveX, Menus, StdCtrls, {$IFDEF COMPILER_6_UP} RTLConsts, {$ELSE} Consts, {$ENDIF} {$IFDEF SpTBX} TBX, SpTBXItem, {$ENDIF} {$IFDEF TNTSUPPORT} TntStdCtrls, {$ENDIF} EasyLVResources, MPCommonUtilities, MPShellTypes, MPDataObject, MPCommonObjects, MPThreadManager, EasyTaskPanelForm; {$R EasyRes.res} const EGT_FIRSTLETTER = $FFFF; IID_IEasyCellEditor = '{A1686E7E-7F39-4BD4-BE1F-9C20D7BC6EA0}'; IID_IEasyCellEditorSink = '{C0AAA3C0-AC98-43C8-8D9A-376A3F64FAD2}'; IID_IEasyCaptions = '{6C838C0E-22A5-48D4-80C6-E266E950D3CF}'; IID_IEasyCaptionsEditable = '{F1403B00-7163-4FB7-804F-1A5500CD980A}'; IID_IEasyImageList = '{298932FB-A0AE-4A0A-BE34-A782743A0579}'; IID_IEasyStateImageList = '{F0202D63-92A7-4C2F-9CA4-CBDE4DE0ED30}'; IID_IEasyImages = '{20C419F5-F3DD-40C4-8526-88322E182C49}'; IID_IEasyImagesEditable = '{DC580B13-1D19-46BB-885F-FC5CE9B2BE66}' ; IID_IEasyThumbnail = '{F9CA8297-0CB3-4C47-905F-3D1497C4FC4D}'; IID_IEasyCustomImage = '{00260055-6915-43B5-9D43-379E7F61EEA9}'; IID_IEasyDetails = '{AE1D21EB-BA52-4C24-9EB1-B35733299489}'; IID_IEasyDetailsEditable = '{BBD853F9-D803-4478-B5A8-EE02FF47DC80}'; IID_IEasyChecks = '{E8820F40-2EE3-4718-B54A-39318D2D1232}'; IID_IEasyNotficationSink = '{E4F0D3DE-B2BD-4EC0-B24B-8A9B85B23A63}'; IID_IEasyNotifier = '{F10150F9-17E3-43B6-8C05-33283FF1B14E}'; IID_IEasyCompare = '{0761D4F5-D451-4A6D-BFDC-B3000FFD0299}'; IID_IEasyDividerPersist = '{EE6C3C89-7FAE-46CD-AD30-6954B4308721}'; IID_IEasyGroupKey = '{2B87BB19-A133-4D43-9164-AC456747EB19}'; IID_IEasyGroupKeyEditable = '{26EFE2C6-2DE2-4795-94E3-0DB0CAA38B09}'; // EASYLISTVIEW_STREAM_VERSION = 4; EASYLISTVIEW_STREAM_VERSION = 5; // Fixed bug in Streaming any other types then TEasyXXXXStored STREAM_ID_KEY = $CEFEFF; _AUTOSCROLLDELAY = 500; // 500 ms _AUTOSCROLLTIME = 50; // ms CURSOR_VHEADERSPLIT = 'VEASYHEADERSPLIT'; BITMAP_DEFAULTGROUPEXPANDED = 'DEFAULTEXPANDED'; BITMAP_DEFAULTGROUPCOLLAPSED = 'DEFAULTCOLLAPSED'; BITMAP_SORTARROWUP = 'SORTARROWUP'; BITMAP_SORTARROWDOWN = 'SORTARROWDOWN'; BITMAP_DEFAULTColumnGLYPHS = 'ColumnGLYPHS'; BITMAP_DEFAULTColumnGLYPHSBKGND = $00FF00FF; SELECTION_OFFSET = 0.15; // The selection rectangle will select an item +/- x% of the Caption width (like M$ Listview) WM_HOOKAPPACTIVATE = WM_APP + 204; WM_EDITORRESIZE = WM_APP + 205; WM_TABMOVEFOCUS = WM_APP + 206; RESIZEHITZONEMARGIN = 4; // LABEL_MARGIN = 2; crVHeaderSplit = 768; DEFAULT_GROUP_NAME = 'Default Group'; // group default name used if a first group is automatically created EASYLISTVIEW_HEADER_CLIPFORMAT = 'EasyListview.Header'; // Magic, mystical stuff for CBuilder (*$HPPEMIT 'namespace Easylistview {'*) {$HPPEMIT 'class DELPHICLASS TEasyItem;'} {$HPPEMIT 'class DELPHICLASS TEasyGroup;'} {$HPPEMIT 'class DELPHICLASS TEasyColumn;'} {$HPPEMIT 'struct TGroupSortInfoRec;'} {$HPPEMIT '__interface IEasyNotificationSink;'} (*$HPPEMIT '}'*) type TCustomEasyListview = class; TEasyItems = class; TEasyItem = class; TEasyItemInterfaced = class; TEasyViewItem = class; TEasyGroups = class; TEasyGroup = class; TEasyViewGroup = class; TEasyColumns = class; TEasyColumn = class; TEasyCollectionItem = class; TCustomEasyDragManagerBase = class; TEasyCellSize = class; TEasyHeader = class; TEasyCollection = class; TEasyPaintInfoBasic = class; TEasyHintInfo = class; TEasyOLEDragManager = class; TEasyHotTrackManager = class; TEasyViewColumn = class; TEasyHeaderDragManager = class; TEasySortManager = class; TEasyAlphaBlender = class; TEasyPaintInfoBaseGroup = class; TEasyColumnStored = class; TEasyBaseEditor = class; TEasyCollectionItemClass = class of TEasyCollectionItem; TEasyViewItemClass = class of TEasyViewItem; TEasyViewColumnClass = class of TEasyViewColumn; TEasyViewGroupClass = class of TEasyViewGroup; TEasyGridGroupClass = class of TEasyGridGroup; TEasyGroupClass = class of TEasyGroup; TEasyItemClass = class of TEasyItem; TEasyColumnClass = class of TEasyColumn; TEasyColumnStoredClass = class of TEasyColumnStored; TItemNextEnum = function(Item: TEasyItem): TEasyItem of object; TItemEnumFirstLast = function: TEasyItem of object; TRectArray = array of TRect; TCommonMouseButtons = set of TCommonMouseButton; TEasyItemArray = array of TEasyItem; TEasyGroupArray = array of TEasyGroup; TEasyColumnArray = array of TEasyColumn; TEasyQueryDragResult = ( eqdrContinue, // The drag drop loop should contine eqdrQuit, // The drag drop loop should end eqdrDrop // The drag drop loop should drop the object where it is ); TEasyCheckType = ( ectNone, // No Checks ettNoneWithSpace, // No Checks but leave the space for the checkbox ectBox, // Square Checkbox type checkbox ectRadio // Round Radio button type checkbox ); TEasyListStyle = ( elsIcon, // The Listview's Large Icon Mode elsSmallIcon, // The Listview's Small Icon Mode elsList, // The Listview's List Mode elsReport, // The Listview's Report (Details) Mode elsThumbnail, // The Listview's Thumbnail Mode elsTile, // The Listview's Tile Mode elsFilmStrip, // The Listview's FilmStrip Mode elsGrid // The Listview's Grid Mode ); TEasyGroupMarginEdge = ( egmeBackground, // Background of the entire Group egmeTop, // Header of a Group egmeBottom, // Footer of a Group egmeLeft, // Left Margin area of a Group egmeRight, // Right Margin area of a Group egmeForeground // Foreground of the entire Group ); TEasyHeaderType = ( ehtHeader, // Report view Header ehtFooter // Report view Footer ); TEasyHeaderButtonStyle = ( ehbsThick, // "Normal" raised button ehbsFlat, // Flat style button ehbsPlate, // Plate style button ehbsThemed // Draw using current Activation Context theme ); TEasyHeaderImagePosition = ( ehpLeft, // The image is to the left of the Text ehpTop, // The image is to the Top of the Text ehpRight, // The image is to the Right of the Text ehpBottom // The image is to the Bottom of the Text ); TEasySortDirection = ( esdNone, esdAscending, // The sort is ascending esdDescending // The sort is descending ); TEasySortGlyphAlign = ( esgaLeft, // Column SortGlpyh placed to left of Caption esgaRight // Column SortGlpyh placed to right of Caption ); TEasyDragType = ( edtOLE, // OLE Dragging edtVCL // VCL Dragging ); TEasySelectionType = ( ecstSelect, // Select all objects ecstUnSelect, // UnSelect all objects ecstInvert // Invert the selection state of objects ); TEasyColumnHitTestInfo = ( ectOnCheckbox, // Hit in the Checkbox ectOnIcon, // Hit the icon ectOnLabel, // Hit the Label ectOnText // Hit in the current text in the label area ); TEasyColumnHitTestInfoSet = set of TEasyColumnHitTestInfo; TEasyHitInfoColumn = packed record Column: TEasyColumn; // The object hit HitInfo: TEasyColumnHitTestInfoSet; // Details of the hit end; TEasyGroupHitTestInfo = ( egtOnBand, // Hit the colored band egtOnCheckbox, // Hit in the Checkbox egtOnExpandButton, // Hit the ExpandButton egtOnIcon, // Hit the icon egtOnLabel, // Hit the Label egtOnText, // Hit in the current text in the label area egtOnHeader, // Hit in the header of the group egtOnFooter, // Hit in the footer of the group egtOnLeftMargin, // Hit in the Left Margin of the group egtOnRightMargin // Hit in the Right Margin of the group ); TEasyGroupHitTestInfoSet = set of TEasyGroupHitTestInfo; TEasyDefaultWheelScroll = ( edwsHorz, // Mouse Wheel scrolls horizontal by default, vertical with shift pressed edwsVert // Mouse Wheel scrolls vertical by default, horizontal with shift pressed ); TEasyHitInfoGroup = packed record Group: TEasyGroup; // The object hit HitInfo: TEasyGroupHitTestInfoSet; // Details of the hit end; TEasyItemHitTestInfo = ( ehtStateIcon, // Hit the state icon ehtOnIcon, // Hit the icon ehtOnLabel, // Hit the label, the area available for the Text ehtOnClickSelectBounds, // Hit the area defined as a selection area for a click ehtOnDragSelectBounds, // Hit the area defined as a selection area for a drag select ehtOnText, // Hit the area in the label that contains text ehtOnCheck, // Hit the area where the check box is drawn ehtOnEdit // Hit the area where the edit is started for the item ); TEasyItemHitTestInfoSet = set of TEasyItemHitTestInfo; TEasyHitInfoItem = packed record Item: TEasyItem; Group: TEasyGroup; // The group the object is in Column: TEasyColumn; // The the Column hit (if applicable) HitInfo: TEasyItemHitTestInfoSet; // Details of the hit end; // CAUTION ADD NEW STATES TO END TO PRESERVE STREAMING TEasyStorageObjectState = ( esosChecked, // The object is checked esosCheckPending, // The object has a check pending, the mouse has been pressed in the check area but not yet released esosCheckHover, // The object has the mouse hovering over the checkbox (matters mostly themed) esosClicking, // The object is being "clicked" esosCut, // The object is being "cut" esosDestroying, // The object is being destroyed esosHilighted, // The object is currently hilighted, for an item this mean drop hilighed for a Column this means hot track hilighed esosEnabled, // The object is enabled esosFocused, // The object is focused, i.e. it will take the keyboard input esosInitialized, // The object has been initialized esosSelected, // The object is selected, i.e. it will be included for an operation on it esosVisible, // The object is currently visible esosHotTracking, // The object is currently in a hot track state esosBold, // The object is in a Bold state esosDropTarget, // The object is hilighted as a drop target esosGhosted // The object image is drawn "ghosted" (blended with background) ); TEasyStorageObjectStates = set of TEasyStorageObjectState; TEasyGroupsState = ( egsRebuilding // GroupManager is rebuild the item layout ); TEasyGroupsStates = set of TEasyGroupsState; TEasySelectHitType = ( eshtClickSelect, // Test for a hit based on a mouse click eshtDragSelect // Test for a hit based on a drag rectangle ); TEasyCellRectType = ( ertBounds, // The bounds of the item minus the border ertIcon, // The bounds of the icon image ertLabel, // The bounds of the area dedicated to the text (will be static based on grid) ertClickSelectBounds, // The bounds of the area dedicated to a click selection (usually the Text area) ertDragSelectBounds, // The bounds of the area dedicated to a drag selection (depends on the view) ertText, // The bounds of the text for the item (will be dynamic based on current text) ertFullText // The bounds of the actual Complete text for the item independant of current state of control/item ); TEasyImageSize = ( eisSmall, // Paint Small Images eisLarge, // Paint Large Images eisExtraLarge // Paint JumboImages ); TEasyImageKind = ( eikNormal, // Normal image eikOverlay, // Overlay for the Normal image eikState // State image ); TEasyDragManagerState = ( edmsDragging, // The Drag Manager is in the middle of a drag operation edmsAutoScrolling // The Drag Manager is autoscrolling during a draw operation ); TEasyDragManagerStates = set of TEasyDragManagerState; TEasyControlState = ( ebcsLButtonDown, // The Left Mouse Button is down ebcsRButtonDown, // The Right Mouse Button is down ebcsMButtonDown, // The Middle Mouse Button is down ebcsScrollButtonDown, // The scroll wheel is down ebcsDragPending, // The mouse is down and we are ready to check for a drag of an object ebcsDragging, // The control is in the middle of a dragging operation ebcsVCLDrag, // The drag operation is a VCL drag ebcsDragSelectPending, // The mouse is down and we are ready to check for a drag select ebcsDragSelecting, // The control is in a drag selecting mode ebcsThemesLoaded, // The control has loaded themes if avaiable ebcsCheckboxClickPending, // The mouse is down over a checkbox and the box now has the attention of the mouse ebcsGroupExpandPending, ebcsHeaderCapture, // The Header area has captured the mouse ebcsScrolling, // The control is scrolling ebcsOLERegistered, // Registered for OLE Drag and Drop ebcsCancelContextMenu // A right button drag drop should not show the context menu ); TEasyControlStates = set of TEasyControlState; TEasyHeaderState = ( ehsMouseCaptured, // The Header captured the mouse (drag column/row; resize column/row) ehsResizing, // One of the columns/headers is resizing ehsDragging, // One of the columns/headers is being dragged ehsDragPending, ehsClickPending, // One of the columns/headers was pressed and the mouse is being dragged around ehsCheckboxClickPending, ehsResizePending, ehsLButtonDown, ehsRButtonDown, ehsMButtonDown ); TEasyHeaderStates = set of TEasyHeaderState; TEasyItemState = ( eisTextRectCached ); TEasyItemStates = set of TEasyItemState; TEasyRectArrayObject = packed record LabelRect, // The bounds of the area dedicated to the text // (will be static based on grid) IconRect, // The bounds of the icon image TextRect, // The bounds of the text for the item (will be // dynamic based on current text) // If TextRects is used then this is the Union of all // the TextRects // It will be calculated from LabelRect -2 pixels so that // a Frame and a Focus Rect may be drawn around it and // not extend past the Label Rect CheckRect: TRect; // The rectangle used for the Checkbox of an item BoundsRect, // The bounds of the item minus the border ClickSelectBoundsRect, // The bounds of the area dedicated to a click // selection (may be possible the area is not // definable by a simple rectangle) DragSelectBoundsRect, // The bounds of the area dedicated to a drag // selection (may be possible the area is not // definable by a simple rectangle) FullTextRect: TRect; // The bounds of the largest rect of text that // can be shown (Icon view when item has focus the // entire text is shown, overlapping other items) SelectionRect: TRect; // The bounds of the area that is painted in the // hilighted selection color FullFocusSelRect: TRect; // The bounds of the largest rect of selection that // can be shown (Icon view when item has focus the // entire text is shown, overlapping other items) FocusChangeInvalidRect: TRect; // The Rectangle to Invalidate(True) if the item // changes focus or selection EditRect: TRect; // The rectangle used for the editor in Edit Mode SortRect: TRect; // The rectangle used for the Sort Glyphs StateRect: TRect; // The rectangle used for state images TextRects: TRectArray; // Text rectangles for Details ExpandButtonRect, // The rectangle available in the group for the Expand Button (Groups Only) BandRect: TRect; // The rectangle available in the group for the Band stripe (Groups Only) BackGndRect: TRect; // The background of the group minus the Margin area, includes the Border (Groups Only) GroupRect: TRect; // The entire space the group occupies (Groups Only) DropDownArrow: TRect; // The DropDown Button for Columns (Columns Only) end; TEasyRectArrayObjectArray = array of TEasyRectArrayObject; TEasyMakeVisiblePos = ( emvTop, // Make visible with the top of the Client Window emvMiddle, // Make visible with the middle of the Client Window emvBottom, // Make visible with the bottom of the Client Window emvAuto // Make visible and scroll based on if the item is above or below the current client window ); TEasySearchDirection = ( esdForward, esdBackward ); TEasyAdjacentCellDir = ( acdLeft, // The cell that is to the left of a particular cell acdRight, // The cell that is to the right of a particular cell acdUp, // The cell that is above a particular cell acdDown, // The cell that is below of a particular cell acdPageDown, // The cell that is a single page down from a particular cell acdPageUp // The cell that is a single page up from a particular cell ); TEasyGridLayout = ( eglHorz, // The Grid is a Horizontal grid (scrolls horz sized to fit vert) eglVert, // The Grid is a Vertical grid (scrolls vert, sized to fit horz) eglGrid // The Grid can scroll either way (may not fit client window either way) ); TEasyHintType = ( ehtText, // Shows the hint in the passed text parameter ehtToolTip, // Shows entire caption text if it does not fit in the assigned caption area ehtCustomDraw // The hint will callback when it needs drawing ); PEasyHintInfoRec = ^TEasyHintInfoRec; // The actual record is below due to a BDS C++ bug in generating the hpp file TEasySortAlgorithm = ( esaQuickSort, esaBubbleSort, esaMergeSort ); TEasyIncrementalSearchState = ( eissTimerRunning, // The Search timeout timer is running eissSearching // Currently in a Search mode ); TEasyIncrementalSearchStates = set of TEasyIncrementalSearchState; TCoolIncrementalSearchStart = ( eissStartOver, // Always start a search from the beginning of the list eissLastHit, // Start search from the last node found in the incremental search eissFocusedNode // Start search from current focused node ); TEasyIncrementalSearchItemType = ( eisiAll, // Search All items in list eisiInitializedOnly, // Search only items with their initialized property set, this will include collapsed groups but not invisible groups eisiVisible // Search only items with their visible property set, this will include collapsed groups but not invisible groups ); TEasyIncrementalSearchDir = ( eisdForward, // Search Forward in the list eisdBackward // Search Backward in the list ); TEasyNextItemType = ( enitAny, enitVisible, enitInitialized, enitVisibleInExpandedGroup, enitEditable // Implies visible ); TEasyScrollbarDir = ( esdVertical, esdHorizontal, esdBoth ); TEasyHotTrackState = ( ehsEnable, // object becoming a hot track target ehsDisable // object losing a hot track status ); TEasyHotTrackRectItem = ( htiIcon, // Hot track is defined on the image htiText, // Hot track is defined on the Text htiAnyWhere // Hot track is defined on the entire cell ); TEasyHotTrackRectItems = set of TEasyHotTrackRectItem; TEasyHotTrackRectGroup = ( htgIcon, // Hot track is defined on the image htgText, // Hot track is defined on the Text htgTopMargin, // Hot track is defined on the Top Group Margin htgBottomMargin,// Hot track is defined on the Bottom Group Margin htgLeftMargin, // Hot track is defined on the Left Group Margin htgRightMargin, // Hot track is defined on the Right Group Margin htgAnyWhere // Hot track is defined on the entire cell ); TEasyHotTrackRectGroups = set of TEasyHotTrackRectGroup; TEasyHotTrackRectColumn = ( htcIcon, // Hot track is defined on the image htcText, // Hot track is defined on the Text htcAnyWhere // Hot track is defined on the entire cell ); TEasyHotTrackRectColumns = set of TEasyHotTrackRectColumn; // **************************************************************** // Intefaces that EasyListview is aware of such that user data may implement these // interfaces to present the data necessary for the control // **************************************************************** // Implements the read only Caption for the Control IEasyCaptions = interface(IUnknown) [IID_IEasyCaptions] function GetCaption(Column: Integer): Variant; property Captions[Column: Integer]: Variant read GetCaption; end; // Implements the Caption for the Control IEasyCaptionsEditable = interface(IEasyCaptions) [IID_IEasyCaptionsEditable] function SetCaption(Column: Integer; const Value: Variant): Boolean; end; // Implements a custom ImageList on a per item/column basis for the Control IEasyImageList = interface(IUnknown) [IID_IEasyImageList] function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; property ImageList[Column: Integer; IconSize: TEasyImageSize]: TCustomImageList read GetImageList; end; // Implements a custom State ImageList on a per item/column basis for the Control IEasyStateImageList = interface(IUnknown) [IID_IEasyStateImageList] function GetImageList(Column: Integer): TCustomImageList; property ImageList[Column: Integer]: TCustomImageList read GetImageList; end; // Implements the read only ImageIndex for the Control IEasyImages = interface(IUnknown) [IID_IEasyImages] function GetImageIndex(Column: Integer; ImageKind: TEasyImageKind): Integer; property ImageIndexes[Column: Integer; ImageKind: TEasyImageKind]: Integer read GetImageIndex; end; // Implements the ImageIndex for the Control IEasyImagesEditable = interface(IEasyImages) [IID_IEasyImagesEditable] procedure SetImageIndex(Column: Integer; ImageKind: TEasyImageKind; const Value: Integer); property ImageIndexes[Column: Integer; ImageKind: TEasyImageKind]: Integer read GetImageIndex write SetImageIndex; end; // Implements the Thumbnail (Bitmap) for the Control IEasyThumbnail = interface(IUnknown) [IID_IEasyThumbnail] procedure ThumbnailDraw(ACanvas: TCanvas; ViewportRect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); end; IEasyCustomImage = interface(IUnknown) [IID_IEasyCustomImage] procedure CustomDrawn(Column: TEasyColumn; var IsCustom: Boolean); procedure DrawImage(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); procedure GetSize(Column: TEasyColumn; var ImageW, ImageH: Integer); end; // Implements the Tile Details for the Control // Points to what Column to get the detail from IEasyDetails = interface(IUnknown) [IID_IEasyDetails] function GetDetailCount: Integer; function GetDetail(Line: Integer): Integer; // Return the Column to be used as the detail for the given line property Detail[Line: Integer]: Integer read GetDetail; property DetailCount: Integer read GetDetailCount; end; IEasyDetailsEditable = interface(IEasyDetails) [IID_IEasyDetailsEditable] procedure SetDetail(Line: Integer; Value: Integer); procedure SetDetailCount(Value: Integer); property Detail[Line: Integer]: Integer read GetDetail write SetDetail; property DetailCount: Integer read GetDetailCount write SetDetailCount; end; // Implements the CheckState for the Control IEasyChecks = interface(IUnknown) [IID_IEasyChecks] function GetChecked(Column: Integer): Boolean; procedure SetChecked(Column: Integer; const Value: Boolean); property Checked[Column: Integer]: Boolean read GetChecked write SetChecked; end; IEasyGroupKey = interface(IUnknown) [IID_IEasyGroupKey] function GetKey(FocusedColumn: Integer): LongWord; property Key[FocusedColumn: Integer]: LongWord read GetKey; // Uniquely identifies the item in a particular group end; IEasyGroupKeyEditable = interface(IEasyGroupKey) [IID_IEasyGroupKeyEditable] procedure SetKey(FocusedColumn: Integer; Value: LongWord); property Key[FocusedColumn: Integer]: LongWord read GetKey write SetKey; end; IEasyNotificationSink = interface(IUnknown) [IID_IEasyNotficationSink] procedure InvalidateItem(ImmediateRefresh: Boolean); procedure UnRegister; end; IEasyNotifier = interface(IUnknown) [IID_IEasyNotifier] procedure OnRegisterNotify(const ANotifier: IEasyNotificationSink); procedure OnUnRegisterNotify(const ANotifier: IEasyNotificationSink); end; IEasyCompare = interface [IID_IEasyCompare] function Compare(const Data: IUnknown; Column: TEasyColumn): Integer; end; // Interface for the EasyControl to communicate with a Cells Editor IEasyCellEditor = interface(IUnknown) [IID_IEasyCellEditor] function AcceptEdit: Boolean; function GetHandle: HWnd; function GetModified: Boolean; procedure ControlWndHookProc(var Message: TMessage); procedure Hide; procedure Initialize(AnItem: TEasyItem; Column: TEasyColumn); procedure Finalize; function PtInEditControl(WindowPt: TPoint): Boolean; procedure SetEditorFocus; procedure SelectAll; procedure Show; property Handle: HWnd read GetHandle; property Modified: Boolean read GetModified; end; // *************************************** // Event callback Definitions // *************************************** TAfterPaintEvent = procedure(Sender: TCustomEasyListview; ACanvas: TCanvas; ClipRect: TRect) of object; TAutoGroupGetKeyEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Key: LongWord) of object; TAutoSortGroupCreateEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Group: TEasyGroup; var DoDefaultAction: Boolean) of object; TEasyClipboardEvent = procedure(Sender: TCustomEasyListview; var Handled: Boolean) of object; TEasyClipboardCutEvent = procedure(Sender: TCustomEasyListview; var MarkAsCut, Handled: Boolean) of object; TColumnCheckChangeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnCheckChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Allow: Boolean) of object; TColumnClickEvent = procedure(Sender: TCustomEasyListview; Button: TCommonMouseButton; const Column: TEasyColumn) of object; TColumnContextMenuEvent = procedure(Sender: TCustomEasyListview; HitInfo: TEasyHitInfoColumn; WindowPoint: TPoint; var Menu: TPopupMenu) of object; // TColumnCreatePaintInfoEvent = procedure(Sender: TCustomEasyListview; var PaintInfo: TEasyColumnPaintInfo) of object; TColumnDblClickEvent = procedure(Sender: TCustomEasyListview; Button: TCommonMouseButton; MousePos: TPoint; const Column: TEasyColumn) of object; TColumnDropDownButtonClickEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Button: TCommonMouseButton; ShiftState: TShiftState; WindowPt: TPoint; var DoDefault: Boolean) of object; TColumnEnableChangeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnEnableChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Allow: Boolean) of object; TColumnFocusChangeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnFocusChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Allow: Boolean) of object; TColumnFreeingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnGetCaptionEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Line: Integer; var Caption: WideString) of object; TColumnGetImageIndexEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger) of object; TColumnGetImageListEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var ImageList: TCustomImageList) of object; TColumnGetDetailCountEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Count: Integer) of object; TColumnImageDrawEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender) of object; TColumnImageGetSizeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var ImageWidth, ImageHeight: Integer) of object; TColumnImageDrawIsCustomEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var IsCustom: Boolean) of object; TColumnGetDetailEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Line: Integer; var Detail: Integer) of object; TColumnInitializeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnPaintTextEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; ACanvas: TCanvas) of object; TEasyColumnLoadFromStreamEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; S: TStream; Version: Integer) of object; TEasyColumnSaveToStreamEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; S: TStream; Version: Integer) of object; TColumnSelectionChangeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnSelectionChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Allow: Boolean) of object; TColumnSetCaptionEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Caption: WideString) of object; TColumnSetImageIndexEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; ImageKind: TEasyImageKind; ImageIndex: Integer) of object; TColumnSetDetailEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Line: Integer; const Detail: Integer) of object; TColumnSizeChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; Width, NewWidth: Integer; var Allow: Boolean) of object; TColumnSizeChangedEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnThumbnailDrawEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; ACanvas: TCanvas; ARect: TRect; var DoDefault: Boolean) of object; TColumnVisibilityChangeEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn) of object; TColumnVisibilityChangingEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var Allow: Boolean) of object; TContextMenuEvent = procedure(Sender: TCustomEasyListview; MousePt: TPoint; var Handled: Boolean) of object; TColumnCustomViewEvent = procedure(Sender: TCustomEasyListview; Column: TEasyColumn; var View: TEasyViewColumnClass) of object; TCustomGridEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass) of object; TDblClickEvent = procedure(Sender: TCustomEasyListview; Button: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState) of object; TGetDragImageEvent = procedure(Sender: TCustomEasyListview; Image: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean) of object; TEasyGestureEvent = procedure(Sender: TCustomEasyListview; Gesture: WideString; var DoDefaultMouseAction: Boolean) of object; TGroupClickEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; KeyStates: TCommonKeyStates; HitTest: TEasyGroupHitTestInfoSet) of object; TGroupCollapseEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupCollapsingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Allow: Boolean) of object; TGroupCompareEvent = function(Sender: TCustomEasyListview; Item1, Item2: TEasyGroup): Integer of object; TGroupContextMenuEvent = procedure(Sender: TCustomEasyListview; HitInfo: TEasyHitInfoGroup; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean) of object; TGroupCustomViewEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass) of object; TGroupDblClickEvent = procedure(Sender: TCustomEasyListview; Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoGroup) of object; TGroupExpandEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupExpandingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Allow: Boolean) of object; TGroupFocusChangeEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupFocusChangingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Allow: Boolean) of object; TGroupFreeingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupGetCaptionEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Caption: WideString) of object; TGroupGetClassEvent = procedure(Sender: TCustomEasyListview; var GroupClass: TEasyCollectionItemClass) of object; TGroupGetImageIndexEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger) of object; TGroupGetImageListEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var ImageList: TCustomImageList) of object; TGroupGetDetailCountEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Count: Integer) of object; TGroupImageDrawEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender) of object; TGroupImageGetSizeEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var ImageWidth, ImageHeight: Integer) of object; TGroupImageDrawIsCustomEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var IsCustom: Boolean) of object; TGroupGetDetailEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; Line: Integer; var Detail: Integer) of object; TGroupInitializeEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupHotTrackEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; State: TEasyHotTrackState; MousePos: TPoint) of object; TGroupLoadFromStreamEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; S: TStream; Version: Integer) of object; TGroupPaintTextEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ACanvas: TCanvas) of object; TGroupSaveToStreamEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; S: TStream; Version: Integer) of object; TGroupSetCaptionEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; Caption: WideString) of object; TGroupSetImageIndexEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ImageKind: TEasyImageKind; ImageIndex: Integer) of object; TGroupSetDetailEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; Line: Integer; const Detail: Integer) of object; TGroupSelectionChangeEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupSelectionChangingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Allow: Boolean) of object; TGroupThumbnailDrawEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean) of object; TGroupVisibilityChangeEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup) of object; TGroupVisibilityChangingEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var Allow: Boolean) of object; THintCustomDrawEvent = procedure(Sender: TCustomEasyListview; TargetObj: TEasyCollectionItem; const Info: TEasyHintInfo) of object; THintCustomizeInfoEvent = procedure(Sender: TCustomEasyListview; TargetObj: TEasyCollectionItem; Info: TEasyHintInfo) of object; THintPauseTimeEvent = procedure(Sender: TCustomEasyListview; HintWindowShown: Boolean; var PauseDelay: Integer) of object; THintPopupEvent = procedure(Sender: TCustomEasyListview; TargetObj: TEasyCollectionItem; HintType: TEasyHintType; MousePos: TPoint; var AText: WideString; var HideTimeout, ReShowTimeout: Integer; var Allow: Boolean) of object; THeaderClickEvent = procedure(Sender: TCustomEasyListview; MouseButton: TCommonMouseButton; Column: TEasyColumn) of object; THeaderDblClickEvent = procedure(Sender: TCustomEasyListview; MouseButton: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState) of object; THeaderMouseEvent = procedure(Sender: TCustomEasyListview; MouseButton: TCommonMouseButton; Shift: TShiftState; X, Y: Integer; Column: TEasyColumn) of object; TIncrementalSearchEvent = procedure(Item: TEasyCollectionItem; const SearchBuffer: WideString; var Handled: Boolean; var CompareResult: Integer) of object; TItemCheckChangeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemCheckChangingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Allow: Boolean) of object; TItemClickEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; KeyStates: TCommonKeyStates; HitInfo: TEasyItemHitTestInfoSet) of object; TItemCompareEvent = function(Sender: TCustomEasyListview; Column: TEasyColumn; Group: TEasyGroup; Item1, Item2: TEasyItem; var DoDefault: Boolean): Integer of object; TItemContextMenuEvent = procedure(Sender: TCustomEasyListview; HitInfo: TEasyHitInfoItem; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean) of object; TItemCreateEditorEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Editor: IEasyCellEditor) of object; TItemCustomViewEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; ViewStyle: TEasyListStyle; var View: TEasyViewItemClass) of object; TItemLoadFromStreamEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; S: TStream; Version: Integer) of object; TItemSaveToStreamEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; S: TStream; Version: Integer) of object; TItemDblClickEvent = procedure(Sender: TCustomEasyListview; Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoItem) of object; TItemEditBegin = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Column: Integer; var Allow: Boolean) of object; TItemEditedEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var NewValue: Variant; var Accept: Boolean) of object; TItemEditEnd = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemEnableChangeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemEnableChangingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Allow: Boolean) of object; TItemFreeingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemFocusChangeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemFocusChangingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Allow: Boolean) of object; TItemGetStreamingCreateClassEvent = procedure(Sender: TCustomEasyListview; var AClass: TEasyColumnStoredClass) of object; TItemGetCaptionEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; var Caption: WideString) of object; TEasyItemGetCaptionEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: TEasyColumn; var Caption: WideString) of object; TItemGetEditMenuEvent = procedure(Sender: TCustomEasyListview; Editor: TEasyBaseEditor; var Menu: TPopupMenu) of object; TItemGetClassEvent = procedure(Sender: TCustomEasyListview; var ItemClass: TEasyCollectionItemClass) of object; TItemGetGroupKeyEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; FocusedColumn: Integer; var GroupKey: LongWord) of object; TItemGetImageIndexEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger) of object; TItemGetImageListEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; var ImageList: TCustomImageList) of object; TEasyGetTaskPanelEvent = procedure(Sender: TCustomEasyListview; Group: TEasyGroup; var TaskPanel: TEasyTaskPanelFormClass) of object; TItemGetTileDetailCountEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Count: Integer) of object; TItemImageDrawEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender) of object; TItemImageGetSizeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: TEasyColumn; var ImageWidth, ImageHeight: Integer) of object; TItemImageDrawIsCustomEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: TEasyColumn; var IsCustom: Boolean) of object; TItemGetTileDetailEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Line: Integer; var Detail: Integer) of object; TItemHotTrackEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; State: TEasyHotTrackState; MousePos: TPoint) of object; TItemInitializeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemMouseDownEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean) of object; TItemMouseUpEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean) of object; TItemPaintTextEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Position: Integer; ACanvas: TCanvas) of object; TItemSelectionChangeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemSelectionChangingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Allow: Boolean) of object; TEasyItemSelectionsChangedEvent = procedure(Sender: TCustomEasyListview) of object; TItemSetCaptionEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; Caption: WideString) of object; TItemSetGroupKeyEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; Key: LongWord) of object; TItemSetImageIndexEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; ImageIndex: Integer) of object; TItemSetTileDetailEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; Line: Integer; const Detail: Integer) of object; TItemThumbnailDrawEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean) of object; TItemVisibilityChangeEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem) of object; TItemVisibilityChangingEvent = procedure(Sender: TCustomEasyListview; Item: TEasyItem; var Allow: Boolean) of object; TEasyKeyActionEvent = procedure(Sender: TCustomEasyListview; var CharCode: Word; var Shift: TShiftState; var DoDefault: Boolean) of object; TOLEDropSourceDragEndEvent = procedure(Sender: TCustomEasyListview; ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates) of object; TOLEDropSourceDragStartEvent = procedure(Sender: TCustomEasyListview; ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean) of object; TOLEDropSourceQueryContineDragEvent = procedure(Sender: TCustomEasyListview; EscapeKeyPressed: Boolean; KeyStates: TCommonKeyStates; var QueryResult: TEasyQueryDragResult) of object; TOLEDropSourceGiveFeedbackEvent = procedure(Sender: TCustomEasyListview; Effect: TCommonDropEffects; var UseDefaultCursors: Boolean) of object; TOLEDropTargetDragEnterEvent = procedure(Sender: TCustomEasyListview; DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredDropEffect: TCommonDropEffect) of object; TOLEDropTargetDragOverEvent = procedure(Sender: TCustomEasyListview; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredDropEffect: TCommonDropEffect) of object; TOLEDropTargetDragLeaveEvent = procedure(Sender: TCustomEasyListview) of object; TOLEDropTargetDragDropEvent = procedure(Sender: TCustomEasyListview; DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredDropEffect: TCommonDropEffect; var Handled: Boolean) of object; TOLEGetCustomFormatsEvent = procedure(Sender: TCustomEasyListview; var Formats: TFormatEtcArray) of object; TOLEGetDataEvent = procedure(Sender: TCustomEasyListview; const FormatEtcIn: TFormatEtc; var Medium: TStgMedium; var Handled: Boolean) of object; FOLEGetDataObjectEvent = procedure(Sender: TCustomEasyListview; var DataObject: IDataObject) of object; TOLEQueryDataEvent = procedure(Sender: TCustomEasyListview; const FormatEtcIn: TFormatEtc; var FormatAvailable: Boolean; var Handled: Boolean) of object; TPaintBkGndEvent = procedure(Sender: TCustomEasyListview; ACanvas: TCanvas; AWindowRect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean) of object; TPaintHeaderBkGndEvent = procedure(Sender: TCustomEasyListview; ACanvas: TCanvas; ARect: TRect; var Handled: Boolean) of object; TViewChangingEvent = procedure(Sender: TCustomEasyListview; View: TEasyListStyle; var Allow: Boolean) of object; TViewChangedEvent = procedure(Sender: TCustomEasyListview) of object; TEasyScrollEvent = procedure(Sender: TCustomEasyListview; DeltaX, DeltaY: Integer) of object; TEasyDoGroupCompare = function(Column: TEasyColumn; Group1, Group2: TEasyGroup): Integer of object; TEasyDoItemCompare = function(Column: TEasyColumn; Group: TEasyGroup; Item1, Item2: TEasyItem): Integer of object; // ************************************************************************** // TEasyMemo // A class that uses TntMemo when TNTSUPPORT is defined // ************************************************************************** {$IFDEF TNTSUPPORT} TEasyMemo = class(TTntMemo); TEasyEdit = class(TTntEdit); {$ELSE} TEasyMemo = class(TMemo); TEasyEdit = class(TEdit); {$ENDIF} // ************************************************************************** // TEasyInterfacedPersistent // A class that makes a TPersistent class that is an interfaced object // ************************************************************************** TEasyInterfacedPersistent = class(TPersistent, IUnknown, ICommonExtractObj) private FRefCount: Integer; protected // IUnknown function _AddRef: Integer; virtual; stdcall; function _Release: Integer; virtual; stdcall; function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; // IEasyExtractObj function GetObj: TObject; public procedure AfterConstruction; override; procedure BeforeDestruction; override; class function NewInstance: TObject; override; property Obj: TObject read GetObj; property RefCount: Integer read FRefCount; end; // ************************************************************************** // TEasyOwnedInterfacedPersistent // A class that makes an interfaced object that has knowledge of the // TEasyOwnerListview // ************************************************************************** TEasyOwnedInterfacedPersistent = class(TEasyInterfacedPersistent) private FOwner: TCustomEasyListview; public constructor Create(AnOwner: TCustomEasyListview); virtual; property Owner: TCustomEasyListview read FOwner; end; // ************************************************************************** // TEasyPersistent // ************************************************************************** TEasyPersistent = class(TPersistent) public constructor Create; virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; end; // ************************************************************************** // TEasyOwnedPersistent // Basis for Managers and objects that need a link back to the Main Window // ************************************************************************** TEasyOwnedPersistent = class(TEasyPersistent) private FOwnerListview: TCustomEasyListview; protected function GetOwner: TPersistent; override; public constructor Create(AnOwner: TCustomEasyListview); reintroduce; virtual; procedure LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); virtual; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); virtual; property OwnerListview: TCustomEasyListview read FOwnerListview; end; TEasyCanvasStore = class protected FBrush: TBrush; FFont: TFont; FPen: TPen; public destructor Destroy; override; procedure RestoreCanvasState(Canvas: TCanvas); procedure StoreCanvasState(Canvas: TCanvas); property Brush: TBrush read FBrush write FBrush; property Font: TFont read FFont write FFont; property Pen: TPen read FPen write FPen; end; // ************************************************************************** // TEasyOwnerPersistentView // Basis for any class that will become a view // ************************************************************************** TEasyOwnedPersistentView = class(TEasyOwnedPersistent) private FCanvasStore: TEasyCanvasStore; function GetCanvasStore: TEasyCanvasStore; protected procedure PaintCheckboxCore(CheckType: TEasyCheckType; OwnerListView: TCustomEasyListView; ACanvas: TCanvas; ARect: TRect; IsEnabled, IsChecked, IsHot, IsFlat, IsHovering, IsPending: Boolean; Obj: TEasyCollectionItem; Size: Integer); property CanvasStore: TEasyCanvasStore read GetCanvasStore write FCanvasStore; public destructor Destroy; override; published end; // ************************************************************************** // TEasyAlphaBlender // Helper for Alpha blending a canvas // ************************************************************************** TEasyAlphaBlender = class(TEasyPersistent) public destructor Destroy; override; procedure BasicBlend(Listview: TCustomEasyListview; ACanvas: TCanvas; ViewportRect: TRect; Color: TColor; Alpha: Byte = 128; UseScrollPostion: Boolean = True); virtual; procedure Blend(Listview: TCustomEasyListview; Obj: TEasyCollectionItem; ACanvas: TCanvas; ViewportRect: TRect; Image: TBitmap); virtual; procedure GetBlendParams(Listview: TCustomEasyListview; Obj: TEasyCollectionItem; var BlendAlpha: Byte; var BlendColor: TColor; var DoBlend: Boolean); end; // ************************************************************************** // TEasyOwnedPersistentGroupItem // Basis for any class property of a TEasyGroup that allows communication // back to the TEasyGroups // ************************************************************************** TEasyOwnedPersistentGroupItem = class(TEasyOwnedPersistentView) private FOwnerGroup: TEasyGroup; public constructor Create(AnOwner: TEasyGroup); reintroduce; virtual; property OwnerGroup: TEasyGroup read FOwnerGroup; end; TEasySelectionGroupList = class private FDisplayRect: TRect; FFirstItem: TEasyItem; FList: TList; FRefCount: Integer; protected function GetItems(Index: Integer): TEasyItem; procedure SetItems(Index: Integer; Value: TEasyItem); property List: TList read FList write FList; property RefCount: Integer read FRefCount write FRefCount; public constructor Create; destructor Destroy; override; function Count: Integer; procedure Add(Item: TEasyItem); procedure Clear; procedure DecRef; procedure IncRef; property DisplayRect: TRect read FDisplayRect write FDisplayRect; property FirstItem: TEasyItem read FFirstItem write FFirstItem; property Items[Index: Integer]: TEasyItem read GetItems write SetItems; default; end; // ************************************************************************** // TEasyMargin // Property for TEasyGroupItem to set the attributes of the Group Margins // ************************************************************************** TEasyMargin = class(TEasyOwnedPersistent) private FSize: Integer; FVisible: Boolean; procedure SetSize(Value: Integer); procedure SetVisible(Value: Boolean); protected function RuntimeSize: Integer; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; published property Size: Integer read FSize write SetSize default 30; property Visible: Boolean read FVisible write SetVisible default False; end; // ************************************************************************** // TEasyHeaderMargin // Property for TEasyGroupItem to set the attributes of the Header Group Margin // ************************************************************************** TEasyHeaderMargin = class(TEasyMargin) public constructor Create(AnOwner: TCustomEasyListview); override; published property Visible default True; end; // ************************************************************************** // TCustomEasyFooterMargin // Property for TEasyGroupItem to set the attributes of the Group Margins // ************************************************************************** TCustomEasyFooterMargin = class(TEasyMargin) private FCaption: WideString; FImageIndex: TCommonImageIndexInteger; FImageOverlayIndex: TCommonImageIndexInteger; FPaintInfo: TEasyPaintInfoBaseGroup; function GetAlignment: TAlignment; function GetCaptionIndent: Integer; function GetCaptionLines: Integer; function GetImageIndent: Integer; function GetPaintInfo: TEasyPaintInfoBaseGroup; function GetVAlignment: TCommonVAlignment; procedure SetAlignment(Value: TAlignment); procedure SetCaption(Value: WideString); procedure SetCaptionIndent(Value: Integer); procedure SetCaptionLines(Value: Integer); procedure SetImageIndent(Value: Integer); procedure SetImageIndex(const Value: TCommonImageIndexInteger); procedure SetImageOveralyIndex(const Value: TCommonImageIndexInteger); procedure SetPaintInfo(const Value: TEasyPaintInfoBaseGroup); procedure SetVAlignment(Value: TCommonVAlignment); protected property Alignment: TAlignment read GetAlignment write SetAlignment default taLeftJustify; property Caption: WideString read FCaption write SetCaption; property CaptionIndent: Integer read GetCaptionIndent write SetCaptionIndent default 2; property CaptionLines: Integer read GetCaptionLines write SetCaptionLines default 1; property ImageIndent: Integer read GetImageIndent write SetImageIndent default 2; property ImageIndex: TCommonImageIndexInteger read FImageIndex write SetImageIndex default -1; property ImageOverlayIndex: TCommonImageIndexInteger read FImageOverlayIndex write SetImageOveralyIndex default -1; property PaintInfo: TEasyPaintInfoBaseGroup read GetPaintInfo write SetPaintInfo; property Size default 30; property VAlignment: TCommonVAlignment read GetVAlignment write SetVAlignment default cvaCenter; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; end; TEasyFooterMarginCustomClass = class of TCustomEasyFooterMargin; // ************************************************************************** // TEasyFooterMargin // Default Footer Margin PaintInfo that is global to all Groups. Defined under // the EasyListview.PaintInfoGroup.MarginBottom property // ************************************************************************** TEasyFooterMargin = class(TCustomEasyFooterMargin) published property Alignment; property Caption; property CaptionIndent; property CaptionLines; property ImageIndent; property ImageIndex; property ImageOverlayIndex; property Size default 30; property VAlignment; end; // ************************************************************************** // TEasyPaintInfoBasic // Basic information that defines how a particular UI object is Painted // ************************************************************************** TEasyPaintInfoBasic = class(TEasyOwnedPersistent) private FAlignment: TAlignment; FBorder: Integer; FBorderColor: TColor; FCaptionIndent: Integer; FCaptionLines: Integer; FCheckFlat: Boolean; FCheckIndent: Integer; FCheckSize: Integer; FCheckType: TEasyCheckType; FImageIndent: Integer; FShowBorder: Boolean; FVAlignment: TCommonVAlignment; procedure SetAlignment(Value: TAlignment); procedure SetBorder(Value: Integer); procedure SetBorderColor(Value: TColor); procedure SetCaptionIndent(Value: Integer); procedure SetCaptionLines(Value: Integer); procedure SetCheckFlat(Value: Boolean); procedure SetCheckIndent(Value: Integer); procedure SetCheckSize(Value: Integer); procedure SetCheckType(Value: TEasyCheckType); procedure SetImageIndent(Value: Integer); procedure SetShowBorder(const Value: Boolean); procedure SetVAlignment(Value: TCommonVAlignment); protected procedure Invalidate(ImmediateUpdate: Boolean); virtual; property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; property Border: Integer read FBorder write SetBorder default 4; property BorderColor: TColor read FBorderColor write SetBorderColor default clHighlight; property CaptionIndent: Integer read FCaptionIndent write SetCaptionIndent default 4; property CaptionLines: Integer read FCaptionLines write SetCaptionLines default 1; property CheckFlat: Boolean read FCheckFlat write SetCheckFlat default False; property CheckIndent: Integer read FCheckIndent write SetCheckIndent default 2; property CheckSize: Integer read FCheckSize write SetCheckSize default 12; property CheckType: TEasyCheckType read FCheckType write SetCheckType default ectNone; property ImageIndent: Integer read FImageIndent write SetImageIndent default 2; property ShowBorder: Boolean read FShowBorder write SetShowBorder default True; property VAlignment: TCommonVAlignment read FVAlignment write SetVAlignment default cvaCenter; public constructor Create(AnOwner: TCustomEasyListview); override; procedure Assign(Source: TPersistent); override; end; TEasyPaintInfoBasicClass = class of TEasyPaintInfoBasic; // ************************************************************************** // TEasyPaintInfoBaseItem // Information that defines how an Items UI object is Painted // ************************************************************************** TEasyPaintInfoBaseItem = class(TEasyPaintInfoBasic) private FGridLineColor: TColor; FGridLines: Boolean; FHideCaption: Boolean; FTileDetailCount: Integer; procedure SetGridLineColor(const Value: TColor); procedure SetGridLines(const Value: Boolean); procedure SetHideCaption(const Value: Boolean); procedure SetTileDetailCount(Value: Integer); protected property GridLineColor: TColor read FGridLineColor write SetGridLineColor default clBtnFace; property GridLines: Boolean read FGridLines write SetGridLines default False; property HideCaption: Boolean read FHideCaption write SetHideCaption default False; property TileDetailCount: Integer read FTileDetailCount write SetTileDetailCount default 1; public constructor Create(AnOwner: TCustomEasyListview); override; end; TEasyPaintInfoItem = class(TEasyPaintInfoBaseItem) published property Border; property BorderColor; property CaptionIndent; property CaptionLines; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property GridLineColor; property GridLines; property HideCaption; property ImageIndent; property ShowBorder; property TileDetailCount; property VAlignment; end; TEasyPaintInfoTaskBandItem = class(TEasyPaintInfoBaseItem) published property CaptionIndent; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property VAlignment; end; // ************************************************************************** // TEasyPaintInfoBaseColumn // Information that defines how an Column UI object is Painted // ************************************************************************** TEasyPaintInfoBaseColumn = class(TEasyPaintInfoBasic) private FColor: TColor; FHilightFocused: Boolean; FHilightFocusedColor: TColor; FHotTrack: Boolean; FImagePosition: TEasyHeaderImagePosition; FSortGlyphAlign: TEasySortGlyphAlign; FSortGlyphIndent: Integer; FStyle: TEasyHeaderButtonStyle; procedure SetColor(Value: TColor); procedure SetHilightFocused(const Value: Boolean); procedure SetHilightFocusedColor(const Value: TColor); procedure SetImagePosition(Value: TEasyHeaderImagePosition); procedure SetSortGlpyhAlign(Value: TEasySortGlyphAlign); procedure SetSortGlyphIndent(Value: Integer); procedure SetStyle(Value: TEasyHeaderButtonStyle); protected property Color: TColor read FColor write SetColor default clBtnFace; property HilightFocused: Boolean read FHilightFocused write SetHilightFocused default False; property HilightFocusedColor: TColor read FHilightFocusedColor write SetHilightFocusedColor default $00F7F7F7; property HotTrack: Boolean read FHotTrack write FHotTrack default True; property ImagePosition: TEasyHeaderImagePosition read FImagePosition write SetImagePosition default ehpLeft; property SortGlyphAlign: TEasySortGlyphAlign read FSortGlyphAlign write SetSortGlpyhAlign default esgaRight; property SortGlyphIndent: Integer read FSortGlyphIndent write SetSortGlyphIndent default 2; property Style: TEasyHeaderButtonStyle read FStyle write SetStyle default ehbsThick; public constructor Create(AnOwner: TCustomEasyListview); override; published end; TCustomEasyPaintInfoBaseColumn = class(TEasyPaintInfoBaseColumn) end; TEasyPaintInfoColumn = class(TCustomEasyPaintInfoBaseColumn) private published property Border; property BorderColor; property CaptionIndent; property CaptionLines; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property Color; property HilightFocused; property HilightFocusedColor; property HotTrack; property ImageIndent; property ImagePosition; property SortGlyphAlign; property SortGlyphIndent; property Style; property VAlignment; end; TEasyPaintInfoTaskBandColumn = class(TCustomEasyPaintInfoBaseColumn) published // Nothing published end; // ************************************************************************** // TEasyPaintInfoBasicGroup // Basic information that defines how an Groups UI object is Painted // ************************************************************************** TEasyPaintInfoBaseGroup = class(TEasyPaintInfoBasic) private FBandBlended: Boolean; FBandColor: TColor; FBandColorFade: TColor; FBandEnabled: Boolean; FBandFullWidth: Boolean; FBandIndent: Integer; FBandLength: Integer; FBandMargin: Integer; FBandRadius: Byte; FBandThickness: Integer; FExpandable: Boolean; FExpanded: Boolean; FExpandImageIndent: Integer; FMarginBottom: TCustomEasyFooterMargin; FMarginLeft: TEasyMargin; FMarginRight: TEasyMargin; FMarginTop: TEasyHeaderMargin; function GetMarginBottom: TCustomEasyFooterMargin; function GetMarginLeft: TEasyMargin; function GetMarginRight: TEasyMargin; function GetMarginTop: TEasyHeaderMargin; procedure SetBandBlended(Value: Boolean); procedure SetBandColor(Value: TColor); procedure SetBandColorFade(Value: TColor); procedure SetBandEnabled(Value: Boolean); procedure SetBandFullWidth(Value: Boolean); procedure SetBandIndent(Value: Integer); procedure SetBandLength(Value: Integer); procedure SetBandMargin(Value: Integer); procedure SetBandRadius(Value: Byte); procedure SetBandThickness(Value: Integer); procedure SetExpandable(Value: Boolean); procedure SetExpandImageIndent(Value: Integer); procedure SetMarginBottom(Value: TCustomEasyFooterMargin); procedure SetMarginLeft(Value: TEasyMargin); procedure SetMarginRight(Value: TEasyMargin); procedure SetMarginTop(Value: TEasyHeaderMargin); protected property BandBlended: Boolean read FBandBlended write SetBandBlended default True; property BandColor: TColor read FBandColor write SetBandColor default clBlue; property BandColorFade: TColor read FBandColorFade write SetBandColorFade default clWindow; property BandEnabled: Boolean read FBandEnabled write SetBandEnabled default True; property BandFullWidth: Boolean read FBandFullWidth write SetBandFullWidth default False; property BandIndent: Integer read FBandIndent write SetBandIndent default 0; property BandLength: Integer read FBandLength write SetBandLength default 300; property BandMargin: Integer read FBandMargin write SetBandMargin default 2; property BandRadius: Byte read FBandRadius write SetBandRadius default 4; property BandThickness: Integer read FBandThickness write SetBandThickness default 3; property Expandable: Boolean read FExpandable write SetExpandable default True; property ExpandImageIndent: Integer read FExpandImageIndent write SetExpandImageIndent default 4; property MarginBottom: TCustomEasyFooterMargin read GetMarginBottom write SetMarginBottom; property MarginLeft: TEasyMargin read GetMarginLeft write SetMarginLeft; property MarginRight: TEasyMargin read GetMarginRight write SetMarginRight; property MarginTop: TEasyHeaderMargin read GetMarginTop write SetMarginTop; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; end; // ************************************************************************** // TEasyPaintInfoGroup // Information that defines how an Groups UI object is Painted // ************************************************************************** TEasyPaintInfoGroup = class(TEasyPaintInfoBaseGroup) published property Alignment; property BandBlended; property BandColor; property BandColorFade; property BandEnabled; property BandFullWidth; property BandIndent; property BandLength; property BandMargin; property BandRadius; property BandThickness; property Border; property BorderColor; property CaptionIndent; property CaptionLines; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property Expandable; property ExpandImageIndent; property ImageIndent; property MarginBottom; property MarginLeft; property MarginRight; property MarginTop; property VAlignment; end; // ************************************************************************** // TEasyPaintInfoGroup // Information that defines how an Groups UI object is Painted // ************************************************************************** TEasyPaintInfoTaskbandGroup = class(TEasyPaintInfoBaseGroup) published property Alignment; property CaptionIndent; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property Expandable; property MarginBottom; property MarginLeft; property MarginRight; property MarginTop; property VAlignment; end; // ************************************************************************** // TEasyDynamicDataHelper // Helps with multiple captions/image storage for item/groups/columns // ************************************************************************** TEasyDynamicDataHelper = class private FCaptionArray: TCommonWideStringDynArray; FDetailArray: TCommonIntegerDynArray; FGroupKeyArray: TCommonIntegerDynArray; FImageIndexArray: TCommonIntegerDynArray; FOverlayIndexArray: TCommonIntegerDynArray; function GetCaptions(Index: Integer): Widestring; function GetDetails(Index: Integer): Integer; function GetImageIndexes(Index: Integer): Integer; function GetImageOverlayIndexes(Index: Integer): Integer; procedure LoadIntArrayFromStream(S: TStream; var AnArray: TCommonIntegerDynArray); procedure LoadWideStrArrayFromStream(S: TStream; var AnArray: TCommonWideStringDynArray); procedure SaveIntArrayToStream(S: TStream; var AnArray: TCommonIntegerDynArray); procedure SaveWideStrArrayToStream(S: TStream; var AnArray: TCommonWideStringDynArray); procedure SetCaptions(Index: Integer; Value: Widestring); procedure SetDetails(Index: Integer; Value: Integer); procedure SetImageIndexes(Index: Integer; Value: Integer); procedure SetImageOverlayIndexes(Index: Integer; Value: Integer); property CaptionArray: TCommonWideStringDynArray read FCaptionArray write FCaptionArray; property DetailArray: TCommonIntegerDynArray read FDetailArray write FDetailArray; property GroupKeyArray: TCommonIntegerDynArray read FGroupKeyArray write FGroupKeyArray; property ImageIndexArray: TCommonIntegerDynArray read FImageIndexArray write FImageIndexArray; property OverlayIndexArray: TCommonIntegerDynArray read FOverlayIndexArray write FOverlayIndexArray; public procedure Clear; procedure LoadFromStream(S: TStream; Version: Integer); virtual; procedure SaveToStream(S: TStream; Version: Integer); virtual; property Captions[Index: Integer]: Widestring read GetCaptions write SetCaptions; property Details[Index: Integer]: Integer read GetDetails write SetDetails; property ImageIndexes[Index: Integer]: Integer read GetImageIndexes write SetImageIndexes; property ImageOverlayIndexes[Index: Integer]: Integer read GetImageOverlayIndexes write SetImageOverlayIndexes; end; TEasyItemDynamicDataHelper = class(TEasyDynamicDataHelper) private FStateImageArray: TCommonIntegerDynArray; function GetGroupKey(Index: Integer): LongWord; function GetStateImageIndexes(Index: Integer): TCommonImageIndexInteger; procedure SetGroupKey(Index: Integer; Value: LongWord); procedure SetStateImageIndexes(Index: Integer; Value: TCommonImageIndexInteger); protected property StateImageArray: TCommonIntegerDynArray read FStateImageArray write FStateImageArray; public procedure LoadFromStream(S: TStream; Version: Integer); override; procedure SaveToStream(S: TStream; Version: Integer); override; property GroupKey[Index: Integer]: LongWord read GetGroupKey write SetGroupKey; property StateImageIndexes[Index: Integer]: TCommonImageIndexInteger read GetStateImageIndexes write SetStateImageIndexes; end; // ************************************************************************** // TEasyCollectionItem // Basis for Collection items (, TEasyGroup, TEasyColumn) // This Item can access its data through the // ************************************************************************** TEasyCollectionItem = class(TEasyPersistent, IUnknown, IEasyNotificationSink) private FCollection: TEasyCollection; FData: TObject; FDataInf: IUnknown; FDisplayRect: TRect; // The viewport coordinates of the object FIndex: Integer; // Absolute Index of the item within a particular collecton FOwnsPaintInfo: Boolean; FPaintInfo: TEasyPaintInfoBasic; // Information to draw the item FRefCount: Integer; FState: TEasyStorageObjectStates; // State of the item FTag: Integer; FVisibleIndex: Integer; // Index of the item across all collections (flat list across collection in group) // See TEasyItem.VisibleIndexInGroup function GetAlignment: TAlignment; function GetBold: Boolean; function GetBorder: Integer; function GetBorderColor: TColor; function GetCaptionIndent: Integer; function GetCheckFlat: Boolean; function GetCheckHovering: Boolean; function GetCheckIndent: Integer; function GetCheckPending: Boolean; function GetCheckSize: Integer; function GetCheckType: TEasyCheckType; function GetClicking: Boolean; function GetCut: Boolean; function GetDataInf: IUnknown; function GetDestroying: Boolean; function GetGhosted: Boolean; function GetHilighted: Boolean; function GetEnabled: Boolean; function GetFocused: Boolean; function GetHotTracking(MousePos: TPoint): Boolean; function GetImageIndent: Integer; function GetInitialized: Boolean; function GetOwnerListview: TCustomEasyListview; function GetPaintInfo: TEasyPaintInfoBasic; function GetSelected: Boolean; function GetVAlignment: TCommonVAlignment; function GetViewRect: TRect; function GetVisible: Boolean; procedure SetAlignment(Value: TAlignment); procedure SetBold(const Value: Boolean); procedure SetBorder(Value: Integer); procedure SetBorderColor(Value: TColor); procedure SetCaptionIndent(Value: Integer); procedure SetCheckFlat(Value: Boolean); procedure SetCheckHovering(Value: Boolean); procedure SetCheckIndent(Value: Integer); procedure SetCheckPending(Value: Boolean); procedure SetCheckSize(Value: Integer); procedure SetCheckType(Value: TEasyCheckType); procedure SetClicking(Value: Boolean); procedure SetCut(Value: Boolean); procedure SetData(Value: TObject); virtual; procedure SetDataInf(const Value: IUnknown); procedure SetGhosted(const Value: Boolean); procedure SetHilighted(Value: Boolean); procedure SetEnabled(Value: Boolean); procedure SetFocused(Value: Boolean); procedure SetHotTracking(MousePos: TPoint; Value: Boolean); procedure SetImageIndent(Value: Integer); procedure SetInitialized(Value: Boolean); virtual; procedure SetPaintInfo(Value: TEasyPaintInfoBasic); procedure SetSelected(Value: Boolean); procedure SetVAlignment(Value: TCommonVAlignment); procedure SetVisible(Value: Boolean); protected function AllowDrag(ViewportPt: TPoint): Boolean; virtual; // IUnknown function _AddRef: Integer; virtual; stdcall; function _Release: Integer; virtual; stdcall; function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function CanChangeBold(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeCheck(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeEnable(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeFocus(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeHotTracking(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeSelection(NewValue: Boolean): Boolean; virtual; abstract; function CanChangeVisibility(NewValue: Boolean): Boolean; virtual; abstract; function DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; virtual; function GetChecked: Boolean; virtual; function GetDisplayName: WideString; virtual; function LocalPaintInfo: TEasyPaintInfoBasic; virtual; abstract; procedure Freeing; virtual; abstract; procedure GainingBold; virtual; abstract; procedure GainingCheck; virtual; abstract; procedure GainingEnable; virtual; abstract; procedure GainingFocus; virtual; abstract; procedure GainingGhosted; virtual; abstract; procedure GainingHilight; virtual; abstract; procedure GainingHotTracking(MousePos: TPoint); virtual; abstract; procedure GainingSelection; virtual; abstract; procedure GainingVisibility; virtual; abstract; function GetCaption: WideString; virtual; function GetCaptions(Column: Integer): Widestring; virtual; abstract; function GetImageIndex: TCommonImageIndexInteger; virtual; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; virtual; abstract; function GetImageOverlayIndex: TCommonImageIndexInteger; virtual; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; virtual; abstract; function GetOwner: TPersistent; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; virtual; abstract; function GetIndex: Integer; virtual; function GetDetailCount: Integer; virtual; abstract; function GetDetails(Line: Integer): Integer; virtual; abstract; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); virtual; abstract; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW, ImageH: Integer); virtual; abstract; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); virtual; abstract; procedure InvalidateItem(ImmediateRefresh: Boolean); // IEasyNotificationSink procedure LosingBold; virtual; abstract; procedure LosingGhosted; virtual; abstract; procedure LosingHotTracking; virtual; abstract; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); virtual; abstract; procedure Initialize; virtual; abstract; procedure LosingCheck; virtual; abstract; procedure LosingEnable; virtual; abstract; procedure LosingFocus; virtual; abstract; procedure LosingHilight; virtual; abstract; procedure LosingSelection; virtual; abstract; procedure LosingVisibility; virtual; abstract; procedure SetCaptions(Column: Integer; Value: Widestring); virtual; abstract; procedure SetCaption(Value: WideString); virtual; procedure SetChecked(Value: Boolean); virtual; procedure SetDestroyFlags; procedure SetDetailCount(Value: Integer); virtual; abstract; procedure SetDetails(Line: Integer; Value: Integer); virtual; abstract; procedure SetImageIndex(const Value: TCommonImageIndexInteger); virtual; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); virtual; abstract; procedure SetImageOverlayIndex(const Value: TCommonImageIndexInteger); virtual; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); virtual; abstract; procedure UnRegister; // IEasyNotificationSink property Alignment: TAlignment read GetAlignment write SetAlignment default taLeftJustify; property Bold: Boolean read GetBold write SetBold default False; property Border: Integer read GetBorder write SetBorder default 0; property BorderColor: TColor read GetBorderColor write SetBorderColor default clWindow; property CaptionIndent: Integer read GetCaptionIndent write SetCaptionIndent default 2; property Checked: Boolean read GetChecked write SetChecked default False; property CheckFlat: Boolean read GetCheckFlat write SetCheckFlat default False; property CheckHovering: Boolean read GetCheckHovering write SetCheckHovering; property CheckIndent: Integer read GetCheckIndent write SetCheckIndent default 2; property CheckPending: Boolean read GetCheckPending write SetCheckPending; property CheckSize: Integer read GetCheckSize write SetCheckSize default 12; property CheckType: TEasyCheckType read GetCheckType write SetCheckType default ectNone; property Clicking: Boolean read GetClicking write SetClicking default False; property Collection: TEasyCollection read FCollection write FCollection; property Cut: Boolean read GetCut write SetCut default False; property DataInf: IUnknown read GetDataInf write SetDataInf; property Destroying: Boolean read GetDestroying; property DisplayRect: TRect read FDisplayRect write FDisplayRect; property Enabled: Boolean read GetEnabled write SetEnabled default True; property Focused: Boolean read GetFocused write SetFocused default False; property Ghosted: Boolean read GetGhosted write SetGhosted default False; property Hilighted: Boolean read GetHilighted write SetHilighted default False; property ImageIndent: Integer read GetImageIndent write SetImageIndent default 2; property Initialized: Boolean read GetInitialized write SetInitialized; property OwnsPaintInfo: Boolean read FOwnsPaintInfo write FOwnsPaintInfo default False; property PaintInfo: TEasyPaintInfoBasic read GetPaintInfo write SetPaintInfo; property Selected: Boolean read GetSelected write SetSelected default False; property State: TEasyStorageObjectStates read FState write FState;// The State of the object, checked, selected, focused, etc. property VAlignment: TCommonVAlignment read GetVAlignment write SetVAlignment; property Visible: Boolean read GetVisible write SetVisible default True; public constructor Create(ACollection: TEasyCollection); reintroduce; virtual; destructor Destroy; override; function EditAreaHitPt(ViewportPoint: TPoint): Boolean; virtual; abstract; function SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; virtual; abstract; function SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; virtual; abstract; procedure Invalidate(ImmediateUpdate: Boolean); virtual; // IEasyNotificationSink procedure LoadFromStream(S: TStream; var Version: Integer); virtual; procedure MakeVisible(Position: TEasyMakeVisiblePos); virtual; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); virtual; property Caption: WideString read GetCaption write SetCaption; property Captions[Column: Integer]: Widestring read GetCaptions write SetCaptions; property Data: TObject read FData write SetData; property DetailCount: Integer read GetDetailCount write SetDetailCount; property Details[Line: Integer]: Integer read GetDetails write SetDetails; property HotTracking[MousePos: TPoint]: Boolean read GetHotTracking write SetHotTracking; property ImageIndex: TCommonImageIndexInteger read GetImageIndex write SetImageIndex default -1; property ImageIndexes[Column: Integer]: TCommonImageIndexInteger read GetImageIndexes write SetImageIndexes; property ImageList[Column: Integer; IconSize: TEasyImageSize]: TCustomImageList read GetImageList; property ImageOverlayIndex: TCommonImageIndexInteger read GetImageOverlayIndex write SetImageOverlayIndex default -1; property ImageOverlayIndexes[Column: Integer]: TCommonImageIndexInteger read GetImageOverlayIndexes write SetImageOverlayIndexes; property Index: Integer read GetIndex; property OwnerListview: TCustomEasyListview read GetOwnerListview; property RefCount: Integer read FRefCount; property Tag: Integer read FTag write FTag default 0; property ViewRect: TRect read GetViewRect; property VisibleIndex: Integer read FVisibleIndex; end; // ************************************************************************** // TEasyItemBase // Basis for any object that can be stored in a TEasyGroup. Implements the // basic handling of interaction between the item and the Listview // ************************************************************************** TEasyItem = class(TEasyCollectionItem) private FSelectionGroup: TEasySelectionGroupList; // If grouped selection is on this points to the selection group this item belongs to (nil if none) FView: TEasyViewItem; FVisibleIndexInGroup: Integer; // Index of visible item within a group function GetColumnPos: Integer; function GetOwnerGroup: TEasyGroup; function GetOwnerItems: TEasyItems; function GetPaintInfo: TEasyPaintInfoItem; function GetRowPos: Integer; function GetView: TEasyViewItem; function GetViewClass: TEasyViewItemClass; procedure SetPaintInfo(const Value: TEasyPaintInfoItem); procedure SetSelectionGroup(Value: TEasySelectionGroupList); protected function AllowDrag(ViewportPt: TPoint): Boolean; override; function CanChangeBold(NewValue: Boolean): Boolean; override; function CanChangeCheck(NewValue: Boolean): Boolean; override; function CanChangeEnable(NewValue: Boolean): Boolean; override; function CanChangeFocus(NewValue: Boolean): Boolean; override; function CanChangeHotTracking(NewValue: Boolean): Boolean; override; function CanChangeSelection(NewValue: Boolean): Boolean; override; function CanChangeVisibility(NewValue: Boolean): Boolean; override; function DefaultStateImageList: TCustomImageList; function GetDefaultViewClass: TEasyViewItemClass; virtual; function GetGroupKey(FocusedColumn: Integer): LongWord; virtual; function GetIndex: Integer; override; function GetStateImageIndex: TCommonImageIndexInteger; virtual; function GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; virtual; abstract; function GetStateImageList(Column: Integer): TCustomImageList; virtual; abstract; function LocalPaintInfo: TEasyPaintInfoBasic; override; procedure Freeing; override; procedure GainingBold; override; procedure GainingCheck; override; procedure GainingEnable; override; procedure GainingFocus; override; procedure GainingGhosted; override; procedure GainingHilight; override; procedure GainingHotTracking(MousePos: TPoint); override; procedure GainingSelection; override; procedure GainingVisibility; override; procedure Initialize; override; procedure LosingBold; override; procedure LosingCheck; override; procedure LosingEnable; override; procedure LosingFocus; override; procedure LosingGhosted; override; procedure LosingHilight; override; procedure LosingHotTracking; override; procedure LosingSelection; override; procedure LosingVisibility; override; procedure ReleaseSelectionGroup; procedure SetStateImageIndex(const Value: TCommonImageIndexInteger); virtual; procedure SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); virtual; abstract; property SelectionGroup: TEasySelectionGroupList read FSelectionGroup write SetSelectionGroup; procedure SetGroupKey(FocusedColumn: Integer; Value: LongWord); virtual; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; function EditAreaHitPt(ViewportPoint: TPoint): Boolean; override; function HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyItemHitTestInfoSet): Boolean; function SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; override; function SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; override; procedure Edit(Column: TEasyColumn = nil); procedure Invalidate(ImmediateUpdate: Boolean); override; procedure ItemRectArray(Column: TEasyColumn; ACanvas: TCanvas; var RectArray: TEasyRectArrayObject); procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure MakeVisible(Position: TEasyMakeVisiblePos); override; procedure Paint(ACanvas: TCanvas; ViewportClipRect: TRect; Column: TEasyColumn; ForceSelectionRectDraw: Boolean); virtual; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; property Alignment; property Bold; property Border; property BorderColor; property Caption; property CaptionIndent; property Captions; property Checked; property CheckFlat; property CheckHovering; property CheckIndent; property CheckPending; property CheckSize; property CheckType; property ColumnPos: Integer read GetColumnPos; property Cut; property Destroying; property DetailCount; property Details; property Enabled; property Focused; property GroupKey[FocusedColumn: Integer]: LongWord read GetGroupKey write SetGroupKey; property Hilighted; property ImageIndent; property ImageIndex; property ImageIndexes; property ImageList; property ImageOverlayIndex; property ImageOverlayIndexes; property Initialized; property OwnerGroup: TEasyGroup read GetOwnerGroup; property OwnerItems: TEasyItems read GetOwnerItems; property OwnsPaintInfo; property PaintInfo: TEasyPaintInfoItem read GetPaintInfo write SetPaintInfo; property RowPos: Integer read GetRowPos; property Selected; property State; property StateImageIndex: TCommonImageIndexInteger read GetStateImageIndex write SetStateImageIndex default -1; property StateImageIndexes[Column: Integer]: TCommonImageIndexInteger read GetStateImageIndexes write SetStateImageIndexes; property StateImageList[Column: Integer]: TCustomImageList read GetStateImageList; property VAlignment; property View: TEasyViewItem read GetView; property ViewClass: TEasyViewItemClass read GetViewClass; property Visible; property VisibleIndexInGroup: Integer read FVisibleIndexInGroup; published end; // ************************************************************************** // TEasyItemInterfaced // Uses interfaced based data extraction to extract the data from a data // source. The data source can implement any of the following // IEasyCaptions // Returns Captions for the control // IEasyCaptionsEditable // Sets Captions in the data from the Control // IEasyImages // Returns Images for the control // IEasyImagesEditable // Sets Images in the data from the Control // IEasyThumbnail // Returns Thumbnail for the control // IEasyThumbnailEditable // Sets Thumbnail in the data from the Control // IEasyChecks // Sets/Unsets the Checkbox State for the control // IEasyNotifier // Returns an Inteterface to allow data to notify Control of changes in the data // IEasyCompareData // Allows sorting of the data set // ************************************************************************** TEasyItemInterfaced = class(TEasyItem) private function GetCommonImageIndex(Column: Integer; Kind: TEasyImageKind): TCommonImageIndexInteger; procedure SetCommonImageIndex(Column: Integer; Kind: TEasyImageKind; Value: TCommonImageIndexInteger); protected function GetCaptions(Column: Integer): Widestring; override; function GetChecked: Boolean; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetGroupKey(FocusedColumn: Integer): LongWord; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageList(Column: Integer): TCustomImageList; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW, ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetChecked(Value: Boolean); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetGroupKey(FocusedColumn: Integer; Value: LongWord); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; public function ExtractObject: TObject; property DataInf; end; // ************************************************************************** // TEasyItemVirtual // Calls back through the Controls Events for the data to display // ************************************************************************** TEasyItemVirtual = class(TEasyItem) protected function GetCaptions(Column: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetGroupKey(FocusedColumn: Integer): LongWord; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageList(Column: Integer): TCustomImageList; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetGroupKey(FocusedColumn: Integer; Value: LongWord); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; public end; // ************************************************************************** // TEasyItemStored // Stores the data local to the Item instance // ************************************************************************** TEasyItemStored = class(TEasyItem) private FDataHelper: TEasyItemDynamicDataHelper; protected function GetCaptions(Column: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetGroupKey(FocusedColumn: Integer): LongWord; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetStateImageList(Column: Integer): TCustomImageList; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Column: Integer; Value: Integer); override; procedure SetGroupKey(FocusedColumn: Integer; Value: LongWord); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; property DataHelper: TEasyItemDynamicDataHelper read FDataHelper write FDataHelper; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; published property Bold; property Caption; property Checked; property Enabled; property Ghosted; property ImageIndex; property ImageOverlayIndex; property Selected; property StateImageIndex; property Tag; property Visible; end; TEasyItemStoredClass = class of TEasyItemStored; // ************************************************************************** // TEasyCollection // Basis for Collection (TEasyItems, TEasyGroups, TEasyColumns) // ************************************************************************** TEasyCollection = class(TEasyOwnedPersistent) private FHideFromDFM: Boolean; FList: TList; FReIndexCount: Integer; FTag: Integer; FVisibleList: TList; function GetCount: Integer; function GetItem(Index: Integer): TEasyCollectionItem; function GetOwnerListview: TCustomEasyListview; function GetReIndexDisable: Boolean; function GetVisibleCount: Integer; procedure SetItem(Index: Integer; Value: TEasyCollectionItem); procedure SetReIndexDisable(const Value: Boolean); protected FItemClass: TEasyCollectionItemClass; function DoStore: Boolean; dynamic; function GetOwner: TPersistent; override; procedure DefineProperties(Filer: TFiler); override; procedure DoItemAdd(Item: TEasyCollectionItem; Index: Integer); virtual; procedure DoStructureChange; virtual; property List: TList read FList write FList; property ReIndexCount: Integer read FReIndexCount write FReIndexCount; property VisibleList: TList read FVisibleList write FVisibleList; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; function Add(Data: TObject = nil): TEasyCollectionItem; function FirstVisible: TEasyColumn; virtual; function LastVisible: TEasyColumn; virtual; function NextVisible(Column: TEasyColumn): TEasyColumn; virtual; function PrevVisible(Column: TEasyColumn): TEasyColumn; virtual; procedure BeginUpdate(ReIndex: Boolean); virtual; procedure Clear(FreeItems: Boolean = True); virtual; procedure Delete(Index: Integer); procedure EndUpdate(Invalidate: Boolean = True); virtual; function Insert(Index: Integer; Data: TObject = nil): TEasyCollectionItem; procedure Exchange(Index1, Index2: Integer); procedure MakeAllVisible; virtual; procedure ReadItems(Stream: TStream); virtual; procedure ReIndexItems; procedure WriteItems(Stream: TStream); virtual; property Count: Integer read GetCount; property HideFromDFM: Boolean read FHideFromDFM write FHideFromDFM default False; property ItemClass: TEasyCollectionItemClass read FItemClass; property Items[Index: Integer]: TEasyCollectionItem read GetItem write SetItem; default; property OwnerListview: TCustomEasyListview read GetOwnerListview; property ReIndexDisable: Boolean read GetReIndexDisable write SetReIndexDisable; property VisibleCount: Integer read GetVisibleCount; published property Tag: Integer read FTag write FTag default 0; end; TEasyCollectionClass = class of TEasyCollection; // ************************************************************************** // TEasyViewItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewItem = class(TEasyOwnedPersistentGroupItem) private procedure PaintAlphaBlendedRoundRect(ACanvas: TCanvas; AlphaColor: TColor; GradientBottom: TColor; GradientTop: TColor; var LocalSelWindowClippedRect: TRect; var Rgn: HRGN); procedure PaintAlphaBlendedSelection(ACanvas: TCanvas; AlphaColor: TColor; HeaderClippedWindowRect: TRect; LocalSelRect: TRect); procedure PaintAlphaBlendedGradientFill(ACanvas: TCanvas; GradientBottom: TColor; GradientTop: TColor; LocalSelRect: TRect; LocalSelWindowClippedRect: TRect; LocalSelClippedRect: TRect); procedure PaintNonAlphaBlendedSelection(ACanvas: TCanvas; LocalSelRect: TRect); protected function AllowDrag(Item: TEasyItem; ViewportPoint: TPoint): Boolean; virtual; function PaintStateImage: Boolean; virtual; function ValidateColumnIndex(Column: TEasyColumn): Integer; public procedure AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); virtual; procedure CalculateTextRect(Item: TEasyItem; Column: TEasyColumn; var TextR: TRect; ACanvas: TControlCanvas); function EditAreaHitPt(Item: TEasyItem; ViewportPoint: TPoint): Boolean; virtual; function ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; virtual; function ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; virtual; function FullRowSelect: Boolean; virtual; function GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; virtual; procedure GetImageSize(Item: TEasyItem; Column: TEasyColumn; var ImageW, ImageH: Integer; Image: TEasyImageKind); virtual; function GetStateImageList(Column: TEasyColumn; Item: TEasyItem): TCustomImageList; virtual; function ItemRect(Item: TEasyItem; Column: TEasyColumn; RectType: TEasyCellRectType): TRect; virtual; procedure ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); virtual; procedure LoadTextFont(Item: TEasyItem; Position: Integer; ACanvas: TCanvas; Hilightable: Boolean); virtual; function OverlappedFocus: Boolean; virtual; procedure Paint(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; ViewportClipRect: TRect; ForceSelectionRectDraw: Boolean); virtual; procedure PaintAfter(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); virtual; procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); virtual; procedure PaintCheckBox(Item: TEasyItem; Column: TEasyColumn; RectArray: TEasyRectArrayObject; ACanvas: TCanvas); virtual; procedure PaintFocusRect(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas); virtual; procedure PaintImage(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ImageSize: TEasyImageSize; ACanvas: TCanvas); virtual; function PaintImageSize: TEasyImageSize; virtual; procedure PaintSelectionRect(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; ViewportClipRect: TRect; ForceSelectionRectDraw: Boolean); virtual; procedure PaintText(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; LinesToDraw: Integer); virtual; function PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; virtual; function PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; virtual; function PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; virtual; function PtInRect(Item: TEasyItem; Column: TEasyColumn; Pt: TPoint): Integer; virtual; procedure ReSizeRectArray(var RectArray: TEasyRectArrayObjectArray); virtual; function SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; virtual; function SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; virtual; procedure TestAndClipImage(ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Rgn: HRgn); procedure TestAndUnClipImage(ACanvas: TCanvas; RectArray: TEasyRectArrayObject; Rgn: HRgn); end; // ************************************************************************** // TEasyViewIconItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewIconItem = class(TEasyViewItem) public function ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function OverlappedFocus: Boolean; override; function PaintImageSize: TEasyImageSize; override; function PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; override; procedure AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); override; procedure ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); override; procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); override; end; // ************************************************************************** // TEasyViewSmallIconItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewSmallIconItem = class(TEasyViewItem) public function CalculateDisplayRect(Item: TEasyItem; Column: TEasyColumn): TRect; virtual; function ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; procedure ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); override; procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); override; function PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; override; function PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; override; function PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; override; end; // ************************************************************************** // TEasyViewListItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewListItem = class(TEasyViewSmallIconItem) end; // ************************************************************************** // TEasyViewReportItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewReportItem = class(TEasyViewSmallIconItem) protected function AllowDrag(Item: TEasyItem; ViewportPoint: TPoint): Boolean; override; function PaintStateImage: Boolean; override; public function CalculateDisplayRect(Item: TEasyItem; Column: TEasyColumn): TRect; override; function ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function FullRowSelect: Boolean; override; function SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; override; function SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; override; end; // ************************************************************************** // TEasyViewGridItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewGridItem = class(TEasyViewSmallIconItem) end; // ************************************************************************** // TEasyViewThumbnailItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewThumbnailItem = class(TEasyViewItem) public function ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; override; function PaintImageSize: TEasyImageSize; override; procedure AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); override; procedure ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); override; function OverlappedFocus: Boolean; override; procedure PaintAfter(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); override; procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); override; function PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; override; function PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; override; function SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; override; function SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; override; end; // ************************************************************************** // TEasyViewTileItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewTileItem = class(TEasyViewItem) public function ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; override; function GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; override; function PaintImageSize: TEasyImageSize; override; function PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; override; procedure AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); override; procedure ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); override; procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); override; procedure PaintText(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; LinesToDraw: Integer); override; end; // ************************************************************************** // TEasyViewFilmStripItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem // ************************************************************************** TEasyViewFilmStripItem = class(TEasyViewThumbnailItem) end; // ************************************************************************** // TEasyViewTaskBandItem // Basis for the UI (drawing, and mouse interaction) for a TEasyItem in the // Taskband control // ************************************************************************** TEasyViewTaskBandItem = class(TEasyViewSmallIconItem) public end; // ************************************************************************** // TEasyItems // Collection that contains all the Items within a Group in the control // ************************************************************************** TEasyItems = class(TEasyCollection) private FOwnerGroup: TEasyGroup; function GetItem(Index: Integer): TEasyItem; procedure SetItem(Index: Integer; Value: TEasyItem); protected procedure DoStructureChange; override; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); reintroduce; virtual; destructor Destroy; override; function Add(Data: TObject = nil): TEasyItem; function AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; function AddVirtual(Data: TObject = nil): TEasyItemVirtual; function AddCustom(CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; procedure Clear(FreeItems: Boolean = True); override; procedure Delete(Index: Integer); reintroduce; procedure Exchange(Index1, Index2: Integer); reintroduce; function Insert(Index: Integer; Data: TObject = nil): TEasyItem; function InsertCustom(Index: Integer; CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; function InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; function InsertVirtual(Index: Integer; Data: TObject = nil): TEasyItemVirtual; property Items[Index: Integer]: TEasyItem read GetItem write SetItem; default; property OwnerGroup: TEasyGroup read FOwnerGroup; end; // ************************************************************************** // TEasyGlobalItems // Convenience TListview migration items // ************************************************************************** TEasyGlobalItems = class private FOwner: TCustomEasyListview; function GetCount: Integer; function GetItem(Index: Integer): TEasyItem; function GetItemInternal(Index: Integer): TEasyItem; function GetLastGroup: TEasyGroup; procedure EnsureFirstGroup; procedure IndexError(Index: Integer); procedure SetItem(Index: Integer; const Value: TEasyItem); procedure SetReIndexDisable(const Value: Boolean); public constructor Create(AnOwner: TCustomEasyListview); function Add(Data: TObject = nil): TEasyItem; function AddCustom(CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; function AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; function AddVirtual(Data: TObject = nil): TEasyItemVirtual; function IndexOf(Item: TEasyItem): Integer; function Insert(Index: Integer; Data: TObject = nil): TEasyItem; function InsertCustom(Index: Integer; CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; function InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; function InsertVirtual(Index: Integer; Data: TObject = nil): TEasyItemVirtual; procedure Clear; procedure Delete(Index: Integer; ReIndex: Boolean = True); procedure Exchange(Index1, Index2: Integer); property Count: Integer read GetCount; property Items[Index: Integer]: TEasyItem read GetItem write SetItem; default; property OwnerListview: TCustomEasyListview read FOwner; property ReIndexDisable: Boolean write SetReIndexDisable; end; // ************************************************************************** // TEasyGlobalImageManager // Manages images and bitmaps that are used in the EasyControl such as // expand "+" buttons, etc. // ************************************************************************** TEasyGlobalImageManager = class(TEasyOwnedPersistent) private FGroupExpandButton: TBitmap; FGroupCollapseButton: TBitmap; FColumnSortUp: TBitmap; FColumnSortDown: TBitmap; function GetColumnSortDown: TBitmap; function GetColumnSortUp: TBitmap; function GetGroupCollapseImage: TBitmap; function GetGroupExpandImage: TBitmap; procedure SetColumnSortDown(Value: TBitmap); procedure SetColumnSortUp(Value: TBitmap); procedure SetGroupCollapseImage(const Value: TBitmap); procedure SetGroupExpandImage(const Value: TBitmap); protected procedure MakeTransparent(Bits: TBitmap; TransparentColor: TColor); public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; published property GroupExpandButton: TBitmap read GetGroupExpandImage write SetGroupExpandImage; property GroupCollapseButton: TBitmap read GetGroupCollapseImage write SetGroupCollapseImage; property ColumnSortUp: TBitmap read GetColumnSortUp write SetColumnSortUp; property ColumnSortDown: TBitmap read GetColumnSortDown write SetColumnSortDown; end; // ************************************************************************** // TEasyGridGroup // Builds the Grid for the Group, by default the grid fits in the OwnerWindow // horizontally and wraps down // ************************************************************************** TEasyGridGroup = class(TEasyOwnedPersistent) private FColumnCount: Integer; // Number of Columns in the grid FLayout: TEasyGridLayout; FOwnerGroup: TEasyGroup; // The group that the grid is attached to FRowCount: Integer; // The number of Rows in the group function GetOwnerGroups: TEasyGroups; protected function AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; virtual; function GetCellSize: TEasyCellSize; virtual; abstract; function GetMaxColumns(Group: TEasyGroup; WindowWidth: Integer): Integer; virtual; function LastItemInNColumn(Group: TEasyGroup; N: Integer): TEasyItem; function NextVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; function PrevVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; function SearchForHitRight(ColumnPos: Integer; Pt: TPoint): TEasyItem; function StaticTopItemMargin: Integer; virtual; function StaticTopMargin: Integer; virtual; procedure AutoSizeCells; virtual; procedure FindLongestCaption(Column: TEasyColumn; var Item: TEasyItem); procedure SetCellSize(Value: TEasyCellSize); virtual; abstract; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); reintroduce; virtual; destructor Destroy; override; procedure FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); virtual; procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); virtual; property CellSize: TEasyCellSize read GetCellSize write SetCellSize; property ColumnCount: Integer read FColumnCount; property Layout: TEasyGridLayout read FLayout; property OwnerGroup: TEasyGroup read FOwnerGroup; property OwnerGroups: TEasyGroups read GetOwnerGroups; property RowCount: Integer read FRowCount; end; // ************************************************************************** // TEasyGridIconGroup // Builds the Large Icon Grid for the Group // ************************************************************************** TEasyGridIconGroup = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; procedure AutoSizeCells; override; procedure SetCellSize(Value: TEasyCellSize); override; public end; // ************************************************************************** // TEasyGridSmallIconGroup // Builds the Small Icon Grid for the Group // ************************************************************************** TEasyGridSmallIconGroup = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; procedure SetCellSize(Value: TEasyCellSize); override; public end; // ************************************************************************** // TEasyGridListGroup // Builds the List Grid for the Group // ************************************************************************** TEasyGridListGroup = class(TEasyGridGroup) protected function AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; override; function GetCellSize: TEasyCellSize; override; procedure SetCellSize(Value: TEasyCellSize); override; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); override; procedure FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); override; procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); override; end; // ************************************************************************** // TEasyGridReportGroup // Builds the Report Grid for the Group // ************************************************************************** TEasyGridReportGroup = class(TEasyGridGroup) protected function AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; override; function GetCellSize: TEasyCellSize; override; procedure SetCellSize(Value: TEasyCellSize); override; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); override; procedure FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); override; procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); override; end; // ************************************************************************** // TEasyGridThumbnailGroup // Builds the Thumbnail Grid for the Group // ************************************************************************** TEasyGridThumbnailGroup = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; procedure AutoSizeCells; override; procedure SetCellSize(Value: TEasyCellSize); override; public end; // ************************************************************************** // TEasyGridTileGroup // Builds the Tile Grid for the Group // ************************************************************************** TEasyGridTileGroup = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; procedure SetCellSize(Value: TEasyCellSize); override; public procedure FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); override; end; // ************************************************************************** // TEasyGridFilmStripGroup // Builds the List Grid for the Group // ************************************************************************** TEasyGridFilmStripGroup = class(TEasyGridListGroup) protected function GetCellSize: TEasyCellSize; override; procedure AutoSizeCells; override; procedure SetCellSize(Value: TEasyCellSize); override; end; // ************************************************************************** // TEasyGridGridGroup // Builds the Report Grid for the Group // ************************************************************************** TEasyGridGridGroup = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; procedure SetCellSize(Value: TEasyCellSize); override; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); override; procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); override; end; TEasyGridSingleColumn = class(TEasyGridGroup) protected function GetCellSize: TEasyCellSize; override; function GetMaxColumns(Group: TEasyGroup; WindowWidth: Integer): Integer; override; procedure AutoSizeCells; override; procedure SetCellSize(Value: TEasyCellSize); override; public procedure FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); override; end; // ************************************************************************** // TGridTaskBandGroup // Builds the Report Grid for the Group in the Taskband control // ************************************************************************** TEasyGridTaskBandGroup = class(TEasyGridSingleColumn) private FCellSize: TEasyCellSize; protected function GetCellSize: TEasyCellSize; override; function StaticTopItemMargin: Integer; override; function StaticTopMargin: Integer; override; procedure SetCellSize(Value: TEasyCellSize); override; property CellSize: TEasyCellSize read FCellSize write FCellSize; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); override; destructor Destroy; override; end; // ************************************************************************** // Grid for the TEasyTaskPanel component // ************************************************************************** TEasyGridGroupTaskPanel = class(TEasyGridSingleColumn) private FCellSize: TEasyCellSize; protected function GetCellSize: TEasyCellSize; override; function StaticTopMargin: Integer; override; procedure SetCellSize(Value: TEasyCellSize); override; public constructor Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); override; destructor Destroy; override; procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); override; published end; // ************************************************************************** // TEasyGroupBase // Collection Item that represents a single group in the Listview // ************************************************************************** TEasyGroup = class(TEasyCollectionItem) private FExpanded: Boolean; // Is the group expanded/collapsed FGrid: TEasyGridGroup; // The UI grid that defines the item positions FItems: TEasyItems; // The List of Items (TEasyItems) in the group FKey: LongWord; FView: TEasyViewGroup; FVisibleItems: TList; function GetBandBlended: Boolean; function GetBandColor: TColor; function GetBandColorFade: TColor; function GetBandEnabled: Boolean; function GetBandFullWidth: Boolean; function GetBandIndent: Integer; function GetBandLength: Integer; function GetBandMargin: Integer; function GetBandRadius: Byte; function GetBandThickness: Integer; function GetClientRect: TRect; function GetExpandable: Boolean; function GetExpandImageIndent: Integer; function GetGrid: TEasyGridGroup; function GetGridClass: TEasyGridGroupClass; function GetItem(Index: Integer): TEasyItem; function GetItemCount: Integer; function GetMarginBottom: TEasyFooterMargin; function GetMarginLeft: TEasyMargin; function GetMarginRight: TEasyMargin; function GetMarginTop: TEasyHeaderMargin; function GetOwnerGroups: TEasyGroups; function GetOwnerListview: TCustomEasyListview; function GetPaintInfo: TEasyPaintInfoBaseGroup; function GetView: TEasyViewGroup; function GetViewClass: TEasyViewGroupClass; function GetVisibleCount: Integer; function GetVisibleItem(Index: Integer): TEasyItem; procedure SetBandBlended(Value: Boolean); procedure SetBandColor(Value: TColor); procedure SetBandColorFade(Value: TColor); procedure SetBandEnabled(Value: Boolean); procedure SetBandFullWidth(Value: Boolean); procedure SetBandIndent(Value: Integer); procedure SetBandLength(Value: Integer); procedure SetBandMargin(Value: Integer); procedure SetBandRadius(Value: Byte); procedure SetBandThickness(Value: Integer); procedure SetExpandable(Value: Boolean); procedure SetExpanded(Value: Boolean); virtual; procedure SetExpandImageIndent(Value: Integer); procedure SetItem(Index: Integer; Value: TEasyItem); procedure SetMarginBottom(Value: TEasyFooterMargin); procedure SetMarginLeft(Value: TEasyMargin); procedure SetMarginRight(Value: TEasyMargin); procedure SetMarginTop(Value: TEasyHeaderMargin); procedure SetPaintInfo(const Value: TEasyPaintInfoBaseGroup); protected function CanChangeBold(NewValue: Boolean): Boolean; override; function CanChangeCheck(NewValue: Boolean): Boolean; override; function CanChangeEnable(NewValue: Boolean): Boolean; override; function CanChangeFocus(NewValue: Boolean): Boolean; override; function CanChangeHotTracking(NewValue: Boolean): Boolean; override; function CanChangeSelection(NewValue: Boolean): Boolean; override; function CanChangeVisibility(NewValue: Boolean): Boolean; override; function DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; override; function GetDefaultGridClass: TEasyGridGroupClass; virtual; function GetDefaultViewClass: TEasyViewGroupClass; virtual; function LocalPaintInfo: TEasyPaintInfoBasic; override; procedure Freeing; override; procedure GainingBold; override; procedure GainingCheck; override; procedure GainingEnable; override; procedure GainingFocus; override; procedure GainingGhosted; override; procedure GainingHilight; override; procedure GainingHotTracking(MousePos: TPoint); override; procedure GainingSelection; override; procedure GainingVisibility; override; procedure Initialize; override; procedure LosingBold; override; procedure LosingCheck; override; procedure LosingEnable; override; procedure LosingFocus; override; procedure LosingGhosted; override; procedure LosingHilight; override; procedure LosingHotTracking; override; procedure LosingSelection; override; procedure LosingVisibility; override; property Alignment; property BandBlended: Boolean read GetBandBlended write SetBandBlended default True; property BandColor: TColor read GetBandColor write SetBandColor default clBlue; property BandColorFade: TColor read GetBandColorFade write SetBandColorFade default clWindow; property BandEnabled: Boolean read GetBandEnabled write SetBandEnabled default True; property BandFullWidth: Boolean read GetBandFullWidth write SetBandFullWidth default False; property BandIndent: Integer read GetBandIndent write SetBandIndent default 0; property BandLength: Integer read GetBandLength write SetBandLength default 300; property BandMargin: Integer read GetBandMargin write SetBandMargin default 0; property BandRadius: Byte read GetBandRadius write SetBandRadius default 4; property BandThickness: Integer read GetBandThickness write SetBandThickness default 3; property CaptionIndent; property CheckFlat; property CheckIndent; property CheckSize; property CheckType; property Expandable: Boolean read GetExpandable write SetExpandable default True; property ExpandImageIndent: Integer read GetExpandImageIndent write SetExpandImageIndent default 4; property ImageIndent; property Key: LongWord read FKey write FKey; property MarginBottom: TEasyFooterMargin read GetMarginBottom write SetMarginBottom; property MarginLeft: TEasyMargin read GetMarginLeft write SetMarginLeft; property MarginRight: TEasyMargin read GetMarginRight write SetMarginRight; property MarginTop: TEasyHeaderMargin read GetMarginTop write SetMarginTop; property OwnsPaintInfo; property PaintInfo: TEasyPaintInfoBaseGroup read GetPaintInfo write SetPaintInfo; property VAlignment default cvaCenter; property VisibleItem[Index: Integer]: TEasyItem read GetVisibleItem; property VisibleItems: TList read FVisibleItems write FVisibleItems; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; function BoundsRectBkGnd: TRect; function BoundsRectBottomMargin: TRect; function BoundsRectLeftMargin: TRect; function BoundsRectRightMargin: TRect; function BoundsRectTopMargin: TRect; function EditAreaHitPt(ViewportPoint: TPoint): Boolean; override; function HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyGroupHitTestInfoSet): Boolean; function ItemByPoint(ViewportPoint: TPoint): TEasyItem; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure Paint(MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; ACanvas: TCanvas); procedure Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); function SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; override; function SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; property Bold; property Caption; property Checked; property ClientRect: TRect read GetClientRect; property Cut; property Enabled; property Expanded: Boolean read FExpanded write SetExpanded default True; property Focused; property Grid: TEasyGridGroup read GetGrid; property GridClass: TEasyGridGroupClass read GetGridClass; property ImageIndex; property ImageOverlayIndex; property Item[Index: Integer]: TEasyItem read GetItem write SetItem; default; property ItemCount: Integer read GetItemCount; property Items: TEasyItems read FItems write FItems; property OwnerListview: TCustomEasyListview read GetOwnerListview; property OwnerGroups: TEasyGroups read GetOwnerGroups; property View: TEasyViewGroup read GetView; property ViewClass: TEasyViewGroupClass read GetViewClass; property Visible; property VisibleCount: Integer read GetVisibleCount; end; TEasyGroupInterfaced = class(TEasyGroup) protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; public property DataInf; end; TEasyBaseGroupStored = class(TEasyGroup) private FDataHelper: TEasyDynamicDataHelper; protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger ; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; property DataHelper: TEasyDynamicDataHelper read FDataHelper write FDataHelper; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; end; TEasyGroupStored = class(TEasyBaseGroupStored) published property Caption; property Bold; property Checked; property Cut; property Enabled; property Expanded; property ImageIndex; property ImageOverlayIndex; property Items; property Tag; property Visible; end; // // Group for the TEasyTaskPanel component // TEasyGroupTaskPanel = class(TEasyBaseGroupStored) private FHeight: Integer; FTaskPanel: TEasyTaskPanelForm; function GetTaskWindowCreated: Boolean; procedure SetExpanded(Value: Boolean); override; procedure SetHeight(const Value: Integer); procedure SetInitialized(Value: Boolean); override; protected procedure CreateTaskWindow; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; property TaskPanel: TEasyTaskPanelForm read FTaskPanel; published property Caption; property Bold; property Checked; property Cut; property Enabled; property Expanded; property Height: Integer read FHeight write SetHeight default 100; property ImageIndex; property ImageOverlayIndex; property Tag; property TaskWindowCreated: Boolean read GetTaskWindowCreated; property Visible; end; TEasyGroupVirtual = class(TEasyGroup) protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; end; // ************************************************************************** // TEasyViewGroup // Implements the basis for the UI (drawing, and mouse interaction) for a EasyGroup // ************************************************************************** TEasyViewGroup = class(TEasyOwnedPersistentGroupItem) protected function CustomExpandImages: Boolean; procedure GetCollapseExpandImages(var Expand, Collapse: TBitmap); public function EditAreaHitPt(Group: TEasyGroup; ViewportPoint: TPoint): Boolean; virtual; function GetImageList(Group: TEasyGroup): TCustomImageList; procedure GetExpandImageSize(Group: TEasyGroup; var ImageW, ImageH: Integer); virtual; procedure GetImageSize(Group: TEasyGroup; var ImageW, ImageH: Integer); virtual; procedure GroupRectArray(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; var RectArray: TEasyRectArrayObject); virtual; procedure LoadTextFont(Group: TEasyGroup; ACanvas: TCanvas); virtual; procedure Paint(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; ACanvas: TCanvas); virtual; procedure PaintAfter(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintBackground(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintBand(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintBefore(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintCheckBox(Group: TEasyGroup; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); virtual; procedure PaintExpandButton(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintFocusRect(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintImage(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintSelectionRect(Group: TEasyGroup; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; procedure PaintText(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; function SelectionHit(Group: TEasyGroup; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; virtual; function SelectionHitPt(Group: TEasyGroup; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; virtual; end; // ************************************************************************** // TEasyViewTaskBandGroup // Implements the basis for the UI (drawing, and mouse interaction) for a EasyGroup // in the TaskBand control // ************************************************************************** TEasyViewTaskBandGroup = class(TEasyViewGroup) protected function DrawThemed: Boolean; virtual; procedure PaintTextTopThemed(ACanvas: TCanvas; Group: TEasyGroup; ObjRect: TRect; RectArray: TEasyRectArrayObject); virtual; public procedure GetExpandImageSize(Group: TEasyGroup; var ImageW: Integer; var ImageH: Integer); override; procedure GroupRectArray(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; var RectArray: TEasyRectArrayObject); override; procedure LoadTextFont(Group: TEasyGroup; ACanvas: TCanvas); override; procedure PaintBackground(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); override; procedure PaintBand(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); override; procedure PaintExpandButton(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); override; procedure PaintText(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); override; end; // ************************************************************************** // TEasyViewTaskPanelGroup // Implements the basis for the UI (drawing, and mouse interaction) for a EasyGroup // in the TaskPanel control // ************************************************************************** TEasyViewTaskPanelGroup = class(TEasyViewTaskBandGroup) protected public procedure PaintBefore(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); override; end; // ************************************************************************** // TEasyGroups // Collection that contains all the Groups in the control // ************************************************************************** TEasyGroups = class(TEasyCollection) private FGroupsState: TEasyGroupsStates; FStreamGroups: Boolean; function GetCellHeight: Integer; function GetCellWidth: Integer; function GetGroup(Index: Integer): TEasyGroup; function GetItemCount: Integer; function GetViewRect: TRect; function GetVisibleGroup(Index: Integer): TEasyGroup; procedure SetCellHeight(Value: Integer); procedure SetCellWidth(Value: Integer); procedure SetGroup(Index: Integer; Value: TEasyGroup); protected function FirstGroupInternal(VisibleOnly: Boolean): TEasyGroup; function FirstInGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean): TEasyItem; function FirstItemInternal(NextItemType: TEasyNextItemType): TEasyItem; function LastGroupInternal(VisibleOnly: Boolean): TEasyGroup; function LastInGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean): TEasyItem; function LastItemInternal(NextItemType: TEasyNextItemType): TEasyItem; function NavigateGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean; Direction: TEasySearchDirection): TEasyGroup; function NavigateInGroupInternal(Group: TEasyGroup; Item: TEasyItem; VisibleOnly: Boolean; Direction: TEasySearchDirection): TEasyItem; function NavigateItemInternal(Item: TEasyItem; NextItemType: TEasyNextItemType; Direction: TEasySearchDirection): TEasyItem; procedure DoStructureChange; override; property GroupsState: TEasyGroupsStates read FGroupsState write FGroupsState; property VisibleGroup[Index: Integer]: TEasyGroup read GetVisibleGroup; public constructor Create(AnOwner: TCustomEasyListview); reintroduce; virtual; destructor Destroy; override; function Add(Data: TObject = nil): TEasyGroup; function AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyGroupInterfaced; function AddVirtual(Data: TObject = nil): TEasyGroupVirtual; function AddCustom(CustomGroup: TEasyGroupClass; Data: TObject = nil): TEasyGroup; function AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; function CanMoveDown: Boolean; function CanMoveUp: Boolean; procedure Clear(FreeItems: Boolean = True); override; procedure CollapseAll; procedure DeleteGroup(Group: TEasyGroup); procedure DeleteItem(Item: TEasyItem); procedure DeleteItems(ItemArray: TEasyItemArray); procedure ExpandAll; function FirstGroup: TEasyGroup; function FirstGroupInRect(ViewportRect: TRect): TEasyGroup; function FirstInGroup(Group: TEasyGroup): TEasyItem; function FirstInitializedItem: TEasyItem; function FirstItem: TEasyItem; function FirstItemInRect(ViewportRect: TRect): TEasyItem; function FirstVisibleGroup: TEasyGroup; function FirstVisibleInGroup(Group: TEasyGroup): TEasyItem; function FirstVisibleItem: TEasyItem; function GroupByPoint(ViewportPoint: TPoint): TEasyGroup; function Insert(Index: Integer; Data: TObject = nil): TEasyGroup; function InsertCustom(Index: Integer; CustomGroup: TEasyGroupClass; Data: TObject = nil): TEasyGroup; function InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject): TEasyGroupInterfaced; function InsertVirtual(Index: Integer; Data: TObject = nil): TEasyGroupVirtual; procedure InitializeAll; procedure InvalidateItem(Item: TEasyCollectionItem; ImmediateUpdate: Boolean); function LastGroup: TEasyGroup; function LastInGroup(Group: TEasyGroup): TEasyItem; function LastInitializedItem: TEasyItem; function LastItem: TEasyItem; function LastVisibleGroup: TEasyGroup; function LastVisibleInGroup(Group: TEasyGroup): TEasyItem; function LastVisibleItem: TEasyItem; function ItemByPoint(ViewportPoint: TPoint): TEasyItem; function MoveDown: Boolean; function MoveUp: Boolean; function NextEditableItem(Item: TEasyItem): TEasyItem; function NextGroup(Group: TEasyGroup): TEasyGroup; function NextGroupInRect(Group: TEasyGroup; ViewportRect: TRect): TEasyGroup; function NextInitializedItem(Item: TEasyItem): TEasyItem; function NextInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; function NextItem(Item: TEasyItem): TEasyItem; function NextItemInRect(Item: TEasyItem; ViewportRect: TRect): TEasyItem; function NextVisibleGroup(Group: TEasyGroup): TEasyGroup; function NextVisibleGroupWithVisibleItems(Group: TEasyGroup): TEasyGroup; function NextVisibleInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; function NextVisibleItem(Item: TEasyItem): TEasyItem; function PrevEditableItem(Item: TEasyItem): TEasyItem; function PrevGroup(Group: TEasyGroup): TEasyGroup; function PrevInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; function PrevInitializedItem(Item: TEasyItem): TEasyItem; function PrevItem(Item: TEasyItem): TEasyItem; function PrevVisibleGroup(Group: TEasyGroup): TEasyGroup; function PrevVisibleGroupWithVisibleItems(Group: TEasyGroup): TEasyGroup; function PrevVisibleInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; function PrevVisibleItem(Item: TEasyItem): TEasyItem; procedure LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; procedure MakeAllVisible; override; procedure Move(Item: TEasyItem; NewGroup: TEasyGroup); procedure Rebuild(Force: Boolean = False); virtual; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; procedure UnInitializeAll; property CellHeight: Integer read GetCellHeight write SetCellHeight; property CellWidth: Integer read GetCellWidth write SetCellWidth; property Groups[Index: Integer]: TEasyGroup read GetGroup write SetGroup; default; property ItemCount: Integer read GetItemCount; property StreamGroups: Boolean read FStreamGroups write FStreamGroups default True; property ViewRect: TRect read GetViewRect; end; // Specical Groups container and Groups for the TEasyTaskPanel component TEasyGroupsTaskPanel = class(TEasyGroups) private function GetGroup(Index: Integer): TEasyGroupTaskPanel; procedure SetGroup(Index: Integer; Value: TEasyGroupTaskPanel); public constructor Create(AnOwner: TCustomEasyListview); override; property Groups[Index: Integer]: TEasyGroupTaskPanel read GetGroup write SetGroup; default; end; // ************************************************************************** // TEasyCellSize // Maintains the default sizes for the Cells a single view (grid) // ************************************************************************** TEasyCellSize = class(TEasyOwnedPersistent) private FAutoSize: Boolean; FAutoSizeHeight: Integer; // Dynamic size that is reset with each rebuid of the Groups if the Grid is AutoSized FAutoSizeWidth: Integer; // Dynamic size that is reset with each rebuid of the Groups if the Grid is AutoSized FHeight: Integer; // Fixed size that remains constant with each rebuid of the Groups if the Grid is not AutoSized FWidth: Integer; // Fixed size that remains constant with each rebuid of the Groups if the Grid is not AutoSized function GetHeight: Integer; function GetWidth: Integer; procedure SetAutoSize(const Value: Boolean); procedure SetHeight(Value: Integer); procedure SetWidth(Value: Integer); protected property AutoSizeHeight: Integer read FAutoSizeHeight write FAutoSizeHeight; property AutoSizeWidth: Integer read FAutoSizeWidth write FAutoSizeWidth; public constructor Create(AnOwner: TCustomEasyListview); override; procedure Assign(Source: TPersistent); override; procedure SetSize(AWidth, AHeight: Integer); published property AutoSize: Boolean read FAutoSize write SetAutoSize default False; property Height: Integer read GetHeight write SetHeight default 75; property Width: Integer read GetWidth write SetWidth default 75; end; // ************************************************************************** // TEasyCellSizeIcon // Maintains the default sizes for the Cells a Icon view // ************************************************************************** TEasyCellSizeIcon = class(TEasyCellSize) end; // ************************************************************************** // TEasyCellSizeSmallIcon // Maintains the default sizes for the Cells a Small Icon view // ************************************************************************** TEasyCellSizeSmallIcon = class(TEasyCellSize) public constructor Create(AnOwner: TCustomEasyListview); override; published property Width default 200; property Height default 17; end; // ************************************************************************** // TEasyCellSizeThumbnail // Maintains the default sizes for the Cells a Thumbnail view // ************************************************************************** TEasyCellSizeThumbnail = class(TEasyCellSize) public constructor Create(AnOwner: TCustomEasyListview); override; published property Width default 125; property Height default 143; end; // ************************************************************************** // TEasyCellSizeTile // Maintains the default sizes for the Cells a Tile view // ************************************************************************** TEasyCellSizeTile = class(TEasyCellSize) public constructor Create(AnOwner: TCustomEasyListview); override; published property Width default 218; property Height default 58; end; // ************************************************************************** // TEasyCellSizeList // Maintains the default sizes for the Cells a List view // ************************************************************************** TEasyCellSizeList = class(TEasyCellSize) public constructor Create(AnOwner: TCustomEasyListview); override; published property Width default 200; property Height default 17; end; // ************************************************************************** // TEasyCellSizeReport // Maintains the default sizes for the Cells a Report view // ************************************************************************** TEasyCellSizeReport = class(TEasyCellSize) public constructor Create(AnOwner: TCustomEasyListview); override; published property Width default 75; property Height default 17; end; // ************************************************************************** // TEasyCellSizeFilmStrip // Maintains the default sizes for the Cells a FilmStrip view // ************************************************************************** TEasyCellSizeFilmStrip = class(TEasyCellSizeThumbnail) end; // ************************************************************************** // TEasyCellGrid // Maintains the default sizes for the Cells a FilmStrip view // ************************************************************************** TEasyCellGrid = class(TEasyCellSizeReport) end; // ************************************************************************** // TEasyCellSizes // Maintains the default sizes for the Cells in each view // ************************************************************************** TEasyCellSizes = class(TEasyOwnedPersistent) private FFilmStrip: TEasyCellSize; FIcon: TEasyCellSize; FList: TEasyCellSize; FReport: TEasyCellSize; FSmallIcon: TEasyCellSize; FGrid: TEasyCellSize; FThumbnail: TEasyCellSize; FTile: TEasyCellSize; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; published property FilmStrip: TEasyCellSize read FFilmStrip write FFilmStrip; property Icon: TEasyCellSize read FIcon write FIcon; property SmallIcon: TEasyCellSize read FSmallIcon write FSmallIcon; property Grid: TEasyCellSize read FGrid write FGrid; property Thumbnail: TEasyCellSize read FThumbnail write FThumbnail; property Tile: TEasyCellSize read FTile write FTile; property List: TEasyCellSize read FList write FList; property Report: TEasyCellSize read FReport write FReport; end; TEasyColumnDropDownButtonState = ( cdbsHovering, // Mouse is hovering over the button cdbsDown, // Mouse is pressing the button cdbsClickPending // Button was pressed down and held while on the button, may have been moved off the button ); TEasyColumnDropDownButtonStates = set of TEasyColumnDropDownButtonState; TEasyColumnDropDownButton = class(TPersistent) private FAlwaysShow: Boolean; // By default the button only shows when the mouse is hovering over the column header FEnabled: Boolean; FMenu: TPopupMenu; FOwner: TEasyColumn; FState: TEasyColumnDropDownButtonStates; FVisible: Boolean; procedure SetAlwaysShow(const Value: Boolean); procedure SetEnabled(const Value: Boolean); procedure SetVisible(const Value: Boolean); public property State: TEasyColumnDropDownButtonStates read FState write FState; published constructor Create(AnOwner: TEasyColumn); property AlwaysShow: Boolean read FAlwaysShow write SetAlwaysShow default False; property Enabled: Boolean read FEnabled write SetEnabled default True; property Menu: TPopupMenu read FMenu write FMenu; property Owner: TEasyColumn read FOwner; property Visible: Boolean read FVisible write SetVisible default False; end; // ************************************************************************** // TEasyColumn // Collection Item that represents a single column in the Listview // ************************************************************************** TEasyColumn = class(TEasyCollectionItem) private FAlignment: TAlignment; FAutoSizeOnDblClk: Boolean; // Autosizes column when double clicked in size area FAutoSortOnClick: Boolean; FAutoSpring: Boolean; // Sizes column based on width of window FAutoToggleSortGlyph: Boolean; FClickable: Boolean; FDropDownButton: TEasyColumnDropDownButton; FPosition: Integer; FSortDirection: TEasySortDirection; FSpringRest: Single; FStyle: TEasyHeaderButtonStyle; FView: TEasyViewColumn; FWidth: Integer; function GetAlignment: TAlignment; function GetColor: TColor; function GetHotTrack: Boolean; function GetImagePosition: TEasyHeaderImagePosition; function GetOwnerColumns: TEasyColumns; function GetOwnerHeader: TEasyHeader; function GetPaintInfo: TEasyPaintInfoColumn; function GetSortGlyphAlign: TEasySortGlyphAlign; function GetSortGlyphIndent: Integer; function GetStyle: TEasyHeaderButtonStyle; function GetView: TEasyViewColumn; function GetViewClass: TEasyViewColumnClass; procedure SetAlignment(Value: TAlignment); procedure SetAutoSpring(const Value: Boolean); procedure SetColor(Value: TColor); procedure SetHotTrack(Value: Boolean); procedure SetImagePosition(Value: TEasyHeaderImagePosition); procedure SetPaintInfo(Value: TEasyPaintInfoColumn); procedure SetPosition(Value: Integer); procedure SetSortDirection(Value: TEasySortDirection); procedure SetSortGlpyhAlign(Value: TEasySortGlyphAlign); procedure SetSortGlyphIndent(Value: Integer); procedure SetStyle(Value: TEasyHeaderButtonStyle); procedure SetWidth(Value: Integer); protected function CanChangeBold(NewValue: Boolean): Boolean; override; function CanChangeCheck(NewValue: Boolean): Boolean; override; function CanChangeEnable(NewValue: Boolean): Boolean; override; function CanChangeFocus(NewValue: Boolean): Boolean; override; function CanChangeHotTracking(NewValue: Boolean): Boolean; override; function CanChangeSelection(NewValue: Boolean): Boolean; override; function CanChangeVisibility(NewValue: Boolean): Boolean; override; function DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; override; function GetDefaultViewClass: TEasyViewColumnClass; virtual; function LocalPaintInfo: TEasyPaintInfoBasic; override; procedure AutoSizeToFit; virtual; procedure Freeing; override; procedure GainingBold; override; procedure GainingCheck; override; procedure GainingEnable; override; procedure GainingFocus; override; procedure GainingGhosted; override; procedure GainingHilight; override; procedure GainingHotTracking(MousePos: TPoint); override; procedure GainingSelection; override; procedure GainingVisibility; override; procedure Initialize; override; procedure LosingBold; override; procedure LosingCheck; override; procedure LosingEnable; override; procedure LosingFocus; override; procedure LosingGhosted; override; procedure LosingHilight; override; procedure LosingHotTracking; override; procedure LosingSelection; override; procedure LosingVisibility; override; property Color: TColor read GetColor write SetColor; property HotTrack: Boolean read GetHotTrack write SetHotTrack; property ImagePosition: TEasyHeaderImagePosition read GetImagePosition write SetImagePosition; property SortGlyphAlign: TEasySortGlyphAlign read GetSortGlyphAlign write SetSortGlpyhAlign; property SortGlyphIndent: Integer read GetSortGlyphIndent write SetSortGlyphIndent; property SpringRest: Single read FSpringRest write FSpringRest; property Style: TEasyHeaderButtonStyle read GetStyle write SetStyle; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; function EditAreaHitPt(ViewportPoint: TPoint): Boolean; override; function HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyColumnHitTestInfoSet): Boolean; function PaintMouseHovering: Boolean; procedure Invalidate(ImmediateUpdate: Boolean); override; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure MakeVisible(Position: TEasyMakeVisiblePos); override; procedure Paint(ACanvas: TCanvas; HeaderType: TEasyHeaderType); function SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; override; function SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; property Alignment: TAlignment read GetAlignment write SetAlignment default taLeftJustify; property AutoSizeOnDblClk: Boolean read FAutoSizeOnDblClk write FAutoSizeOnDblClk default True; property AutoSortOnClick: Boolean read FAutoSortOnClick write FAutoSortOnClick default False; property AutoSpring: Boolean read FAutoSpring write SetAutoSpring default False; property AutoToggleSortGlyph: Boolean read FAutoToggleSortGlyph write FAutoToggleSortGlyph default True; property Bold; property Caption; property Checked; property Clickable: Boolean read FClickable write FClickable default True; property Clicking; property DropDownButton: TEasyColumnDropDownButton read FDropDownButton write FDropDownButton; property Enabled; property ImageIndex; property ImageOverlayIndex; property OwnerColumns: TEasyColumns read GetOwnerColumns; property OwnerHeader: TEasyHeader read GetOwnerHeader; property OwnsPaintInfo; property PaintInfo: TEasyPaintInfoColumn read GetPaintInfo write SetPaintInfo; property Position: Integer read FPosition write SetPosition; property Selected; property SortDirection: TEasySortDirection read FSortDirection write SetSortDirection default esdNone; property Tag; property View: TEasyViewColumn read GetView; property ViewClass: TEasyViewColumnClass read GetViewClass; property Visible; property Width: Integer read FWidth write SetWidth default 50; end; TEasyColumnInterfaced = class(TEasyColumn) protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; public property DataInf; end; TEasyColumnStored = class(TEasyColumn) private FDataHelper: TEasyDynamicDataHelper; protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; property DataHelper: TEasyDynamicDataHelper read FDataHelper write FDataHelper; public constructor Create(ACollection: TEasyCollection); override; destructor Destroy; override; procedure LoadFromStream(S: TStream; var Version: Integer); override; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; published property Alignment; property AutoSizeOnDblClk; property AutoSortOnClick; property AutoSpring; property AutoToggleSortGlyph; property Bold; property Caption; property Checked; property Clickable; property Color; property DropDownButton; property Enabled; property ImageIndex; property ImageOverlayIndex; property Position; property Selected; property SortDirection; property Width; property Visible; end; TEasyColumnVirtual = class(TEasyColumn) protected function GetCaptions(Line: Integer): Widestring; override; function GetDetailCount: Integer; override; function GetDetails(Line: Integer): Integer; override; function GetImageIndexes(Column: Integer): TCommonImageIndexInteger; override; function GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; override; function GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; override; procedure ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); override; procedure ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); override; procedure ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); override; procedure SetCaptions(Column: Integer; Value: Widestring); override; procedure SetDetailCount(Value: Integer); override; procedure SetDetails(Line: Integer; Value: Integer); override; procedure SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); override; procedure ThumbnailDraw(ACanvas: TCanvas; ARect: TRect;AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); override; end; // ************************************************************************** // TEasyViewColumn // Implements the basis for the UI (drawing, and mouse interaction) for a EasyColumn // ************************************************************************** TEasyViewColumn = class(TEasyOwnedPersistentView) public function EditAreaHitPt(Column: TEasyColumn; ViewportPoint: TPoint): Boolean; virtual; function GetImageList(Column: TEasyColumn): TCustomImageList; procedure CalculateTextRect(Column: TEasyColumn; Canvas: TControlCanvas; var TextR: TRect); virtual; procedure GetImageSize(Column: TEasyColumn; var ImageW, ImageH: Integer); function ItemRect(Column: TEasyColumn; RectType: TEasyCellRectType): TRect; virtual; procedure ItemRectArray(Column: TEasyColumn; var RectArray: TEasyRectArrayObject); virtual; procedure LoadTextFont(Column: TEasyColumn; ACanvas: TCanvas); virtual; procedure Paint(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType); virtual; procedure PaintAfter(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintBefore(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintBkGnd(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintCheckBox(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintDropDownArrow(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintDropGlyph(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintFocusRect(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintImage(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject; ImageSize: TEasyImageSize); virtual; function PaintImageSize(Column: TEasyColumn; HeaderType: TEasyHeaderType): TEasyImageSize; virtual; procedure PaintSortGlyph(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); virtual; procedure PaintText(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject; LinesToDraw: Integer); virtual; procedure ReSizeRectArray(var RectArray: TEasyRectArrayObjectArray); virtual; function SelectionHit(Column: TEasyColumn; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; virtual; function SelectionHitPt(Column: TEasyColumn; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; virtual; end; // ************************************************************************** // TEasyGroups // Collection that contains all the Columns in the control // ************************************************************************** TEasyColumns = class(TEasyCollection) private function GetColumns(Index: Integer): TEasyColumn; function GetOwnerHeader: TEasyHeader; procedure SetColumns(Index: Integer; Value: TEasyColumn); protected procedure DoItemAdd(Item: TEasyCollectionItem; Index: Integer); override; procedure DoStructureChange; override; public constructor Create(AnOwner: TCustomEasyListview); reintroduce; virtual; destructor Destroy; override; function Add(Data: TObject = nil): TEasyColumn; function AddInterfaced(const DataInf: IUnknown; Data: TObject): TEasyColumnInterfaced; function AddVirtual(Data: TObject = nil): TEasyColumnVirtual; function AddCustom(CustomItem: TEasyColumnClass; Data: TObject = nil): TEasyColumn; function ColumnByPoint(ViewportPoint: TPoint): TEasyColumn; function Insert(Index: Integer; Data: TObject = nil): TEasyColumn; function InsertCustom(Index: Integer; CustomColumn: TEasyColumnClass; Data: TObject = nil): TEasyColumn; function InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyColumnInterfaced; function InsertVirtual(Index: Integer; Data: TObject = nil): TEasyColumnVirtual; procedure Clear(FreeItems: Boolean = True); override; property Columns[Index: Integer]: TEasyColumn read GetColumns write SetColumns; default; property OwnerHeader: TEasyHeader read GetOwnerHeader; end; TColumnPos = class(TList) private function Get(Index: Integer): TEasyColumn; procedure Put(Index: Integer; Item: TEasyColumn); public property Items[Index: Integer]: TEasyColumn read Get write Put; default; end; // ************************************************************************** // TEasyHeader // Header area of the Listview // ************************************************************************** TEasyHeader = class(TEasyOwnedPersistent) private FAutoSizeHeight: Boolean; FAutoSizeHeightMargin: Integer; FCanvasStore: TEasyCanvasStore; FColor: TColor; // Color of the header FColumns: TEasyColumns; // The columns that define the header FDisplayRect: TRect; // Rectangle occupied in the Client Window of the Listview, clips column not visible due to scrollbar position of LV FDragManager: TEasyHeaderDragManager; FDropDownHoverColumn: TEasyColumn; // Column that has the DropDownButton and the mouse over it (or button pressed) FFixedSingleColumn: Boolean; FFont: TFont; // The font the header text is drawn in FHeight: Integer; // Height of the header FHotTrackedColumn: TEasyColumn; // the column that is current in a hot tracked state FImages: TCustomImageList; // Images for the header columns FLastWidth: Integer; FPositions: TColumnPos; FPressColumn: TEasyColumn; // Column that currently pressed FResizeColumn: TEasyColumn; // Column that is currently being resized FShowInAllViews: Boolean; FSizeable: Boolean; // The column widths are resizeable by the mouse FState: TEasyHeaderStates; // Current state of the header FStreamColumns: Boolean; FViewRect: TRect; // The total size of the header including the column not visible in the current window FVisible: Boolean; // Shows/Hides the header in the control function GetCanvasStore: TEasyCanvasStore; function GetDisplayRect: TRect; function GetDraggable: Boolean; function GetFixedSingleColumn: Boolean; function GetHeight: Integer; function GetMouseCaptured: Boolean; function GetRuntimeHeight: Integer; procedure SetAutoSizeHeight(const Value: Boolean); procedure SetAutoSizeHeightMargin(const Value: Integer); procedure SetColor(Value: TColor); procedure SetDraggable(Value: Boolean); procedure SetDropDownHoverColumn(const Value: TEasyColumn); procedure SetFixedSingleColumn(const Value: Boolean); procedure SetFont(Value: TFont); procedure SetHeight(Value: Integer); procedure SetHotTrackedColumn(const Value: TEasyColumn); procedure SetImages(Value: TCustomImageList); procedure SetShowInAllViews(const Value: Boolean); procedure SetVisible(Value: Boolean); function GetViewWidth: Integer; protected function InCheckZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; function InDropDownButtonZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; function InHotTrackZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; function InPressZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; function InResizeZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; function IsFontStored: Boolean; procedure CaptureMouse; procedure ClearStates; procedure DoMouseDown(var Message: TWMMouse; Button: TCommonMouseButton; Shift: TShiftState; Column: TEasyColumn); procedure DoMouseMove(var Message: TWMMouse; Shift: TShiftState); procedure DoMouseUp(var Message: TWMMouse; Button: TCommonMouseButton; Shift: TShiftState; Column: TEasyColumn); procedure HandleHotTrack(Msg: TWMMouse; ForceClear: Boolean); procedure ReleaseMouse; procedure SizeFixedSingleColumn(NewWidth: Integer); procedure SpringColumns(NewWidth: Integer); procedure WMContextMenu(var Msg: TMessage); message WM_CONTEXTMENU; procedure WMLButtonDblClk(var Msg: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN; procedure WMLButtonUp(var Msg: TWMLButtonUp); message WM_LBUTTONUP; procedure WMMouseMove(var Msg: TWMMouseMove); message WM_MOUSEMOVE; procedure WMRButtonDown(var Msg: TWMRButtonDown); message WM_RBUTTONDOWN; procedure WMRButtonUp(var Msg: TWMRButtonUp); message WM_RBUTTONUP; procedure WMSize(var Msg: TWMSize); message WM_SIZE; property CanvasStore: TEasyCanvasStore read GetCanvasStore write FCanvasStore; property DropDownHoverColumn: TEasyColumn read FDropDownHoverColumn write SetDropDownHoverColumn; property HotTrackedColumn: TEasyColumn read FHotTrackedColumn write SetHotTrackedColumn; property LastWidth: Integer read FLastWidth write FLastWidth; property Positions: TColumnPos read FPositions write FPositions; property PressColumn: TEasyColumn read FPressColumn write FPressColumn; property ResizeColumn: TEasyColumn read FResizeColumn write FResizeColumn; property RuntimeHeight: Integer read GetRuntimeHeight; property State: TEasyHeaderStates read FState write FState; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; function FirstColumn: TEasyColumn; function FirstColumnByPosition: TEasyColumn; function FirstColumnInRect(ViewportRect: TRect): TEasyColumn; function FirstVisibleColumn: TEasyColumn; function LastColumn: TEasyColumn; function LastVisibleColumn: TEasyColumn; function NextColumn(AColumn: TEasyColumn): TEasyColumn; function NextColumnByPosition(AColumn: TEasyColumn): TEasyColumn; function NextVisibleColumn(Column: TEasyColumn): TEasyColumn; function PrevColumn(AColumn: TEasyColumn): TEasyColumn; function PrevColumnByPosition(AColumn: TEasyColumn): TEasyColumn; function PrevVisibleColumn(Column: TEasyColumn): TEasyColumn; procedure ClickColumn(Column: TEasyColumn); procedure Invalidate(ImmediateUpdate: Boolean); virtual; procedure InvalidateColumn(Item: TEasyColumn; ImmediateUpdate: Boolean); virtual; function LastColumnByPosition: TEasyColumn; function NextColumnInRect(Column: TEasyColumn; ViewportRect: TRect): TEasyColumn; procedure LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; procedure PaintTo(ACanvas: TCanvas; ARect: TRect); virtual; procedure Rebuild(Force: Boolean); virtual; procedure SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); override; property DisplayRect: TRect read GetDisplayRect write FDisplayRect; property MouseCaptured: Boolean read GetMouseCaptured; property StreamColumns: Boolean read FStreamColumns write FStreamColumns default True; property ViewRect: TRect read FViewRect; property ViewWidth: Integer read GetViewWidth; published property AutoSizeHeight: Boolean read FAutoSizeHeight write SetAutoSizeHeight default True; property AutoSizeHeightMargin: Integer read FAutoSizeHeightMargin write SetAutoSizeHeightMargin default 8; property Color: TColor read FColor write SetColor default clBtnFace; property Columns: TEasyColumns read FColumns write FColumns; property Draggable: Boolean read GetDraggable write SetDraggable default True; property DragManager: TEasyHeaderDragManager read FDragManager write FDragManager; property FixedSingleColumn: Boolean read GetFixedSingleColumn write SetFixedSingleColumn default False; property Font: TFont read FFont write SetFont stored IsFontStored; property Height: Integer read GetHeight write SetHeight default 21; property Images: TCustomImageList read FImages write SetImages; property ShowInAllViews: Boolean read FShowInAllViews write SetShowInAllViews default False; property Sizeable: Boolean read FSizeable write FSizeable default True; property Visible: Boolean read FVisible write SetVisible default False; end; // ************************************************************************** // TEasyEditManager // EasyEditManager defines the base class to edit an item. The // IEasyCellEditorSink allows the Editor to communicate back to the manager for // event dispatching without the need for the Editor interface to have knowledge // of the TManagerLink object. // ************************************************************************** TEasyEditManager = class(TEasyOwnedPersistent) private FAppHooked: Boolean; FAutoEditDelayTime: Integer; // Time (in milliseconds) before the object is edited FAutoEditStartClickPt: TPoint; // This is in WINDOW coordinates, the point where the mouse is clicked. Used to determine if the AutoEdit should begin FColor: TColor; FEditColumn: TEasyColumn; FEditFinished: Boolean; // Set when the edit is done FEditing: Boolean; // Set when the edit is in progress FEditItem: TEasyItem; // The Item that is being edited FEditor: IEasyCellEditor; FEnabled: Boolean; // The Edit Manager is enabled FFont: TFont; FTabEditColumns: Boolean; FTabMoveFocus: Boolean; // If an item is begin edited a tab move the focus to the next item and puts it in edit FTabMoveFocusColumn: TEasyColumn; FTabMoveFocusItem: TEasyItem; FTimer: TTimer; // The timer for auto Edit FTimerRunning: Boolean; // True when the auto Edit is timing out function GetEditing: Boolean; procedure SetEnabled(const Value: Boolean); procedure SetFont(const Value: TFont); protected function MainWindowHook(var Message: TMessage): Boolean; procedure StartAutoEditTimer; procedure StopAutoEditTimer; procedure TimerEvent(Sender: TObject); property AppHooked: Boolean read FAppHooked write FAppHooked; property AutoEditStartClickPt: TPoint read FAutoEditStartClickPt write FAutoEditStartClickPt; property EditColumn: TEasyColumn read FEditColumn write FEditColumn; property TabEditColumns: Boolean read FTabEditColumns write FTabEditColumns default False; property TabMoveFocusColumn: TEasyColumn read FTabMoveFocusColumn write FTabMoveFocusColumn; property TabMoveFocusItem: TEasyItem read FTabMoveFocusItem write FTabMoveFocusItem; property Timer: TTimer read FTimer write FTimer; property TimerRunning: Boolean read FTimerRunning; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure BeginEdit(Item: TEasyItem; Column: TEasyColumn); virtual; procedure EndEdit; property Editing: Boolean read GetEditing; property EditItem: TEasyItem read FEditItem; property Editor: IEasyCellEditor read FEditor write FEditor; published property AutoEditDelayTime: Integer read FAutoEditDelayTime write FAutoEditDelayTime default 300; property Color: TColor read FColor write FColor default clWindow; property Enabled: Boolean read FEnabled write SetEnabled default False; property Font: TFont read FFont write SetFont; property TabMoveFocus: Boolean read FTabMoveFocus write FTabMoveFocus default False; end; // ************************************************************************** // TEasyEnumFormatEtcManager // The EnumFormatEtc Manager encapsulates the IEnumFormatEtc interface for // use with the IDataObject (below) interface for Drag/Drop and Clipboard // operations. // ************************************************************************** TEasyEnumFormatEtcManager = class(TEasyInterfacedPersistent, IEnumFormatEtc) private FInternalIndex: integer; // Keeps an internal reference to which format is being enumerated FFormats: TFormatEtcArray; // Keeps a list of all formats that are avaialable in the IDataObject protected { IEnumFormatEtc } function Next(celt: Longint; out elt; pceltFetched: PLongint): HResult; stdcall; function Skip(celt: Longint): HResult; stdcall; function Reset: HResult; stdcall; function Clone(out Enum: IEnumFormatEtc): HResult; stdcall; property InternalIndex: integer read FInternalIndex write FInternalIndex; public constructor Create; destructor Destroy; override; property Formats: TFormatEtcArray read FFormats write FFormats; end; // ************************************************************************** // TEasyDataObjectManager // The Data Object Manager encapsulates the IDataObject interface into a // Delphi class. It is used for Drag/Drop and Clipboard operations // ************************************************************************** TEasyDataObjectManager = class(TCommonDataObject, IDataObject, ICommonDataObject, ICommonExtractObj) private FListview: TCustomEasyListview; protected procedure DoGetCustomFormats(var Formats: TFormatEtcArray); override; procedure DoOnGetData(const FormatEtcIn: TFormatEtc; var Medium: TStgMedium; var Handled: Boolean); override; procedure DoOnQueryGetData(const FormatEtcIn: TFormatEtc; var FormatAvailable: Boolean; var Handled: Boolean); override; public property Listview: TCustomEasyListview read FListview write FListview; end; // ************************************************************************** // TEasyDragManagerBase // Easy Base Drag Manager defines the common actions of the Drag Select // and object Drag Manager, including autoscroll // ************************************************************************** TCustomEasyDragManagerBase = class(TEasyOwnedPersistent) private FAutoScroll: Boolean; FAutoScrollDelay: Integer; FAutoScrollDelayMet: Boolean; FAutoScrollTime: Integer; FDataObject: IDataObject; FMouseButton: TCommonMouseButtons; // Defines what mouse buttons are used for a drag FRegistered: Boolean; FTimer: TTimer; FDragState: TEasyDragManagerStates; FLastKeyState: TCommonKeyStates; FEnabled: Boolean; FAutoScrollAccelerator: Byte; FAutoScrollMargin: Integer; function GetAutoScrolling: Boolean; function GetDragging: Boolean; function GetTimer: TTimer; procedure SetRegistered(Value: Boolean); protected procedure AutoScrollWindow; virtual; procedure DoAfterAutoScroll; virtual; procedure DoBeforeAutoScroll; virtual; procedure DoAutoScroll(DeltaX, DeltaY: Integer); virtual; procedure DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); virtual; procedure DoDragBegin(WindowPoint: TPoint; KeyState: TCommonKeyStates); virtual; procedure DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); virtual; procedure DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); virtual; procedure DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); virtual; procedure DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); virtual; procedure DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); virtual; procedure DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); virtual; function DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; virtual; function DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; virtual; function DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; virtual; function DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; virtual; procedure DoEnable(Enable: Boolean); virtual; function PtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; function PtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; function PtInAutoScrollRegion(WindowPoint: TPoint): Boolean; function PtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; function PtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; function ScrollDeltaDown(WindowPoint: TPoint): Integer; virtual; function ScrollDeltaLeft(WindowPoint: TPoint): Integer; virtual; function ScrollDeltaRight(WindowPoint: TPoint): Integer; virtual; function ScrollDeltaUp(WindowPoint: TPoint): Integer; virtual; procedure RegisterOLEDragDrop(DoRegister: Boolean); procedure SetEnabled(const Value: Boolean); virtual; procedure UpdateAfterAutoScroll; virtual; procedure VCLDragStart; virtual; property DataObject: IDataObject read FDataObject write FDataObject; property LastKeyState: TCommonKeyStates read FLastKeyState write FLastKeyState; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure BeginDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates); virtual; procedure Drag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); procedure DragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); procedure DragEnter(const ADataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); procedure DragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); procedure HandleTimer(Sender: TObject); virtual; procedure WMKeyDown(var Msg: TWMKeyDown); virtual; property AutoScroll: Boolean read FAutoScroll write FAutoScroll default True; property AutoScrollAccelerator: Byte read FAutoScrollAccelerator write FAutoScrollAccelerator default 2; property AutoScrollDelay: Integer read FAutoScrollDelay write FAutoScrollDelay default _AUTOSCROLLDELAY; property AutoScrollDelayMet: Boolean read FAutoScrollDelayMet; property AutoScrolling: Boolean read GetAutoScrolling; property AutoScrollMargin: Integer read FAutoScrollMargin write FAutoScrollMargin default 15; property AutoScrollTime: Integer read FAutoScrollTime write FAutoScrollTime default _AUTOSCROLLTIME; property Dragging: Boolean read GetDragging; property DragState: TEasyDragManagerStates read FDragState write FDragState; property Enabled: Boolean read FEnabled write SetEnabled; property MouseButton: TCommonMouseButtons read FMouseButton write FMouseButton default [cmbLeft]; property Timer: TTimer read GetTimer write FTimer; property Registered: Boolean read FRegistered write SetRegistered; published end; // ************************************************************************** // TEasyHeaderDragManager // Drag Manager is associated with the Header in the EasyListview for // dragging columns around // ************************************************************************** TEasyHeaderDragManager = class(TCustomEasyDragManagerBase) private FAllowDrop: Boolean; FColumn: TEasyColumn; FDefaultImageEvent: TGetDragImageEvent; FDragImageHeight: Integer; FDragImageWidth: Integer; FDragMode: TDragMode; // VCL Only FDragType: TEasyDragType; FEnableDragImage: Boolean; FHeader: TEasyHeader; FTargetColumn: TEasyColumn; function GetDragCursor: TCursor; function GetDragMode: TDragMode; procedure SetDragCursor(Value: TCursor); procedure SetDragMode(Value: TDragMode); procedure SetDragType(Value: TEasyDragType); protected function DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; override; procedure DefaultImage(Sender: TCustomEasyListview; Image: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); virtual; procedure DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoDragBegin(WindowPoint: TPoint; KeyStates: TCommonKeyStates); override; procedure DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); override; procedure DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); override; procedure DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); override; function DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; override; procedure ImageSize(var Width, Height: Integer); virtual; property AllowDrop: Boolean read FAllowDrop write FAllowDrop; property Column: TEasyColumn read FColumn write FColumn; property DefaultImageEvent: TGetDragImageEvent read FDefaultImageEvent write FDefaultImageEvent; property DragImageHeight: Integer read FDragImageHeight write FDragImageHeight default 300; property DragImageWidth: Integer read FDragImageWidth write FDragImageWidth default 200; property DragMode: TDragMode read GetDragMode write SetDragMode default dmManual; property DragType: TEasyDragType read FDragType write SetDragType default edtOLE; property Header: TEasyHeader read FHeader write FHeader; property TargetColumn: TEasyColumn read FTargetColumn write FTargetColumn; public constructor Create(AnOwner: TCustomEasyListview); override; published property AutoScroll; property AutoScrollAccelerator; property AutoScrollDelay; property AutoScrollMargin; property AutoScrollTime; property DragCursor: TCursor read GetDragCursor write SetDragCursor default crDrag; property EnableDragImage: Boolean read FEnableDragImage write FEnableDragImage default True; property MouseButton; end; // ************************************************************************** // TEasyDragManager // Easy Drag Manager is associated with a TWinContol to track the // dragging of the cells in a Easy Control // ************************************************************************** TEasyOLEDragManager = class(TEasyHeaderDragManager) private FDragAnchorPt: TPoint; FDragItem: TEasyItem; FDragTarget: Boolean; FDropTarget: TEasyItem; FHilightDropTarget: Boolean; protected procedure ClearDragItem; procedure ClearDropTarget; procedure DefaultImage(Sender: TCustomEasyListview; Image: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); override; procedure DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); override; procedure DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); override; procedure DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); override; procedure DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); override; function DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; override; procedure ImageSize(var Width: Integer; var Height: Integer); override; procedure SetEnabled(const Value: Boolean); override; procedure VCLDragStart; override; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure FinalizeDrag(KeyState: TCommonKeyStates); function InitializeDrag(HitItem: TEasyItem; WindowPoint: TPoint; KeyState: TCommonKeyStates): Boolean; property DragAnchorPt: TPoint read FDragAnchorPt write FDragAnchorPt; property DragItem: TEasyItem read FDragItem; property DragTarget: Boolean read FDragTarget; property DropTarget: TEasyItem read FDropTarget; published property AutoScroll; property AutoScrollAccelerator; property AutoScrollDelay; property AutoScrollMargin; property AutoScrollTime; property DragImageHeight; property DragImageWidth; property DragMode; property DragType; property Enabled default False; property HilightDropTarget: Boolean read FHilightDropTarget write FHilightDropTarget default True; property MouseButton; end; // ************************************************************************** // TEasySelectionManager // Easy Select Manager is associated with a TWinContol to track the // selection and focus of the cells in a Easy Control. // ************************************************************************** TEasySelectionManager = class(TEasyOwnedPersistent) private FAlphaBlend: Boolean; FAlphaBlendSelRect: Boolean; FBlendAlphaImage: Byte; FBlendAlphaSelRect: Byte; FBlendAlphaTextRect: Byte; FBlendColorIcon: TColor; FBlendColorSelRect: TColor; FBlendIcon: Boolean; FBlurAlphaBkGnd: Boolean; FBorderColor: TColor; FBorderColorSelRect: TColor; FColor: TColor; FCount: Integer; FFocusedColumn: TEasyColumn; FFocusedItem: TEasyItem; FAnchorItem: TEasyItem; FFocusedGroup: TEasyGroup; FEnabled: Boolean; FForceDefaultBlend: Boolean; FFullCellPaint: Boolean; FFullItemPaint: Boolean; FFullRowSelect: Boolean; FGradient: Boolean; FGradientColorBottom: TColor; FGradientColorTop: TColor; FGroupSelections: Boolean; FGroupSelectUpdateCount: Integer; FInactiveBorderColor: TColor; FInactiveColor: TColor; FInactiveTextColor: TColor; FItemsToggled: Integer; FMouseButton: TCommonMouseButtons; FMultiChangeCount: Integer; FMultiSelect: Boolean; FPopupMode: Boolean; FRectSelect: Boolean; // A Click-Shift Select will use the Rectangle of the click and the Anchor Item vs. Selecting all from the Anchor Item Index to the selected Item index FResizeGroupOnFocus: Boolean; // If true and a focused caption will overlap next group, the group is resized to fit focused caption FRoundRect: Boolean; FRoundRectRadius: Byte; FTextColor: TColor; FUseFocusRect: Boolean; function GetAutoScroll: Boolean; function GetAutoScrollAccelerator: Byte; function GetAutoScrollDelay: Integer; function GetAutoScrollMargin: Integer; function GetAutoScrollTime: Integer; function GetEnableDragSelect: Boolean; function GeTCommonMouseButton: TCommonMouseButtons; function GetFocusedColumn: TEasyColumn; function GetMouseButtonSelRect: TCommonMouseButtons; function GetSelecting: Boolean; procedure SetAutoScroll(Value: Boolean); procedure SetAutoScrollAccelerator(Value: Byte); procedure SetAutoScrollDelay(Value: Integer); procedure SetAutoScrollMargin(Value: Integer); procedure SetAutoScrollTime(Value: Integer); procedure SetBlendIcon(Value: Boolean); procedure SetBlurAlphaBkGnd(const Value: Boolean); procedure SetEnableDragSelect(Value: Boolean); procedure SetFocusedColumn(Value: TEasyColumn); procedure SetFocusedItem(Value: TEasyItem); procedure SetFocusedGroup(const Value: TEasyGroup); procedure SetEnabled(const Value: Boolean); procedure SeTCommonMouseButton(Value: TCommonMouseButtons); procedure SetFullCellPaint(Value: Boolean); procedure SetFullItemPaint(Value: Boolean); procedure SetGradient(const Value: Boolean); procedure SetGradientColorBottom(const Value: TColor); procedure SetGradientColorTop(const Value: TColor); procedure SetGroupSelections(Value: Boolean); procedure SetMouseButtonSelRect(Value: TCommonMouseButtons); procedure SetMultiSelect(const Value: Boolean); procedure SetAnchorItem(Value: TEasyItem); protected procedure ActOnAll(SelectType: TEasySelectionType; ExceptItem: TEasyItem); procedure BuildSelectionGroupings(Force: Boolean); virtual; procedure DragSelect(KeyStates: TCommonKeyStates); procedure GainingSelection(Item: TEasyItem); procedure LosingSelection(Item: TEasyItem); procedure NotifyOwnerListview; property ItemsToggled: Integer read FItemsToggled write FItemsToggled; property MultiChangeCount: Integer read FMultiChangeCount write FMultiChangeCount; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; function SelectedToArray: TEasyItemArray; procedure ClearAll; procedure ClearAllExcept(Item: TEasyItem); function First: TEasyItem; function FirstInGroup(Group: TEasyGroup): TEasyItem; procedure FocusFirst; procedure DecMultiChangeCount; procedure DeleteSelected(SelectPrevItem: Boolean = False); procedure GroupSelectBeginUpdate; procedure GroupSelectEndUpdate; procedure IncMultiChangeCount; procedure InvalidateVisibleSelected(ValidateWindow: Boolean); procedure Invert; function Next(Item: TEasyItem): TEasyItem; function NextInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; procedure SelectAll; procedure SelectFirst; procedure SelectGroupItems(Group: TEasyGroup; ClearOtherItems: Boolean); procedure SelectRange(FromItem, ToItem: TEasyItem; RectSelect: Boolean; ClearFirst: Boolean); procedure SelectRect(ViewportSelRect: TRect; ClearFirst: Boolean); property AnchorItem: TEasyItem read FAnchorItem write SetAnchorItem; property Count: Integer read FCount; property FocusedColumn: TEasyColumn read GetFocusedColumn write SetFocusedColumn; property FocusedItem: TEasyItem read FFocusedItem write SetFocusedItem; property FocusedGroup: TEasyGroup read FFocusedGroup write SetFocusedGroup; property Selecting: Boolean read GetSelecting; published property AlphaBlend: Boolean read FAlphaBlend write FAlphaBlend default False; property AlphaBlendSelRect: Boolean read FAlphaBlendSelRect write FAlphaBlendSelRect default False; property AutoScroll: Boolean read GetAutoScroll write SetAutoScroll default True; property AutoScrollAccelerator: Byte read GetAutoScrollAccelerator write SetAutoScrollAccelerator default 2; property AutoScrollDelay: Integer read GetAutoScrollDelay write SetAutoScrollDelay default _AUTOSCROLLDELAY; property AutoScrollMargin: Integer read GetAutoScrollMargin write SetAutoScrollMargin default 15; property AutoScrollTime: Integer read GetAutoScrollTime write SetAutoScrollTime default _AUTOSCROLLTIME; property BlendAlphaImage: Byte read FBlendAlphaImage write FBlendAlphaImage default 128; property BlendAlphaSelRect: Byte read FBlendAlphaSelRect write FBlendAlphaSelRect default 70; property BlendAlphaTextRect: Byte read FBlendAlphaTextRect write FBlendAlphaTextRect default 128; property BlendColorSelRect: TColor read FBlendColorSelRect write FBlendColorSelRect default clHighlight; property BlendIcon: Boolean read FBlendIcon write SetBlendIcon default True; property BlurAlphaBkGnd: Boolean read FBlurAlphaBkGnd write SetBlurAlphaBkGnd default False; property BorderColor: TColor read FBorderColor write FBorderColor default clHighlight; property BorderColorSelRect: TColor read FBorderColorSelRect write FBorderColorSelRect default clHighlight; property Color: TColor read FColor write FColor default clHighlight; property Enabled: Boolean read FEnabled write SetEnabled default True; property EnableDragSelect: Boolean read GetEnableDragSelect write SetEnableDragSelect default False; property ForceDefaultBlend: Boolean read FForceDefaultBlend write FForceDefaultBlend default False; property FullCellPaint: Boolean read FFullCellPaint write SetFullCellPaint default False; property FullItemPaint: Boolean read FFullItemPaint write SetFullItemPaint default False; property FullRowSelect: Boolean read FFullRowSelect write FFullRowSelect default False; property Gradient: Boolean read FGradient write SetGradient default False; property GradientColorBottom: TColor read FGradientColorBottom write SetGradientColorBottom default $FCEFD5; property GradientColorTop: TColor read FGradientColorTop write SetGradientColorTop default $FDF8F1; property GroupSelections: Boolean read FGroupSelections write SetGroupSelections default False; property InactiveBorderColor: TColor read FInactiveBorderColor write FInactiveBorderColor default clInactiveBorder; property InactiveColor: TColor read FInactiveColor write FInactiveColor default clInactiveBorder; property InactiveTextColor: TColor read FInactiveTextColor write FInactiveTextColor default clBlack; property MouseButton: TCommonMouseButtons read GeTCommonMouseButton write SeTCommonMouseButton default [cmbLeft]; property MouseButtonSelRect: TCommonMouseButtons read GetMouseButtonSelRect write SetMouseButtonSelRect default [cmbLeft, cmbRight]; property MultiSelect: Boolean read FMultiSelect write SetMultiSelect default False; property PopupMode: Boolean read FPopupMode write FPopupMode default False; property RectSelect: Boolean read FRectSelect write FRectSelect default False; property ResizeGroupOnFocus: Boolean read FResizeGroupOnFocus write FResizeGroupOnFocus default False; property RoundRect: Boolean read FRoundRect write FRoundRect default False; property RoundRectRadius: Byte read FRoundRectRadius write FRoundRectRadius default 4; property TextColor: TColor read FTextColor write FTextColor default clHighlightText; property UseFocusRect: Boolean read FUseFocusRect write FUseFocusRect default True; end; // ************************************************************************** // TEasyCheckManager // Manages the check state of the items. The item carries the check state // of itself but this manager allows manipulation of multiple items // ************************************************************************** TEasyCheckManager = class(TEasyOwnedPersistent) private FCount: Integer; // Number of items with checks set FPendingObject: TEasyCollectionItem; // When the mouse button is pressed over an item PendingCheckItem is set to that item procedure SetPendingObject(Value: TEasyCollectionItem); protected property PendingObject: TEasyCollectionItem read FPendingObject write SetPendingObject; public function CheckedToArray: TEasyItemArray; procedure CheckAll; procedure CheckAllInGroup(Group: TEasyGroup); function First: TEasyItem; function FirstInGroup(Group: TEasyGroup): TEasyCollectionItem; function Next(Item: TEasyItem): TEasyItem; function NextInGroup(Item: TEasyItem): TEasyItem; procedure DeleteChecked; procedure UnCheckAll; procedure UnCheckAllInGroup(Group: TEasyGroup); property Count: Integer read FCount; end; TEasyHotTrackManager = class(TEasyOwnedPersistent) private FColor: TColor; FColumnTrack: TEasyHotTrackRectColumns; FEnabled: Boolean; FCursor: TCursor; FGroupTrack: TEasyHotTrackRectGroups; FItemTrack: TEasyHotTrackRectItems; FOnlyFocused: Boolean; FPendingObject: TEasyCollectionItem; FPendingObjectCheck: TEasyCollectionItem; FUnderline: Boolean; function GetPendingObject(MousePos: TPoint): TEasyCollectionItem; procedure SetPendingObject(MousePos: TPoint; Value: TEasyCollectionItem); procedure SetPendingObjectCheck(const Value: TEasyCollectionItem); protected property PendingObject[MousePos: TPoint]: TEasyCollectionItem read GetPendingObject write SetPendingObject; property PendingObjectCheck: TEasyCollectionItem read FPendingObjectCheck write SetPendingObjectCheck; public constructor Create(AnOwner: TCustomEasyListview); override; published property Color: TColor read FColor write FColor default clHighlight; // property ColumnTrack: TEasyHotTrackRectColumns read FColumnTrack write FColumnTrack default [htcImage, htcText]; property Enabled: Boolean read FEnabled write FEnabled default False; property Cursor: TCursor read FCursor write FCursor default crHandPoint; property GroupTrack: TEasyHotTrackRectGroups read FGroupTrack write FGroupTrack default [htgIcon, htgText]; property ItemTrack: TEasyHotTrackRectItems read FItemTrack write FItemTrack default [htiIcon, htiText]; property OnlyFocused: Boolean read FOnlyFocused write FOnlyFocused default False; property Underline: Boolean read FUnderline write FUnderline default True; end; // ************************************************************************** // TEasyScrollbarManager // ScrollManager is associated with a TWinContol to handle the // controls scrollbars // ************************************************************************** TEasyScrollbarManager = class(TEasyOwnedPersistent) private FHorzEnabled: Boolean; FOffsetX: Integer; FOffsetY: Integer; FRebuilding: Boolean; FSnapHorzView: Boolean; // Causes scroll to snap to column width FVertEnabled: Boolean; FViewRect: TRect; function GetHorzBarVisible: Boolean; function GetLine: Integer; function GetMaxOffsetX: Integer; function GetMaxOffsetY: Integer; function GetVertBarVisible: Boolean; function GetViewHeight: Integer; function GetViewWidth: Integer; procedure SetHorzEnabled(const Value: Boolean); procedure SetOffsetX(const Value: Integer); procedure SetOffsetY(const Value: Integer); procedure SetVertEnabled(const Value: Boolean); protected public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; function MapWindowToView(WindowPoint: TPoint; AccountForHeader: Boolean = True): TPoint; overload; function MapWindowToView(WindowPoint: TSmallPoint; AccountForHeader: Boolean = True): TPoint; overload; function MapWindowRectToViewRect(WindowRect: TRect; AccountForHeader: Boolean = True): TRect; function MapViewToWindow(ViewportPoint: TPoint; AccountForHeader: Boolean = True): TPoint; overload; function MapViewToWindow(ViewportPoint: TSmallPoint; AccountForHeader: Boolean = True): TPoint; overload; function MapViewRectToWindowRect(ViewPortRect: TRect; AccountForHeader: Boolean = True): TRect; procedure ReCalculateScrollbars(Redraw: Boolean; Force: Boolean); procedure Scroll(DeltaX, DeltaY: Integer); procedure SetViewRect(AViewRect: TRect; InvalidateWindow: Boolean); procedure ValidateOffsets(var AnOffsetX, AnOffsetY: Integer); function ViewableViewportRect: TRect; procedure WMHScroll(var Msg: TWMVScroll); procedure WMKeyDown(var Msg: TWMKeyDown); procedure WMVScroll(var Msg: TWMVScroll); property HorzBarVisible: Boolean read GetHorzBarVisible; property Line: Integer read GetLine; property MaxOffsetX: Integer read GetMaxOffsetX; property MaxOffsetY: Integer read GetMaxOffsetY; property OffsetX: Integer read FOffsetX write SetOffsetX; property OffsetY: Integer read FOffsetY write SetOffsetY; property Rebuilding: Boolean read FRebuilding; property VertBarVisible: Boolean read GetVertBarVisible; property ViewHeight: Integer read GetViewHeight; property ViewRect: TRect read FViewRect; property ViewWidth: Integer read GetViewWidth; published property HorzEnabled: Boolean read FHorzEnabled write SetHorzEnabled default True; property SnapHorzView: Boolean read FSnapHorzView write FSnapHorzView default True; property VertEnabled: Boolean read FVertEnabled write SetVertEnabled default True; end; // ************************************************************************** // TEasyBackgroundManager // Easy Background handles the drawing of a background in Easy // controls. It is a stand alone component that can be shared // ************************************************************************** TEasyBackgroundManager = class(TEasyOwnedPersistent) private FAlphaBlend: Boolean; FAlphaBlender: TEasyAlphaBlender; FBlendAlpha: Integer; FBlendMode: TCommonBlendMode; FCaption: WideString; FCaptionAlignment: TAlignment; FCaptionShow: Boolean; FCaptionShowOnlyWhenEmpty: Boolean; FCaptionSingleLine: Boolean; FCaptionVAlignment: TCommonVAlignment; FEnabled: Boolean; FImage: TBitmap; FOffsetTrack: Boolean; FOffsetX: Integer; FOffsetY: Integer; FTile: Boolean; FTransparent: Boolean; FAlphaImage: TBitmap; procedure SetAlphaBlend(const Value: Boolean); procedure SetAlphaImage(const Value: TBitmap); procedure SetBlendAlpha(const Value: Integer); procedure SetCaption(const Value: WideString); procedure SetCaptionAlignment(const Value: TAlignment); procedure SetCaptionShow(const Value: Boolean); procedure SetCaptionShowOnlyWhenEmpty(const Value: Boolean); procedure SetCaptionSingleLine(const Value: Boolean); procedure SetCaptionVAlignment(const Value: TCommonVAlignment); procedure SetCommonBlendMode(const Value: TCommonBlendMode); procedure SetEnabled(const Value: Boolean); procedure SetImage(const Value: TBitmap); procedure SetOffsetX(const Value: Integer); procedure SetOffsetY(const Value: Integer); procedure SetTile(const Value: Boolean); procedure SetTransparent(const Value: Boolean); protected procedure ChangeBitmapBits(Sender: TObject); property AlphaBlender: TEasyAlphaBlender read FAlphaBlender write FAlphaBlender; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure AssignTo(Target: TPersistent); override; procedure PaintTo(ACanvas: TCanvas; ARect: TRect; PaintDefault: Boolean); virtual; procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging); virtual; published property AlphaBlend: Boolean read FAlphaBlend write SetAlphaBlend default False; property AlphaImage: TBitmap read FAlphaImage write SetAlphaImage; property BlendAlpha: Integer read FBlendAlpha write SetBlendAlpha default 128; property BlendMode: TCommonBlendMode read FBlendMode write SetCommonBlendMode default cbmConstantAlphaAndColor; property Caption: WideString read FCaption write SetCaption; property CaptionAlignment: TAlignment read FCaptionAlignment write SetCaptionAlignment default taCenter; property CaptionShow: Boolean read FCaptionShow write SetCaptionShow default False; property CaptionShowOnlyWhenEmpty: Boolean read FCaptionShowOnlyWhenEmpty write SetCaptionShowOnlyWhenEmpty default True; property CaptionSingleLine: Boolean read FCaptionSingleLine write SetCaptionSingleLine default True; property CaptionVAlignment: TCommonVAlignment read FCaptionVAlignment write SetCaptionVAlignment default cvaCenter; property Enabled: Boolean read FEnabled write SetEnabled default False; property Image: TBitmap read FImage write SetImage; property OffsetTrack: Boolean read FOffsetTrack write FOffsetTrack default False; property OffsetX: Integer read FOffsetX write SetOffsetX default 0; property OffsetY: Integer read FOffsetY write SetOffsetY default 0; property Tile: Boolean read FTile write SetTile default True; property Transparent: Boolean read FTransparent write SetTransparent default False; end; // ************************************************************************** // TEasyTaskBandBackgroundManager // Easy Background handles the drawing of a background in Easy // controls. It is a stand alone component that can be shared // ************************************************************************** TEasyTaskBandBackgroundManager = class(TEasyBackgroundManager) public procedure PaintTo(ACanvas: TCanvas; ARect: TRect; PaintDefault: Boolean); override; end; // ************************************************************************** // TEasyDropTargetManager // Implements the IDropTarget inteface to allow for the control to become // a drag/drop target and accept drops. // ************************************************************************** TEasyDropTargetManager = class(TEasyOwnedInterfacedPersistent, IDropTarget) private FDragManager: TCustomEasyDragManagerBase; FDropTargetHelper: IDropTargetHelper; // Win2k and up drag image support built in to Windows function GetDropTargetHelper: IDropTargetHelper; protected function DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragLeave: HResult; stdcall; function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; property DragManager: TCustomEasyDragManagerBase read FDragManager write FDragManager; property DropTargetHelper: IDropTargetHelper read GetDropTargetHelper; public end; // ************************************************************************** // TEasyDropSourceManager // Implements the IDropSource inteface to allow for the control to become // a drag/drop source. // ************************************************************************** TEasyDropSourceManager = class(TEasyOwnedInterfacedPersistent, IDropSource) protected function QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Longint): HResult; stdcall; function GiveFeedback(dwEffect: Longint): HResult; stdcall; end; // ************************************************************************** // Drag TEasyDragRectManager Manager // Easy DragRect Manager is associated with a TWinContol to handle the // controls drag selection rectangle // ************************************************************************** TEasyDragRectManager = class(TCustomEasyDragManagerBase) private FAnchorPoint: TPoint; // Anchor point in Viewport coordinates FDragPoint: TPoint; // Dragging point in Viewport coordinates FOldOffsets: TPoint; FPrevRect: TRect; function GetSelectionRect: TRect; procedure PaintRect(Canvas: TCanvas); procedure SetAnchorPoint(ViewportAnchor: TPoint); procedure SetDragPoint(const Value: TPoint); protected procedure DoAfterAutoScroll; override; procedure DoAutoScroll(DeltaX, DeltaY: Integer); override; procedure DoBeforeAutoScroll; override; procedure DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; procedure DoDragBegin(WindowPoint: TPoint; KeyState: TCommonKeyStates); override; procedure DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); override; procedure DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); override; function DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; override; function DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; override; procedure UpdateAfterAutoScroll; override; property OldOffsets: TPoint read FOldOffsets write FOldOffsets; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure FinalizeDrag(KeyState: TCommonKeyStates); function InitializeDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates): Boolean; procedure PaintSelectionRect(Canvas: TCanvas); function SelRectInWindowCoords: TRect; procedure WMKeyDown(var Msg: TWMKeyDown); override; property AnchorPoint: TPoint read FAnchorPoint write SetAnchorPoint; property DragPoint: TPoint read FDragPoint write SetDragPoint; property PrevRect: TRect read FPrevRect; property SelectionRect: TRect read GetSelectionRect; end; // > 0 (positive) Item1 is less than Item2 // 0 Item1 is equal to Item2 // < 0 (negative) Item1 is greater than Item2 TEasySortProc = function(Column: TEasyColumn; Item1, Item2: TEasyCollectionItem): Integer; TEasySorter = class private FOwner: TEasySortManager; public constructor Create(AnOwner: TEasySortManager); virtual; procedure Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); virtual; abstract; property Owner: TEasySortManager read FOwner write FOwner; end; TEasyQuickSort = class(TEasySorter) public procedure Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); override; end; TEasyBubbleSort = class(TEasySorter) public procedure Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); override; end; TEasyMergeSort = class(TEasySorter) private FColumn: TEasyColumn; FGroupCompareFunc: TEasyDoGroupCompare; FItemCompareFunc: TEasyDoItemCompare; FOwnerGroup: TEasyGroup; protected function CompareInterfaces(i1, i2: TEasyCollectionItem): Boolean; function CompareGroup(i1, i2: TEasyCollectionItem): Boolean; function CompareItem(i1, i2: TEasyCollectionItem): Boolean; function CompareDefault(i1, i2: TEasyCollectionItem): Boolean; property Column: TEasyColumn read FColumn write FColumn; property GroupCompareFunc: TEasyDoGroupCompare read FGroupCompareFunc write FGroupCompareFunc; property ItemCompareFunc: TEasyDoItemCompare read FItemCompareFunc write FItemCompareFunc; property OwnerGroup: TEasyGroup read FOwnerGroup write FOwnerGroup; public procedure Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); override; end; TGroupSortInfoRec = record Item: TEasyItem; Key: LongWord; end; TGroupSortInfoArray = array of TGroupSortInfoRec; // ************************************************************************** // TEasySortManager // Manages the sorting of the Listview. Because of the way EasyListview // works it is not feasable to try to add an AutoSort property. EasyListview // can access a caption by a callback, storing it in the control, or through // an interface. Due to the wildly varying ways of storing the caption it was // decided to not try to find all the possible places it would be necessary to // AutoSort. There are some scenarios, such as the interface access, where it // is not possible to detect when an autosort should be carried out. // ************************************************************************** TEasySortManager = class(TEasyOwnedPersistent) private FAlgorithm: TEasySortAlgorithm; // The algorithm used when sorting FAutoRegroup: Boolean; FAutoSort: Boolean; // Items and groups are resorted when any object is added/inserted FLockoutSort: Boolean; FSortList: TGroupSortInfoArray; FSorter: TEasySorter; // The algorithm engine for the sort FUpdateCount: Integer; procedure SetAlgorithm(Value: TEasySortAlgorithm); procedure SetAutoRegroup(Value: Boolean); procedure SetAutoSort(Value: Boolean); protected function CollectionSupportsInterfaceSorting(Collection: TEasyCollection): Boolean; procedure GroupItem(Item: TEasyItem; ColumnIndex: Integer; Key: LongWord); property Sorter: TEasySorter read FSorter write FSorter; property SortList: TGroupSortInfoArray read FSortList write FSortList; property UpdateCount: Integer read FUpdateCount write FUpdateCount; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure BeginUpdate; procedure EndUpdate; procedure ReGroup(Column: TEasyColumn); virtual; procedure SortAll(Force: Boolean = False); property LockoutSort: Boolean read FLockoutSort write FLockoutSort; published property Algorithm: TEasySortAlgorithm read FAlgorithm write SetAlgorithm default esaMergeSort; property AutoRegroup: Boolean read FAutoRegroup write SetAutoRegroup default False; property AutoSort: Boolean read FAutoSort write SetAutoSort default False; end; // ************************************************************************** // TEasyHintInfo // Custom hint information for the Unicode Hint Window // ************************************************************************** TEasyHintInfo = class(TEasyOwnedPersistent) private FBounds: TRect; FCanvas: TCanvas; FColor: TColor; FCursorPos: TPoint; FHideTimeout: Integer; FHintType: TEasyHintType; FMaxWidth: Integer; FReshowTimeout: Integer; FText: WideString; FWindowPos: TPoint; public property Canvas: TCanvas read FCanvas write FCanvas; property Color: TColor read FColor write FColor; property CursorPos: TPoint read FCursorPos write FCursorPos; property Bounds: TRect read FBounds write FBounds; property HideTimeout: Integer read FHideTimeout write FHideTimeout; property HintType: TEasyHintType read FHintType write FHintType; property MaxWidth: Integer read FMaxWidth write FMaxWidth; property ReshowTimeout: Integer read FReshowTimeout write FReshowTimeout; property Text: WideString read FText write FText; property WindowPos: TPoint read FWindowPos write FWindowPos; end; // ************************************************************************** // TEasyHintWindow // Custom hint window that supports Unicode and Custom Draw // ************************************************************************** TEasyHintWindow = class(THintWindow) protected FEasyHintInfo: TEasyHintInfo; FHintInfo: PEasyHintInfoRec; procedure Paint; override; property EasyHintInfo: TEasyHintInfo read FEasyHintInfo write FEasyHintInfo; property HintInfo: PEasyHintInfoRec read FHintInfo write FHintInfo; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ActivateHint(ARect: TRect; const AHint: string); override; procedure ActivateHintData(ARect: TRect; const AHint: string; AData: Pointer); override; function CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; override; function IsHintMsg(var Msg: TMsg): Boolean; override; end; TEasyHintWindowClass = class of TEasyHintWindow; // ************************************************************************** // TEasyIncrementalSearchManager // Implements the incremental search of the listview // ************************************************************************** TEasyIncrementalSearchManager = class(TEasyOwnedPersistent) private FDirection: TEasyIncrementalSearchDir; FEnabled: Boolean; FhTimer: THandle; FItemType: TEasyIncrementalSearchItemType; FNextSearchItem: TEasyItem; FResetTime: Integer; FSearchBuffer: WideString; FSearchItem: TEasyItem; FStart: TCoolIncrementalSearchStart; FState: TEasyIncrementalSearchStates; FTimerStub: Pointer; procedure SetSearchItem(Value: TEasyItem); protected procedure EndTimer; function IsSearching: Boolean; procedure HandleWMChar(var Msg: TWMChar); virtual; procedure HandleWMKeyDown(var Msg: TWMKeyDown); virtual; procedure LoadFutureItem; procedure ResetTimer; procedure SearchPreloadItem(Next, Prev: TItemNextEnum; First, Last: TItemEnumFirstLast; var SearchItem: TEasyItem); procedure StartSearch; procedure StartTimer; procedure TimerProc(Window: HWnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall; property hTimer: THandle read FhTimer write FhTimer; property NextSearchItem: TEasyItem read FNextSearchItem write FNextSearchItem; property SearchBuffer: WideString read FSearchBuffer write FSearchBuffer; property SearchItem: TEasyItem read FSearchItem write SetSearchItem; property TimerStub: Pointer read FTimerStub write FTimerStub; public constructor Create(AnOwner: TCustomEasyListview); override; destructor Destroy; override; procedure ClearSearch; virtual; procedure ResetSearch; property State: TEasyIncrementalSearchStates read FState write FState; published property Direction: TEasyIncrementalSearchDir read FDirection write FDirection default eisdForward; property Enabled: Boolean read FEnabled write FEnabled default False; property ResetTime: Integer read FResetTime write FResetTime default 2000; property StartType: TCoolIncrementalSearchStart read FStart write FStart default eissStartOver; property ItemType: TEasyIncrementalSearchItemType read FItemType write FItemType default eisiVisible; end; // ************************************************************************** // TEasyGestureManager // Implements the Gesture feature of the listview // ************************************************************************** TEasyGestureManager = class(TEasyOwnedPersistent) private FButton: TCommonMouseButtons; FEnabled: Boolean; FPath: WideString; FTolerance: Integer; protected property Path: WideString read FPath write FPath; public constructor Create(AnOwner: TCustomEasyListview); override; published property Button: TCommonMouseButtons read FButton write FButton default [cmbRight]; property Enabled: Boolean read FEnabled write FEnabled default False; property Tolerance: Integer read FTolerance write FTolerance default 3; end; // Down here due to a bug in C++ BDS2006 hpp generated files TEasyHintInfoRec = record HintControl: TControl; HintWindowClass: THintWindowClass; HintPos: TPoint; HintMaxWidth: Integer; HintColor: TColor; HintType: TEasyHintType; CursorRect: TRect; CursorPos: TPoint; ReshowTimeout: Integer; HideTimeout: Integer; HintStr: WideString; HintData: Pointer; Listview: TCustomEasyListview; TargetObj: TEasyCollectionItem; // What the hint is being popped up over (EasyItem, EasyGroup, EasyColumn etc.) ToolTipRect: TRect; // The size of the rect needed for a tool tip hint end; // ************************************************************************** // TCustomEasyListview // ************************************************************************** TCustomEasyListview = class(TCommonCanvasControl) private FAllowInvisibleCheckedItems: Boolean; FBackBits: TBitmap; FBackGround: TEasyBackgroundManager; FCacheDoubleBufferBits: Boolean; FCellSizes: TEasyCellSizes; FCheckManager: TEasyCheckManager; FDisabledBlendAlpha: Byte; FDisabledBlendColor: TColor; FDragManager: TEasyOLEDragManager; FDragRect: TEasyDragRectManager; FDropTarget: IDropTarget; FEditManager: TEasyEditManager; FForcePaint: Boolean; FGesture: TEasyGestureManager; FGlobalImages: TEasyGlobalImageManager; FGroupCollapseButton: TBitmap; FGroupExpandButton: TBitmap; FGroupFont: TFont; FGroupImageGetSize: TGroupImageGetSizeEvent; FGroups: TEasyGroups; FHeader: TEasyHeader; FHintAlignment: TAlignment; FHintData: TEasyHintInfoRec; FHintInfo: TEasyHintInfo; FHotTrack: TEasyHotTrackManager; FImagesExLarge: TCustomImageList; FImagesGroup: TCustomImageList; FImagesLarge: TCustomImageList; FImagesSmall: TCustomImageList; FImagesState: TCustomImageList; FIncrementalSearch: TEasyIncrementalSearchManager; FItems: TEasyGlobalItems; FLastMousePos: TSmallPoint; FNCCanvas: TCanvas; FOnAfterPaint: TAfterPaintEvent; FOnAutoGroupGetKey: TAutoGroupGetKeyEvent; FOnAutoSortGroupCreate: TAutoSortGroupCreateEvent; FOnClipboardCopy: TEasyClipboardEvent; FOnClipboardCut: TEasyClipboardCutEvent; FOnClipboardPaste: TEasyClipboardEvent; FOnColumnCheckChange: TColumnCheckChangeEvent; FOnColumnCheckChanging: TColumnCheckChangingEvent; FOnColumnClick: TColumnClickEvent; FOnColumnContextMenu: TColumnContextMenuEvent; FOnColumnDblClick: TColumnDblClickEvent; FOnColumnDropDownButtonClick: TColumnDropDownButtonClickEvent; FOnColumnImageDrawIsCustom: TColumnImageDrawIsCustomEvent; FOnColumnEnableChange: TColumnEnableChangeEvent; FOnColumnEnableChanging: TColumnEnableChangingEvent; FOnColumnFocusChanged: TColumnFocusChangeEvent; FOnColumnFocusChanging: TColumnFocusChangingEvent; FOnColumnFreeing: TColumnFreeingEvent; FOnColumnGetCaption: TColumnGetCaptionEvent; FOnColumnGetDetail: TColumnGetDetailEvent; FOnColumnGetDetailCount: TColumnGetDetailCountEvent; FOnColumnGetImageIndex: TColumnGetImageIndexEvent; FOnColumnGetImageList: TColumnGetImageListEvent; FOnColumnImageDraw: TColumnImageDrawEvent; FOnColumnImageGetSize: TColumnImageGetSizeEvent; FOnColumnInitialize: TColumnInitializeEvent; FOnColumnLoadFromStream: TEasyColumnLoadFromStreamEvent; FOnColumnPaintText: TColumnPaintTextEvent; FOnColumnSaveToStream: TEasyColumnSaveToStreamEvent; FOnColumnSelectionChanged: TColumnSelectionChangeEvent; FOnColumnSelectionChanging: TColumnSelectionChangingEvent; FOnColumnSetCaption: TColumnSetCaptionEvent; FOnColumnSetDetail: TColumnSetDetailEvent; FOnColumnSetImageIndex: TColumnSetImageIndexEvent; FOnColumnSizeChanged: TColumnSizeChangedEvent; FOnColumnSizeChanging: TColumnSizeChangingEvent; FOnColumnStructureChange: TNotifyEvent; FOnColumnThumbnailDraw: TColumnThumbnailDrawEvent; FOnColumnVisibilityChanged: TColumnVisibilityChangeEvent; FOnColumnVisibilityChanging: TColumnVisibilityChangingEvent; FOnContextMenu: TContextMenuEvent; FOnColumnCustomView: TColumnCustomViewEvent; FOnCustomGrid: TCustomGridEvent; FOnDblClick: TDblClickEvent; FOnMouseGesture: TEasyGestureEvent; FOnGetDragImage: TGetDragImageEvent; FOnGroupClick: TGroupClickEvent; FOnGroupCollapse: TGroupCollapseEvent; FOnGroupCollapsing: TGroupCollapsingEvent; FOnGroupCompare: TGroupCompareEvent; FOnGroupContextMenu: TGroupContextMenuEvent; FOnGroupCustomView: TGroupCustomViewEvent; FOnGroupDblClick: TGroupDblClickEvent; FOnGroupImageDrawIsCustom: TGroupImageDrawIsCustomEvent; FOnGroupExpand: TGroupExpandEvent; FOnGroupExpanding: TGroupExpandingEvent; FOnGroupFocusChanged: TGroupFocusChangeEvent; FOnGroupFocusChanging: TGroupFocusChangingEvent; FOnGroupFreeing: TGroupFreeingEvent; FOnGroupGetCaption: TGroupGetCaptionEvent; FOnGroupGetDetailCount: TGroupGetDetailCountEvent; FOnGroupGetDetailIndex: TGroupGetDetailEvent; FOnGroupGetImageIndex: TGroupGetImageIndexEvent; FOnGroupGetImageList: TGroupGetImageListEvent; FOnGroupImageDrawEvent: TGroupImageDrawEvent; FOnGroupInitialize: TGroupInitializeEvent; FOnGroupHotTrack: TGroupHotTrackEvent; FOnGroupLoadFromStream: TGroupLoadFromStreamEvent; FOnGroupPaintText: TGroupPaintTextEvent; FOnGroupSaveToStream: TGroupSaveToStreamEvent; FOnGroupSelectionChanged: TGroupSelectionChangeEvent; FOnGroupSelectionChanging: TGroupSelectionChangingEvent; FOnGroupSetCaption: TGroupSetCaptionEvent; FOnGroupSetImageIndex: TGroupSetImageIndexEvent; FOnGroupSetDetail: TGroupSetDetailEvent; FOnGroupStructureChange: TNotifyEvent; FOnGroupThumbnailDraw: TGroupThumbnailDrawEvent; FOnGroupVisibilityChanged: TGroupVisibilityChangeEvent; FOnGroupVisibilityChanging: TGroupVisibilityChangingEvent; FOnHeaderDblClick: THeaderDblClickEvent; FOnHeaderMouseDown: THeaderMouseEvent; FOnHeaderMouseMove: TMouseMoveEvent; FOnHeaderMouseUp: THeaderMouseEvent; FOnHintCustomDraw: THintCustomDrawEvent; FOnHintCustomInfo: THintCustomizeInfoEvent; FOnHintPauseTime: THintPauseTimeEvent; FOnHintPopup: THintPopupEvent; FOnIncrementalSearch: TIncrementalSearchEvent; FOnItemCheckChange: TItemCheckChangeEvent; FOnItemCheckChanging: TItemCheckChangingEvent; FOnItemClick: TItemClickEvent; FOnItemCompare: TItemCompareEvent; FOnItemContextMenu: TItemContextMenuEvent; FOnItemCreateEditor: TItemCreateEditorEvent; FOnItemCustomView: TItemCustomViewEvent; FOnItemDblClick: TItemDblClickEvent; FOnItemGetEditCaption: TEasyItemGetCaptionEvent; FOnItemGetEditMenu: TItemGetEditMenuEvent; FOnItemGetStateImageList: TItemGetImageListEvent; FOnItemImageDrawIsCustom: TItemImageDrawIsCustomEvent; FOnItemEditBegin: TItemEditBegin; FOnItemEdited: TItemEditedEvent; FOnItemEditEnd: TItemEditEnd; FOnItemEnableChange: TItemEnableChangeEvent; FOnItemEnableChanging: TItemEnableChangingEvent; FOnItemFocusChanged: TItemFocusChangeEvent; FOnItemFocusChanging: TItemFocusChangingEvent; FOnItemFreeing: TItemFreeingEvent; FOnItemGetCaption: TItemGetCaptionEvent; FOnItemGetGroupKey: TItemGetGroupKeyEvent; FOnItemHotTrack: TItemHotTrackEvent; FOnItemGetTileDetailIndex: TItemGetTileDetailEvent; FOnItemGetImageIndex: TItemGetImageIndexEvent; FOnItemGetImageList: TItemGetImageListEvent; FOnItemGetTileDetailCount: TItemGetTileDetailCountEvent; FOnItemImageDraw: TItemImageDrawEvent; FOnItemImageGetSize: TItemImageGetSizeEvent; FOnItemInitialize: TItemInitializeEvent; FOnItemLoadFromStream: TItemLoadFromStreamEvent; FOnItemMouseDown: TItemMouseDownEvent; FOnItemMouseUp: TItemMouseUpEvent; FOnItemPaintText: TItemPaintTextEvent; FOnItemSaveToStream: TItemSaveToStreamEvent; FOnItemSelectionChanged: TItemSelectionChangeEvent; FOnItemSelectionChanging: TItemSelectionChangingEvent; FOnItemSelectionsChanged: TEasyItemSelectionsChangedEvent; FOnItemSetCaption: TItemSetCaptionEvent; FOnItemSetGroupKey: TItemSetGroupKeyEvent; FOnItemSetImageIndex: TItemSetImageIndexEvent; FOnItemSetTileDetail: TItemSetTileDetailEvent; FOnItemStructureChange: TNotifyEvent; FOnItemThumbnailDraw: TItemThumbnailDrawEvent; FOnItemVisibilityChanged: TItemVisibilityChangeEvent; FOnItemVisibilityChanging: TItemVisibilityChangingEvent; FOnKeyAction: TEasyKeyActionEvent; FOnOLEDragDrop: TOLEDropTargetDragDropEvent; FOnOLEDragEnd: TOLEDropSourceDragEndEvent; FOnOLEDragEnter: TOLEDropTargetDragEnterEvent; FOnOLEDragLeave: TOLEDropTargetDragLeaveEvent; FOnOLEDragOver: TOLEDropTargetDragOverEvent; FOnOLEDragStart: TOLEDropSourceDragStartEvent; FOnOLEGetCustomFormats: TOLEGetCustomFormatsEvent; FOnOLEGetData: TOLEGetDataEvent; FOnOLEGetDataObject: FOLEGetDataObjectEvent; FOnOLEGiveFeedback: TOLEDropSourceGiveFeedbackEvent; FOnOLEQueryContineDrag: TOLEDropSourceQueryContineDragEvent; FOnOLEQueryData: TOLEQueryDataEvent; FOnPaintBkGnd: TPaintBkGndEvent; FOnPaintHeaderBkGnd: TPaintHeaderBkGndEvent; FOnScroll: TEasyScrollEvent; FOnViewChange: TViewChangedEvent; FPaintInfoColumn: TEasyPaintInfoBaseColumn; FPaintInfoGroup: TEasyPaintInfoBaseGroup; FPaintInfoItem: TEasyPaintInfoBaseItem; FPopupMenuHeader: TPopupMenu; FScratchCanvas: TControlCanvas; FScrollbars: TEasyScrollbarManager; FSelection: TEasySelectionManager; FShowGroupMargins: Boolean; FShowInactive: Boolean; FShowThemedBorder: Boolean; FSort: TEasySortManager; FStates: TEasyControlStates; FView: TEasyListStyle; FWheelMouseDefaultScroll: TEasyDefaultWheelScroll; FWheelMouseScrollModifierEnabled: Boolean; function GetGroupCollapseImage: TBitmap; function GetGroupExpandImage: TBitmap; function GetHintType: TEasyHintType; function GetPaintInfoColumn: TEasyPaintInfoBaseColumn; virtual; function GetPaintInfoGroup: TEasyPaintInfoBaseGroup; virtual; function GetPaintInfoItem: TEasyPaintInfoBaseItem; virtual; function GetScratchCanvas: TControlCanvas; function GetTopItem: TEasyItem; procedure SetBackGround(const Value: TEasyBackgroundManager); procedure SetCacheDoubleBufferBits(const Value: Boolean); procedure SetGroupCollapseImage(Value: TBitmap); procedure SetGroupExpandImage(Value: TBitmap); procedure SetGroupFont(Value: TFont); procedure SetHintType(Value: TEasyHintType); procedure SetImagesExLarge(Value: TCustomImageList); procedure SetImagesGroup(Value: TCustomImageList); procedure SetImagesLarge(Value: TCustomImageList); procedure SetImagesSmall(Value: TCustomImageList); procedure SetImagesState(const Value: TCustomImageList); procedure SetPaintInfoColumn(const Value: TEasyPaintInfoBaseColumn); virtual; procedure SetPaintInfoGroup(const Value: TEasyPaintInfoBaseGroup); virtual; procedure SetPaintInfoItem(const Value: TEasyPaintInfoBaseItem); virtual; procedure SetSelection(Value: TEasySelectionManager); procedure SetShowInactive(const Value: Boolean); procedure SetShowThemedBorder(Value: Boolean); procedure SetShowGroupMargins(const Value: Boolean); protected function CreateColumnPaintInfo: TEasyPaintInfoBaseColumn; virtual; function CreateGroupPaintInfo: TEasyPaintInfoBaseGroup; virtual; function CreateGroups: TEasyGroups; virtual; function CreateItemPaintInfo: TEasyPaintInfoBaseItem; virtual; function ExecuteDragDrop(AvailableEffects: TCommonDropEffects; DataObjectInf: IDataObject; DropSource: IDropSource; var dwEffect: Integer): HRESULT; virtual; function GetSortColumn: TEasyColumn; virtual; function GroupTestExpand(HitInfo: TEasyGroupHitTestInfoSet): Boolean; virtual; function ToolTipNeeded(TargetObj: TEasyCollectionItem; var TipCaption: WideString): Boolean; function UseInternalDragImage: Boolean; virtual; function ViewSupportsHeader: Boolean; procedure CancelCut; procedure CheckFocus; virtual; procedure ClearPendingDrags; procedure ClearStates; function ClickTestGroup(ViewportPoint: TPoint; KeyStates: TCommonKeyStates; var HitInfo: TEasyGroupHitTestInfoSet): TEasyGroup; function ClickTestItem(ViewportPoint: TPoint; Group: TEasyGroup; KeyStates: TCommonKeyStates; var HitInfo: TEasyItemHitTestInfoSet): TEasyItem; procedure ClipHeader(ACanvas: TCanvas; ResetClipRgn: Boolean); procedure CMDrag(var Msg: TCMDrag); message CM_DRAG; procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; procedure CMHintShowPause(var Message: TCMHintShow); message CM_HINTSHOWPAUSE; procedure CMMouseWheel(var Msg: TWMMouseWheel); message CM_MOUSEWHEEL; procedure CMParentFontChanged(var Msg: TMessage); message CM_PARENTFONTCHANGED; procedure CopyToClipboard; virtual; procedure CreateParams(var Params: TCreateParams); override; procedure CreateWnd; override; procedure CutToClipboard; virtual; procedure DoAfterPaint(ACanvas: TCanvas; ClipRect: TRect); procedure DoAutoGroupGetKey(Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Key: LongWord); virtual; procedure DoAutoSortGroupCreate(Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Group: TEasyGroup; var DoDefaultAction: Boolean); virtual; procedure DoClipboardCopy(var Handled: Boolean); virtual; procedure DoClipboardCut(var MarkAsCut, Handled: Boolean); virtual; procedure DoClipboardPaste(var Handled: Boolean); virtual; procedure DoColumnCheckChanged(Column: TEasyColumn); virtual; procedure DoColumnCheckChanging(Column: TEasyColumn; var Allow: Boolean); virtual; procedure DoColumnClick(Button: TCommonMouseButton; const Column: TEasyColumn); virtual; procedure DoColumnContextMenu(HitInfo: TEasyHitInfoColumn; WindowPoint: TPoint; var Menu: TPopupMenu); virtual; procedure DoColumnCustomView(Column: TEasyColumn; var ViewClass: TEasyViewColumnClass); virtual; procedure DoColumnDblClick(Button: TCommonMouseButton; ShiftState: TShiftState; MousePos: TPoint; Column: TEasyColumn); virtual; procedure DoColumnDropDownButtonClick(Column: TEasyColumn; Button: TCommonMouseButton; ShiftState: TShiftState; MousePos: TPoint; var DoDefault: Boolean); virtual; procedure DoColumnEnableChanged(Column: TEasyColumn); virtual; procedure DoColumnEnableChanging(Column: TEasyColumn; var Allow: Boolean); virtual; procedure DoColumnFocusChanged(Column: TEasyColumn); virtual; procedure DoColumnFocusChanging(Column: TEasyColumn; var Allow: Boolean); virtual; procedure DoColumnFreeing(Column: TEasyColumn); virtual; procedure DoColumnGetCaption(Column: TEasyColumn; Line: Integer; var Caption: WideString); virtual; procedure DoColumnGetImageIndex(Column: TEasyColumn; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); virtual; procedure DoColumnGetImageList(Column: TEasyColumn; var ImageList: TCustomImageList); virtual; procedure DoColumnGetDetail(Column: TEasyColumn; Line: Integer; var Detail: Integer); virtual; procedure DoColumnGetDetailCount(Column: TEasyColumn; var Count: Integer); virtual; procedure DoColumnImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); virtual; procedure DoColumnImageGetSize(Column: TEasyColumn; var ImageWidth, ImageHeight: Integer); virtual; procedure DoColumnImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); virtual; procedure DoColumnInitialize(Column: TEasyColumn); virtual; procedure DoColumnLoadFromStream(Column: TEasyColumn; S: TStream; Version: Integer); virtual; procedure DoColumnPaintText(Column: TEasyColumn; ACanvas: TCanvas); virtual; procedure DoColumnSaveToStream(Column: TEasyColumn; S: TStream; Version: Integer); virtual; procedure DoColumnSelectionChanged(Column: TEasyColumn); virtual; procedure DoColumnSelectionChanging(Column: TEasyColumn; var Allow: Boolean); virtual; procedure DoColumnSetCaption(Column: TEasyColumn; const Caption: WideString); virtual; procedure DoColumnSetImageIndex(Column: TEasyColumn; ImageKind: TEasyImageKind; ImageIndex: Integer); virtual; procedure DoColumnSetDetail(Column: TEasyColumn; Line: Integer; Detail: Integer); virtual; procedure DoColumnSetDetailCount(Column: TEasyColumn; DetailCount: Integer); virtual; procedure DoColumnStructureChange; procedure DoColumnThumbnailDraw(Column: TEasyColumn; ACanvas: TCanvas; ARect: TRect; var DoDefault: Boolean); virtual; procedure DoColumnSizeChanged(Column: TEasyColumn); virtual; procedure DoColumnSizeChanging(Column: TEasyColumn; Size, NewSize: Integer; var Allow: Boolean); virtual; procedure DoColumnVisibilityChanged(Column: TEasyColumn); virtual; procedure DoColumnVisibilityChanging(Column: TEasyColumn; var Allow: Boolean); virtual; procedure DoContextMenu(MousePt: TPoint; var Handled: Boolean); virtual; procedure DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); virtual; procedure DoDblClick(Button: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState); virtual; procedure DoGesture(Gesture: WideString; var Handled: Boolean); virtual; procedure DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); virtual; procedure DoGroupClick(Group: TEasyGroup; KeyStates: TCommonKeyStates; HitTest: TEasyGroupHitTestInfoSet); virtual; procedure DoGroupCollapse(Group: TEasyGroup); virtual; procedure DoGroupCollapsing(Group: TEasyGroup; var Allow: Boolean); virtual; function DoGroupCompare(Column: TEasyColumn; Group1, Group2: TEasyGroup): Integer; virtual; procedure DoGroupContextMenu(HitInfo: TEasyHitInfoGroup; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean); virtual; procedure DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); virtual; procedure DoGroupDblClick(Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoGroup); virtual; procedure DoGroupExpand(Group: TEasyGroup); virtual; procedure DoGroupExpanding(Group: TEasyGroup; var Allow: Boolean); virtual; procedure DoGroupFreeing(Group: TEasyGroup); virtual; procedure DoGroupGetCaption(Group: TEasyGroup; var Caption: WideString); virtual; procedure DoGroupGetImageIndex(Group: TEasyGroup; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); virtual; procedure DoGroupGetImageList(Group: TEasyGroup; var ImageList: TCustomImageList); virtual; procedure DoGroupGetDetail(Group: TEasyGroup; Line: Integer; var Detail: Integer); virtual; procedure DoGroupGetDetailCount(Group: TEasyGroup; var Count: Integer); virtual; procedure DoGroupImageDraw(Group: TEasyGroup; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); virtual; procedure DoGroupImageGetSize(Group: TEasyGroup; var ImageWidth, ImageHeight: Integer); virtual; procedure DoGroupImageDrawIsCustom(Group: TEasyGroup; var IsCustom: Boolean); virtual; procedure DoGroupInitialize(Group: TEasyGroup); virtual; procedure DoGroupHotTrack(Group: TEasyGroup; State: TEasyHotTrackState; MousePos: TPoint); virtual; procedure DoGroupLoadFromStream(Group: TEasyGroup; S: TStream; Version: Integer); virtual; procedure DoGroupPaintText(Group: TEasyGroup; ACanvas: TCanvas); virtual; procedure DoGroupSaveToStream(Group: TEasyGroup; S: TStream; Version: Integer); virtual; procedure DoGroupSelectionChanged(Group: TEasyGroup); virtual; procedure DoGroupSelectionChanging(Group: TEasyGroup; var Allow: Boolean); virtual; procedure DoGroupSetCaption(Group: TEasyGroup; const Caption: WideString); virtual; procedure DoGroupSetImageIndex(Group: TEasyGroup; ImageKind: TEasyImageKind; ImageIndex: Integer); virtual; procedure DoGroupSetDetail(Group: TEasyGroup; Line: Integer; Detail: Integer); virtual; procedure DoGroupSetDetailCount(Group: TEasyGroup; DetailCount: Integer); virtual; procedure DoGroupStructureChange; virtual; procedure DoGroupThumbnailDraw(Group: TEasyGroup; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); virtual; procedure DoGroupVisibilityChanged(Group: TEasyGroup); virtual; procedure DoGroupVisibilityChanging(Group: TEasyGroup; var Allow: Boolean); virtual; procedure DoHeaderDblClick(Button: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState); virtual; procedure DoHintCustomInfo(TargetObj: TEasyCollectionItem; const Info: TEasyHintInfo); virtual; procedure DoHintCustomDraw(TargetObj: TEasyCollectionItem; const Info: TEasyHintInfo); virtual; procedure DoHintPopup(TargetObj: TEasyCollectionItem; HintType: TEasyHintType; MousePos: TPoint; var AText: WideString; var HideTimeout, ReshowTimeout: Integer; var Allow: Boolean); virtual; procedure DoHintShowPause(HintShowingNow: Boolean; var PauseTime: Integer); procedure DoIncrementalSearch(Item: TEasyItem; const SearchBuffer: WideString; var CompareResult: Integer); virtual; procedure DoItemCheckChanged(Item: TEasyItem); virtual; procedure DoItemCheckChanging(Item: TEasyItem; var Allow: Boolean); virtual; procedure DoItemClick(Item: TEasyItem; KeyStates: TCommonKeyStates; HitInfo: TEasyItemHitTestInfoSet); virtual; function DoItemCompare(Column: TEasyColumn; Group: TEasyGroup; Item1, Item2: TEasyItem): Integer; virtual; procedure DoItemContextMenu(HitInfo: TEasyHitInfoItem; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean); virtual; procedure DoItemCreateEditor(Item: TEasyItem; var Editor: IEasyCellEditor); virtual; procedure DoItemCustomView(Item: TEasyItem; ViewStyle: TEasyListStyle; var View: TEasyViewItemClass); virtual; procedure DoItemDblClick(Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoItem); virtual; procedure DoItemEditBegin(Item: TEasyItem; var Column: Integer; var Allow: Boolean); virtual; procedure DoItemEdited(Item: TEasyItem; var NewValue: Variant; var Accept: Boolean); virtual; procedure DoItemEditEnd(Item: TEasyItem); virtual; procedure DoItemGetEditMenu(Editor: TEasyBaseEditor; var Menu: TPopupMenu); virtual; procedure DoItemEnableChanged(Item: TEasyItem); virtual; procedure DoItemEnableChanging(Item: TEasyItem; var Allow: Boolean); virtual; procedure DoItemFreeing(Item: TEasyItem); virtual; procedure DoItemFocusChanged(Item: TEasyItem); virtual; procedure DoItemFocusChanging(Item: TEasyItem; var Allow: Boolean); virtual; procedure DoItemGetCaption(Item: TEasyItem; Column: Integer; var ACaption: WideString); virtual; procedure DoItemGetEditCaption(Item: TEasyItem; Column: TEasyColumn; var Caption: WideString); virtual; procedure DoItemGetGroupKey(Item: TEasyItem; FocusedColumn: Integer; var Key: LongWord); virtual; procedure DoItemGetImageIndex(Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); virtual; procedure DoItemGetImageList(Item: TEasyItem; Column: Integer; var ImageList: TCustomImageList); virtual; procedure DoItemGetStateImageList(Item: TEasyItem; Column: Integer; var ImageList: TCustomImageList); virtual; procedure DoItemGetTileDetail(Item: TEasyItem; Line: Integer; var Detail: Integer); virtual; procedure DoItemGetTileDetailCount(Item: TEasyItem; var Count: Integer); virtual; procedure DoItemHotTrack(Item: TEasyItem; State: TEasyHotTrackState; MousePos: TPoint); virtual; procedure DoItemImageDraw(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); virtual; procedure DoItemImageGetSize(Item: TEasyItem; Column: TEasyColumn; var ImageWidth, ImageHeight: Integer); virtual; procedure DoItemImageDrawIsCustom(Column: TEasyColumn; Item: TEasyItem; var IsCustom: Boolean); virtual; procedure DoItemInitialize(Item: TEasyItem); virtual; procedure DoItemLoadFromStream(Item: TEasyItem; S: TStream; Version: Integer); virtual; procedure DoItemMouseDown(Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean); virtual; procedure DoItemMouseUp(Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean); virtual; procedure DoItemPaintText(Item: TEasyItem; Position: Integer; ACanvas: TCanvas); virtual; procedure DoItemSaveToStream(Item: TEasyItem; S: TStream; Version: Integer); virtual; procedure DoItemSelectionChanged(Item: TEasyItem); virtual; procedure DoItemSelectionChanging(Item: TEasyItem; var Allow: Boolean); virtual; procedure DoItemSelectionsChanged; virtual; procedure DoItemSetCaption(Item: TEasyItem; Column: Integer; const Caption: WideString); virtual; procedure DoItemSetGroupKey(Item: TEasyItem; FocusedColumn: Integer; Key: LongWord); virtual; procedure DoItemSetImageIndex(Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; ImageIndex: Integer); virtual; procedure DoItemSetTileDetail(Item: TEasyItem; Line: Integer; Detail: Integer); virtual; procedure DoItemSetTileDetailCount(Item: TEasyItem; Detail: Integer); virtual; procedure DoItemStructureChange; virtual; procedure DoItemThumbnailDraw(Item: TEasyItem; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); virtual; procedure DoItemVisibilityChanged(Item: TEasyItem); virtual; procedure DoItemVisibilityChanging(Item: TEasyItem; var Allow: Boolean); virtual; function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override; function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override; function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override; procedure DoKeyAction(var CharCode: Word; var Shift: TShiftState; var DoDefault: Boolean); virtual; procedure DoOLEDragEnd(ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); virtual; procedure DoOLEDragStart(ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); virtual; procedure DoOLEDropSourceQueryContineDrag(EscapeKeyPressed: Boolean; KeyStates: TCommonKeyStates; var QueryResult: TEasyQueryDragResult); virtual; procedure DoOLEDropSourceGiveFeedback(Effect: TCommonDropEffects; var UseDefaultCursors: Boolean); virtual; procedure DoOLEDropTargetDragEnter(DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect); virtual; procedure DoOLEDropTargetDragOver(KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect); virtual; procedure DoOLEDropTargetDragLeave; virtual; procedure DoOLEDropTargetDragDrop(DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect; var Handled: Boolean); virtual; procedure DoOLEGetCustomFormats(var Formats: TFormatEtcArray); virtual; procedure DoOLEGetData(const FormatEtcIn: TFormatEtc; var Medium: TStgMedium; var Handled: Boolean); virtual; procedure DoOLEGetDataObject(var DataObject: IDataObject); virtual; procedure DoPaintBkGnd(ACanvas: TCanvas; AWindowRect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); virtual; procedure DoPaintHeaderBkGnd(ACanvas: TCanvas; ARect: TRect; var Handled: Boolean); virtual; procedure DoPaintRect(ACanvas: TCanvas; WindowClipRect: TRect; SelectedOnly: Boolean); virtual; procedure DoQueryOLEData(const FormatEtcIn: TFormatEtc; var FormatAvailable: Boolean; var Handled: Boolean); virtual; procedure DoResize(DeltaX, DeltaY: Integer); virtual; procedure DoScroll(DeltaX, DeltaY: Integer); virtual; procedure DoThreadCallback(var Msg: TWMThreadRequest); virtual; procedure DoUpdate; override; procedure DoViewChange; virtual; procedure DestroyWnd; override; function DragInitiated: Boolean; procedure FinalizeDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates); procedure HandleDblClick(Button: TCommonMouseButton; Msg: TWMMouse); virtual; procedure HandleKeyDown(Msg: TWMKeyDown); virtual; procedure HandleMouseDown(Button: TCommonMouseButton; Msg: TWMMouse); virtual; procedure HandleMouseUp(Button: TCommonMouseButton; Msg: TWMMouse); virtual; procedure InitializeDragPendings(HitItem: TEasyItem; WindowPoint: TPoint; KeyState: TCommonKeyStates; AllowDrag, AllowDragRect: Boolean); function IsFontStored: Boolean; function IsHeaderMouseMsg(MousePos: TSmallPoint; ForceTest: Boolean = False): Boolean; procedure MarkSelectedCut; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure PasteFromClipboard; virtual; procedure ResizeBackBits(NewWidth, NewHeight: Integer); procedure SetView(Value: TEasyListStyle); virtual; procedure WMChar(var Msg: TWMChar); message WM_CHAR; procedure WMClose(var Msg: TWMClose); message WM_CLOSE; procedure WMContextMenu(var Msg: TMessage); message WM_CONTEXTMENU; procedure WMDestroy(var Msg: TMessage); message WM_DESTROY; procedure WMEasyThreadCallback(var Msg: TWMThreadRequest); message WM_COMMONTHREADCALLBACK; procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND; procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE; procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL; procedure WMKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN; procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS; procedure WMLButtonDblClk(var Msg: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN; procedure WMLButtonUp(var Msg: TWMLButtonUp); message WM_LBUTTONUP; procedure WMMButtonDblClk(var Msg: TWMMButtonDblClk); message WM_MBUTTONDBLCLK; procedure WMMButtonDown(var Msg: TWMMButtonDown); message WM_MBUTTONDOWN; procedure WMMButtonUp(var Msg: TWMMButtonUp); message WM_MBUTTONUP; procedure WMMouseActivate(var Msg: TWMMouseActivate); message WM_MOUSEACTIVATE; procedure WMMouseMove(var Msg: TWMMouseMove); message WM_MOUSEMOVE; procedure WMPaint(var Msg: TWMPaint); message WM_PAINT; procedure WMNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE; procedure WMNCPaint(var Msg: TWMNCPaint); message WM_NCPAINT; procedure WMRButtonDblClk(var Msg: TWMRButtonDblClk); message WM_RBUTTONDBLCLK; procedure WMRButtonDown(var Msg: TWMRButtonDown); message WM_RBUTTONDOWN; procedure WMRButtonUp(var Msg: TWMRButtonUp); message WM_RBUTTONUP; procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR; procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS; procedure WMSize(var Msg: TWMSize); message WM_SIZE; procedure WMTabMoveFocus(var Msg: TMessage); message WM_TABMOVEFOCUS; procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL; procedure WMWindowPosChanged(var Msg: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING; property AllowHiddenCheckedItems: Boolean read FAllowInvisibleCheckedItems write FAllowInvisibleCheckedItems default False; property BackBits: TBitmap read FBackBits write FBackBits; property BackGround: TEasyBackgroundManager read FBackGround write SetBackGround; property BevelInner default bvLowered; property CacheDoubleBufferBits: Boolean read FCacheDoubleBufferBits write SetCacheDoubleBufferBits; property CheckManager: TEasyCheckManager read FCheckManager write FCheckManager; property Color default clWindow; property CellSizes: TEasyCellSizes read FCellSizes write FCellSizes; property DisabledBlendAlpha: Byte read FDisabledBlendAlpha write FDisabledBlendAlpha default 128; property DisabledBlendColor: TColor read FDisabledBlendColor write FDisabledBlendColor default clWindow; property DragManager: TEasyOLEDragManager read FDragManager write FDragManager; property DragRect: TEasyDragRectManager read FDragRect write FDragRect; property DropTarget: IDropTarget read FDropTarget write FDropTarget; property EditManager: TEasyEditManager read FEditManager write FEditManager; property Gesture: TEasyGestureManager read FGesture write FGesture; property GlobalImages: TEasyGlobalImageManager read FGlobalImages write FGlobalImages; property GroupCollapseButton: TBitmap read GetGroupCollapseImage write SetGroupCollapseImage; property GroupExpandButton: TBitmap read GetGroupExpandImage write SetGroupExpandImage; property GroupFont: TFont read FGroupFont write SetGroupFont stored IsFontStored; property Groups: TEasyGroups read FGroups write FGroups; property Header: TEasyHeader read FHeader write FHeader; property HintAlignment: TAlignment read FHintAlignment write FHintAlignment; property HintData: TEasyHintInfoRec read FHintData write FHintData; property HintInfo: TEasyHintInfo read FHintInfo write FHintInfo; property HintType: TEasyHintType read GetHintType write SetHintType default ehtText; property HotTrack: TEasyHotTrackManager read FHotTrack write FHotTrack; property ImagesGroup: TCustomImageList read FImagesGroup write SetImagesGroup; property ImagesSmall: TCustomImageList read FImagesSmall write SetImagesSmall; property ImagesLarge: TCustomImageList read FImagesLarge write SetImagesLarge; property ImagesExLarge: TCustomImageList read FImagesExLarge write SetImagesExLarge; property ImagesState: TCustomImageList read FImagesState write SetImagesState; property IncrementalSearch: TEasyIncrementalSearchManager read FIncrementalSearch write FIncrementalSearch; property Items: TEasyGlobalItems read FItems; property LastMousePos: TSmallPoint read FLastMousePos write FLastMousePos; property NCCanvas: TCanvas read FNCCanvas write FNCCanvas; property OnAfterPaint: TAfterPaintEvent read FOnAfterPaint write FOnAfterPaint; property OnAutoGroupGetKey: TAutoGroupGetKeyEvent read FOnAutoGroupGetKey write FOnAutoGroupGetKey; property OnAutoSortGroupCreate: TAutoSortGroupCreateEvent read FOnAutoSortGroupCreate write FOnAutoSortGroupCreate; property OnClipboardCopy: TEasyClipboardEvent read FOnClipboardCopy write FOnClipboardCopy; property OnClipboardCut: TEasyClipboardCutEvent read FOnClipboardCut write FOnClipboardCut; property OnClipboardPaste: TEasyClipboardEvent read FOnClipboardPaste write FOnClipboardPaste; property OnColumnCheckChanged: TColumnCheckChangeEvent read FOnColumnCheckChange write FOnColumnCheckChange; property OnColumnCheckChanging: TColumnCheckChangingEvent read FOnColumnCheckChanging write FOnColumnCheckChanging; property OnColumnClick: TColumnClickEvent read FOnColumnClick write FOnColumnClick; property OnColumnContextMenu: TColumnContextMenuEvent read FOnColumnContextMenu write FOnColumnContextMenu; property OnColumnCustomView: TColumnCustomViewEvent read FOnColumnCustomView write FOnColumnCustomView; property OnColumnDblClick: TColumnDblClickEvent read FOnColumnDblClick write FOnColumnDblClick; property OnColumnDropDownButtonClick: TColumnDropDownButtonClickEvent read FOnColumnDropDownButtonClick write FOnColumnDropDownButtonClick; property OnColumnEnableChanged: TColumnEnableChangeEvent read FOnColumnEnableChange write FOnColumnEnableChange; property OnColumnEnableChanging: TColumnEnableChangingEvent read FOnColumnEnableChanging write FOnColumnEnableChanging; property OnColumnFocusChanged: TColumnFocusChangeEvent read FOnColumnFocusChanged write FOnColumnFocusChanged; property OnColumnFocusChanging: TColumnFocusChangingEvent read FOnColumnFocusChanging write FOnColumnFocusChanging; property OnColumnFreeing: TColumnFreeingEvent read FOnColumnFreeing write FOnColumnFreeing; property OnColumnGetCaption: TColumnGetCaptionEvent read FOnColumnGetCaption write FOnColumnGetCaption; property OnColumnGetImageIndex: TColumnGetImageIndexEvent read FOnColumnGetImageIndex write FOnColumnGetImageIndex; property OnColumnGetImageList: TColumnGetImageListEvent read FOnColumnGetImageList write FOnColumnGetImageList; property OnColumnGetDetail: TColumnGetDetailEvent read FOnColumnGetDetail write FOnColumnGetDetail; property OnColumnGetDetailCount: TColumnGetDetailCountEvent read FOnColumnGetDetailCount write FOnColumnGetDetailCount; property OnColumnImageDraw: TColumnImageDrawEvent read FOnColumnImageDraw write FOnColumnImageDraw; property OnColumnImageGetSize: TColumnImageGetSizeEvent read FOnColumnImageGetSize write FOnColumnImageGetSize; property OnColumnImageDrawIsCustom: TColumnImageDrawIsCustomEvent read FOnColumnImageDrawIsCustom write FOnColumnImageDrawIsCustom; property OnColumnInitialize: TColumnInitializeEvent read FOnColumnInitialize write FOnColumnInitialize; property OnColumnLoadFromStream: TEasyColumnLoadFromStreamEvent read FOnColumnLoadFromStream write FOnColumnLoadFromStream; property OnColumnPaintText: TColumnPaintTextEvent read FOnColumnPaintText write FOnColumnPaintText; property OnColumnSaveToStream: TEasyColumnSaveToStreamEvent read FOnColumnSaveToStream write FOnColumnSaveToStream; property OnColumnSelectionChanged: TColumnSelectionChangeEvent read FOnColumnSelectionChanged write FOnColumnSelectionChanged; property OnColumnSelectionChanging: TColumnSelectionChangingEvent read FOnColumnSelectionChanging write FOnColumnSelectionChanging; property OnColumnSetCaption: TColumnSetCaptionEvent read FOnColumnSetCaption write FOnColumnSetCaption; property OnColumnSetImageIndex: TColumnSetImageIndexEvent read FOnColumnSetImageIndex write FOnColumnSetImageIndex; property OnColumnSetDetail: TColumnSetDetailEvent read FOnColumnSetDetail write FOnColumnSetDetail; property OnColumnStructureChange: TNotifyEvent read FOnColumnStructureChange write FOnColumnStructureChange; property OnColumnThumbnailDraw: TColumnThumbnailDrawEvent read FOnColumnThumbnailDraw write FOnColumnThumbnailDraw; property OnColumnSizeChanged: TColumnSizeChangedEvent read FOnColumnSizeChanged write FOnColumnSizeChanged; property OnColumnSizeChanging: TColumnSizeChangingEvent read FOnColumnSizeChanging write FOnColumnSizeChanging; property OnColumnVisibilityChanged: TColumnVisibilityChangeEvent read FOnColumnVisibilityChanged write FOnColumnVisibilityChanged; property OnColumnVisibilityChanging: TColumnVisibilityChangingEvent read FOnColumnVisibilityChanging write FOnColumnVisibilityChanging; property OnContextMenu: TContextMenuEvent read FOnContextMenu write FOnContextMenu; property OnCustomGrid: TCustomGridEvent read FOnCustomGrid write FOnCustomGrid; property OnDblClick: TDblClickEvent read FOnDblClick write FOnDblClick; property OnGetDragImage: TGetDragImageEvent read FOnGetDragImage write FOnGetDragImage; property OnGroupClick: TGroupClickEvent read FOnGroupClick write FOnGroupClick; property OnGroupCollapse: TGroupCollapseEvent read FOnGroupCollapse write FOnGroupCollapse; property OnGroupCollapsing: TGroupCollapsingEvent read FOnGroupCollapsing write FOnGroupCollapsing; property OnGroupCompare: TGroupCompareEvent read FOnGroupCompare write FOnGroupCompare; property OnGroupContextMenu: TGroupContextMenuEvent read FOnGroupContextMenu write FOnGroupContextMenu; property OnGroupCustomView: TGroupCustomViewEvent read FOnGroupCustomView write FOnGroupCustomView; property OnGroupDblClick: TGroupDblClickEvent read FOnGroupDblClick write FOnGroupDblClick; property OnGroupExpand: TGroupExpandEvent read FOnGroupExpand write FOnGroupExpand; property OnGroupExpanding: TGroupExpandingEvent read FOnGroupExpanding write FOnGroupExpanding; property OnGroupFocusChanged: TGroupFocusChangeEvent read FOnGroupFocusChanged write FOnGroupFocusChanged; property OnGroupFocusChanging: TGroupFocusChangingEvent read FOnGroupFocusChanging write FOnGroupFocusChanging; property OnGroupFreeing: TGroupFreeingEvent read FOnGroupFreeing write FOnGroupFreeing; property OnGroupGetCaption: TGroupGetCaptionEvent read FOnGroupGetCaption write FOnGroupGetCaption; property OnGroupGetImageIndex: TGroupGetImageIndexEvent read FOnGroupGetImageIndex write FOnGroupGetImageIndex; property OnGroupGetImageList: TGroupGetImageListEvent read FOnGroupGetImageList write FOnGroupGetImageList; property OnGroupGetDetail: TGroupGetDetailEvent read FOnGroupGetDetailIndex write FOnGroupGetDetailIndex; property OnGroupGetDetailCount: TGroupGetDetailCountEvent read FOnGroupGetDetailCount write FOnGroupGetDetailCount; property OnGroupHotTrack: TGroupHotTrackEvent read FOnGroupHotTrack write FOnGroupHotTrack; property OnGroupImageDraw: TGroupImageDrawEvent read FOnGroupImageDrawEvent write FOnGroupImageDrawEvent; property OnGroupImageGetSize: TGroupImageGetSizeEvent read FGroupImageGetSize write FGroupImageGetSize; property OnGroupImageDrawIsCustom: TGroupImageDrawIsCustomEvent read FOnGroupImageDrawIsCustom write FOnGroupImageDrawIsCustom; property OnGroupInitialize: TGroupInitializeEvent read FOnGroupInitialize write FOnGroupInitialize; property OnGroupLoadFromStream: TGroupLoadFromStreamEvent read FOnGroupLoadFromStream write FOnGroupLoadFromStream; property OnGroupPaintText: TGroupPaintTextEvent read FOnGroupPaintText write FOnGroupPaintText; property OnGroupSaveToStream: TGroupSaveToStreamEvent read FOnGroupSaveToStream write FOnGroupSaveToStream; property OnGroupSelectionChanged: TGroupSelectionChangeEvent read FOnGroupSelectionChanged write FOnGroupSelectionChanged; property OnGroupSelectionChanging: TGroupSelectionChangingEvent read FOnGroupSelectionChanging write FOnGroupSelectionChanging; property OnGroupSetCaption: TGroupSetCaptionEvent read FOnGroupSetCaption write FOnGroupSetCaption; property OnGroupSetImageIndex: TGroupSetImageIndexEvent read FOnGroupSetImageIndex write FOnGroupSetImageIndex; property OnGroupSetDetail: TGroupSetDetailEvent read FOnGroupSetDetail write FOnGroupSetDetail; property OnGroupStructureChange: TNotifyEvent read FOnGroupStructureChange write FOnGroupStructureChange; property OnGroupThumbnailDraw: TGroupThumbnailDrawEvent read FOnGroupThumbnailDraw write FOnGroupThumbnailDraw; property OnGroupVisibilityChanged: TGroupVisibilityChangeEvent read FOnGroupVisibilityChanged write FOnGroupVisibilityChanged; property OnGroupVisibilityChanging: TGroupVisibilityChangingEvent read FOnGroupVisibilityChanging write FOnGroupVisibilityChanging; property OnHeaderDblClick: THeaderDblClickEvent read FOnHeaderDblClick write FOnHeaderDblClick; property OnHeaderMouseDown: THeaderMouseEvent read FOnHeaderMouseDown write FOnHeaderMouseDown; property OnHeaderMouseMove: TMouseMoveEvent read FOnHeaderMouseMove write FOnHeaderMouseMove; property OnHeaderMouseUp: THeaderMouseEvent read FOnHeaderMouseUp write FOnHeaderMouseUp; property OnHintCustomDraw: THintCustomDrawEvent read FOnHintCustomDraw write FOnHintCustomDraw; property OnHintCustomInfo: THintCustomizeInfoEvent read FOnHintCustomInfo write FOnHintCustomInfo; property OnHintPauseTime: THintPauseTimeEvent read FOnHintPauseTime write FOnHintPauseTime; property OnHintPopup: THintPopupEvent read FOnHintPopup write FOnHintPopup; property OnIncrementalSearch: TIncrementalSearchEvent read FOnIncrementalSearch write FOnIncrementalSearch; property OnItemCheckChange: TItemCheckChangeEvent read FOnItemCheckChange write FOnItemCheckChange; property OnItemCheckChanging: TItemCheckChangingEvent read FOnItemCheckChanging write FOnItemCheckChanging; property OnItemClick: TItemClickEvent read FOnItemClick write FOnItemClick; property OnItemCompare: TItemCompareEvent read FOnItemCompare write FOnItemCompare; property OnItemContextMenu: TItemContextMenuEvent read FOnItemContextMenu write FOnItemContextMenu; property OnItemCreateEditor: TItemCreateEditorEvent read FOnItemCreateEditor write FOnItemCreateEditor; property OnItemCustomView: TItemCustomViewEvent read FOnItemCustomView write FOnItemCustomView; property OnItemDblClick: TItemDblClickEvent read FOnItemDblClick write FOnItemDblClick; property OnItemEditBegin: TItemEditBegin read FOnItemEditBegin write FOnItemEditBegin; property OnItemEdited: TItemEditedEvent read FOnItemEdited write FOnItemEdited; property OnItemEditEnd: TItemEditEnd read FOnItemEditEnd write FOnItemEditEnd; property OnItemEnableChange: TItemEnableChangeEvent read FOnItemEnableChange write FOnItemEnableChange; property OnItemEnableChanging: TItemEnableChangingEvent read FOnItemEnableChanging write FOnItemEnableChanging; property OnItemFreeing: TItemFreeingEvent read FOnItemFreeing write FOnItemFreeing; property OnItemFocusChanged: TItemFocusChangeEvent read FOnItemFocusChanged write FOnItemFocusChanged; property OnItemFocusChanging: TItemFocusChangingEvent read FOnItemFocusChanging write FOnItemFocusChanging; property OnItemGetCaption: TItemGetCaptionEvent read FOnItemGetCaption write FOnItemGetCaption; property OnItemGetEditCaption: TEasyItemGetCaptionEvent read FOnItemGetEditCaption write FOnItemGetEditCaption; property OnItemGetEditMenu: TItemGetEditMenuEvent read FOnItemGetEditMenu write FOnItemGetEditMenu; property OnItemGetGroupKey: TItemGetGroupKeyEvent read FOnItemGetGroupKey write FOnItemGetGroupKey; property OnItemHotTrack: TItemHotTrackEvent read FOnItemHotTrack write FOnItemHotTrack; property OnItemGetImageIndex: TItemGetImageIndexEvent read FOnItemGetImageIndex write FOnItemGetImageIndex; property OnItemGetImageList: TItemGetImageListEvent read FOnItemGetImageList write FOnItemGetImageList; property OnItemGetStateImageList: TItemGetImageListEvent read FOnItemGetStateImageList write FOnItemGetStateImageList; property OnItemGetTileDetail: TItemGetTileDetailEvent read FOnItemGetTileDetailIndex write FOnItemGetTileDetailIndex; property OnItemGetTileDetailCount: TItemGetTileDetailCountEvent read FOnItemGetTileDetailCount write FOnItemGetTileDetailCount; property OnItemImageDraw: TItemImageDrawEvent read FOnItemImageDraw write FOnItemImageDraw; property OnItemImageGetSize: TItemImageGetSizeEvent read FOnItemImageGetSize write FOnItemImageGetSize; property OnItemImageDrawIsCustom: TItemImageDrawIsCustomEvent read FOnItemImageDrawIsCustom write FOnItemImageDrawIsCustom; property OnItemLoadFromStream: TItemLoadFromStreamEvent read FOnItemLoadFromStream write FOnItemLoadFromStream; property OnItemInitialize: TItemInitializeEvent read FOnItemInitialize write FOnItemInitialize; property OnItemMouseDown: TItemMouseDownEvent read FOnItemMouseDown write FOnItemMouseDown; property OnItemMouseUp: TItemMouseUpEvent read FOnItemMouseUp write FOnItemMouseUp; property OnItemPaintText: TItemPaintTextEvent read FOnItemPaintText write FOnItemPaintText; property OnItemSaveToStream: TItemSaveToStreamEvent read FOnItemSaveToStream write FOnItemSaveToStream; property OnItemSelectionChanged: TItemSelectionChangeEvent read FOnItemSelectionChanged write FOnItemSelectionChanged; property OnItemSelectionChanging: TItemSelectionChangingEvent read FOnItemSelectionChanging write FOnItemSelectionChanging; property OnItemSelectionsChanged: TEasyItemSelectionsChangedEvent read FOnItemSelectionsChanged write FOnItemSelectionsChanged; property OnItemSetCaption: TItemSetCaptionEvent read FOnItemSetCaption write FOnItemSetCaption; property OnItemSetGroupKey: TItemSetGroupKeyEvent read FOnItemSetGroupKey write FOnItemSetGroupKey; property OnItemSetImageIndex: TItemSetImageIndexEvent read FOnItemSetImageIndex write FOnItemSetImageIndex; property OnItemSetTileDetail: TItemSetTileDetailEvent read FOnItemSetTileDetail write FOnItemSetTileDetail; property OnItemStructureChange: TNotifyEvent read FOnItemStructureChange write FOnItemStructureChange; property OnItemThumbnailDraw: TItemThumbnailDrawEvent read FOnItemThumbnailDraw write FOnItemThumbnailDraw; property OnItemVisibilityChanged: TItemVisibilityChangeEvent read FOnItemVisibilityChanged write FOnItemVisibilityChanged; property OnItemVisibilityChanging: TItemVisibilityChangingEvent read FOnItemVisibilityChanging write FOnItemVisibilityChanging; property OnKeyAction: TEasyKeyActionEvent read FOnKeyAction write FOnKeyAction; property OnMouseGesture: TEasyGestureEvent read FOnMouseGesture write FOnMouseGesture; property OnOLEDragEnd: TOLEDropSourceDragEndEvent read FOnOLEDragEnd write FOnOLEDragEnd; property OnOLEDragStart: TOLEDropSourceDragStartEvent read FOnOLEDragStart write FOnOLEDragStart; property OnOLEDragEnter: TOLEDropTargetDragEnterEvent read FOnOLEDragEnter write FOnOLEDragEnter; property OnOLEDragOver: TOLEDropTargetDragOverEvent read FOnOLEDragOver write FOnOLEDragOver; property OnOLEDragLeave: TOLEDropTargetDragLeaveEvent read FOnOLEDragLeave write FOnOLEDragLeave; property OnOLEDragDrop: TOLEDropTargetDragDropEvent read FOnOLEDragDrop write FOnOLEDragDrop; property OnOLEGetCustomFormats: TOLEGetCustomFormatsEvent read FOnOLEGetCustomFormats write FOnOLEGetCustomFormats; property OnOLEGetData: TOLEGetDataEvent read FOnOLEGetData write FOnOLEGetData; property OnOLEGetDataObject: FOLEGetDataObjectEvent read FOnOLEGetDataObject write FOnOLEGetDataObject; property OnOLEQueryContineDrag: TOLEDropSourceQueryContineDragEvent read FOnOLEQueryContineDrag write FOnOLEQueryContineDrag; property OnOLEGiveFeedback: TOLEDropSourceGiveFeedbackEvent read FOnOLEGiveFeedback write FOnOLEGiveFeedback; property OnOLEQueryData: TOLEQueryDataEvent read FOnOLEQueryData write FOnOLEQueryData; property OnPaintBkGnd: TPaintBkGndEvent read FOnPaintBkGnd write FOnPaintBkGnd; property OnPaintHeaderBkGnd: TPaintHeaderBkGndEvent read FOnPaintHeaderBkGnd write FOnPaintHeaderBkGnd; property OnScroll: TEasyScrollEvent read FOnScroll write FOnScroll; property OnViewChange: TViewChangedEvent read FOnViewChange write FOnViewChange; property PaintInfoColumn: TEasyPaintInfoBaseColumn read GetPaintInfoColumn write SetPaintInfoColumn; property PaintInfoGroup: TEasyPaintInfoBaseGroup read GetPaintInfoGroup write SetPaintInfoGroup; property PaintInfoItem: TEasyPaintInfoBaseItem read GetPaintInfoItem write SetPaintInfoItem; {$IFDEF COMPILER_7_UP}property ParentBackground default False;{$ENDIF COMPILER_7_UP} property ParentColor default False; property PopupMenuHeader: TPopupMenu read FPopupMenuHeader write FPopupMenuHeader; property ScratchCanvas: TControlCanvas read GetScratchCanvas write FScratchCanvas; property Scrollbars: TEasyScrollbarManager read FScrollbars write FScrollbars; property Selection: TEasySelectionManager read FSelection write SetSelection; property ShowGroupMargins: Boolean read FShowGroupMargins write SetShowGroupMargins default False; property ShowInactive: Boolean read FShowInactive write SetShowInactive default False; property ShowThemedBorder: Boolean read FShowThemedBorder write SetShowThemedBorder default True; property Sort: TEasySortManager read FSort write FSort; property TabStop default True; property View: TEasyListStyle read FView write SetView; property WheelMouseDefaultScroll: TEasyDefaultWheelScroll read FWheelMouseDefaultScroll write FWheelMouseDefaultScroll default edwsVert; property WheelMouseScrollModifierEnabled: Boolean read FWheelMouseScrollModifierEnabled write FWheelMouseScrollModifierEnabled default True; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function ClientInViewportCoords: TRect; function IsGrouped: Boolean; virtual; function IsThumbnailView: Boolean; function IsVertView: Boolean; function ScrollHeaderHorz: Boolean; procedure AutoFitAllCells(VisibleOnly: Boolean); procedure BeginUpdate; override; procedure EndUpdate(Invalidate: Boolean = True); override; procedure Loaded; override; procedure LoadFromFile(FileName: WideString; Mode: Word); procedure LoadFromStream(S: TStream); virtual; procedure SaveToFile(FileName: WideString; Mode: Word); procedure SaveToStream(S: TStream); virtual; property ForcePaint: Boolean read FForcePaint write FForcePaint; property States: TEasyControlStates read FStates write FStates; property TopItem: TEasyItem read GetTopItem; published end; TEasyBaseEditor = class(TEasyInterfacedPersistent, IEasyCellEditor) private FEditColumn: TEasyColumn; FEditor: TWinControl; FItem: TEasyItem; FModified: Boolean; FOldWndProc: TWndMethod; FRectArray: TEasyRectArrayObject; function GetEditor: TWinControl; virtual; function GetListview: TCustomEasyListview; procedure SetEditor(const Value: TWinControl); virtual; protected function EditText(Item: TEasyItem; Column: TEasyColumn): WideString; virtual; function GetEditorColor: TColor; procedure CalculateEditorRect(NewText: WideString; var NewRect: TRect); virtual; abstract; procedure CreateEditor(var AnEditor: TWinControl; Column: TEasyColumn; Parent: TWinControl); virtual; abstract; function GetEditorFont: TFont; virtual; abstract; function GetText: Variant; virtual; abstract; procedure ResizeEditor; property EditColumn: TEasyColumn read FEditColumn write FEditColumn; property Editor: TWinControl read GetEditor write SetEditor; property Item: TEasyItem read FItem write FItem; property Listview: TCustomEasyListview read GetListview; property Modified: Boolean read FModified write FModified; property OldWndProc: TWndMethod read FOldWndProc write FOldWndProc; property RectArray: TEasyRectArrayObject read FRectArray write FRectArray; public function AcceptEdit: Boolean; {IEasyCellEditor} procedure ControlWndHookProc(var Message: TMessage); {IEasyCellEditor} function GetHandle: HWnd; {IEasyCellEditor} function GetModified: Boolean; {IEasyCellEditor} function PtInEditControl(WindowPt: TPoint): Boolean; {IEasyCellEditor} procedure Finalize; {IEasyCellEditor} procedure Hide; {IEasyCellEditor} procedure Initialize(AnItem: TEasyItem; Column: TEasyColumn); {IEasyCellEditor} procedure SelectAll; virtual; abstract; procedure SetEditorFocus; virtual; {IEasyCellEditor} procedure Show; {IEasyCellEditor} property Handle: HWnd read GetHandle; end; TEasyStringEditor = class(TEasyBaseEditor) protected procedure CalculateEditorRect(NewText: WideString; var NewRect: TRect); override; procedure CreateEditor(var AnEditor: TWinControl; Column: TEasyColumn; Parent: TWinControl); override; function GetEditorFont: TFont; override; function GetText: Variant; override; procedure DoEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState; var DoDefault: Boolean); virtual; procedure OnEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public procedure SelectAll; override; procedure SetEditorFocus; override; end; TEasyMemoEditor = class(TEasyBaseEditor) protected procedure CalculateEditorRect(NewText: WideString; var NewRect: TRect); override; procedure CreateEditor(var AnEditor: TWinControl; Column: TEasyColumn; Parent: TWinControl); override; function GetEditorFont: TFont; override; function GetText: Variant; override; procedure DoEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState; var DoDefault: Boolean); virtual; procedure OnEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public procedure SelectAll; override; procedure SetEditorFocus; override; end; TEasyListview = class(TCustomEasyListview) private function GetPaintInfoColumn: TEasyPaintInfoColumn; reintroduce; virtual; function GetPaintInfoGroup: TEasyPaintInfoGroup; reintroduce; virtual; function GetPaintInfoItem: TEasyPaintInfoItem; reintroduce; virtual; procedure SetPaintInfoColumn(const Value: TEasyPaintInfoColumn); reintroduce; virtual; procedure SetPaintInfoGroup(const Value: TEasyPaintInfoGroup); reintroduce; virtual; procedure SetPaintInfoItem(const Value: TEasyPaintInfoItem); reintroduce; virtual; public property CheckManager; property GlobalImages; property Items; property States; published property Align; property AllowHiddenCheckedItems; property Anchors; property BackGround; property BevelKind; property BevelInner; property BevelOuter; property BevelWidth; property BiDiMode; property BorderWidth; property CacheDoubleBufferBits; property CellSizes; property Color; property Constraints; property Ctl3D; property DisabledBlendAlpha; property DisabledBlendColor; property EditManager; property Gesture; property ImagesState; property UseDockManager default True; property DragKind; property DragManager; property Font; property GroupCollapseButton; property GroupExpandButton; property GroupFont; property Groups; property HintAlignment; property HintType; property Header; property HotTrack; property IncrementalSearch; property ImagesGroup; property ImagesSmall; property ImagesLarge; property ImagesExLarge; property PaintInfoColumn: TEasyPaintInfoColumn read GetPaintInfoColumn write SetPaintInfoColumn; property PaintInfoGroup: TEasyPaintInfoGroup read GetPaintInfoGroup write SetPaintInfoGroup; property PaintInfoItem: TEasyPaintInfoItem read GetPaintInfoItem write SetPaintInfoItem; property ParentBiDiMode; {$IFDEF COMPILER_7_UP}property ParentBackground;{$ENDIF} property ParentColor; property ParentCtl3D; property ParentFont; property ParentShowHint; property PopupMenu; property PopupMenuHeader; property Scrollbars; property ShowGroupMargins; property ShowInactive; property ShowThemedBorder; property ShowHint; property Selection; property Sort; property TabOrder; property TabStop; property Themed; property View; property Visible; property WheelMouseDefaultScroll; property WheelMouseScrollModifierEnabled; property OnAfterPaint; property OnCanResize; property OnClick; property OnConstrainedResize; {$IFDEF COMPILER_5_UP} property OnContextPopup; {$ENDIF} property OnAutoGroupGetKey; property OnAutoSortGroupCreate; property OnClipboardCopy; property OnClipboardCut; property OnClipboardPaste; property OnColumnCheckChanged; property OnColumnCheckChanging; property OnColumnClick; property OnColumnContextMenu; property OnColumnCustomView; property OnColumnDblClick; property OnColumnDropDownButtonClick; property OnColumnEnableChanged; property OnColumnEnableChanging; property OnColumnFreeing; property OnColumnGetCaption; property OnColumnGetImageIndex; property OnColumnGetImageList; property OnColumnGetDetail; property OnColumnGetDetailCount; property OnColumnImageDraw; property OnColumnImageGetSize; property OnColumnImageDrawIsCustom; property OnColumnInitialize; property OnColumnLoadFromStream; property OnColumnPaintText; property OnColumnSaveToStream; property OnColumnSelectionChanged; property OnColumnSelectionChanging; property OnColumnSetCaption; property OnColumnSetImageIndex; property OnColumnSetDetail; property OnColumnSizeChanged; property OnColumnSizeChanging; property OnColumnStructureChange; property OnColumnVisibilityChanged; property OnColumnVisibilityChanging; property OnCustomGrid; property OnDblClick; property OnDragDrop; property OnDragOver; property OnDockDrop; property OnDockOver; property OnEndDock; property OnEndDrag; property OnEndUpdate; property OnEnter; property OnExit; property OnGetDragImage; property OnGetSiteInfo; property OnGroupClick; property OnGroupCollapse; property OnGroupCollapsing; property OnGroupCompare; property OnGroupContextMenu; property OnGroupCustomView; property OnGroupDblClick; property OnGroupExpand; property OnGroupExpanding; property OnGroupFreeing; property OnGroupGetCaption; property OnGroupGetImageIndex; property OnGroupGetImageList; property OnGroupGetDetail; property OnGroupGetDetailCount; property OnGroupImageDraw; property OnGroupImageGetSize; property OnGroupImageDrawIsCustom; property OnGroupInitialize; property OnGroupLoadFromStream; property OnGroupPaintText; property OnGroupHotTrack; property OnGroupSaveToStream; property OnGroupSetCaption; property OnGroupSetImageIndex; property OnGroupSetDetail; property OnGroupStructureChange; property OnGroupVisibilityChanged; property OnGroupVisibilityChanging; property OnHeaderDblClick; property OnHeaderMouseDown; property OnHeaderMouseMove; property OnHeaderMouseUp; property OnHintCustomInfo; property OnHintCustomDraw; property OnHintPauseTime; property OnHintPopup; property OnIncrementalSearch; property OnItemCheckChange; property OnItemCheckChanging; property OnItemClick; property OnItemCompare; property OnItemContextMenu; property OnItemCreateEditor; property OnItemCustomView; property OnItemDblClick; property OnItemEditBegin; property OnItemEdited; property OnItemEditEnd; property OnItemEnableChange; property OnItemEnableChanging; property OnItemFreeing; property OnItemFocusChanged; property OnItemFocusChanging; property OnItemGetCaption; property OnItemGetEditCaption; property OnItemGetEditMenu; property OnItemGetGroupKey; property OnItemGetImageIndex; property OnItemGetImageList; property OnItemGetTileDetail; property OnItemGetTileDetailCount; property OnItemHotTrack; property OnItemImageDraw; property OnItemImageGetSize; property OnItemImageDrawIsCustom; property OnItemInitialize; property OnItemLoadFromStream; property OnItemMouseDown; property OnItemMouseUp; property OnItemPaintText; property OnItemSaveToStream; property OnItemSelectionChanged; property OnItemSelectionChanging; property OnItemSelectionsChanged; property OnItemSetCaption; property OnItemSetGroupKey; property OnItemSetImageIndex; property OnItemSetTileDetail; property OnItemStructureChange; property OnItemThumbnailDraw; property OnItemVisibilityChanged; property OnItemVisibilityChanging; property OnKeyAction; property OnMouseGesture; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; property OnOLEDragEnd; property OnOLEDragStart; property OnOLEDragEnter; property OnOLEDragOver; property OnOLEDragLeave; property OnOLEDragDrop; property OnOLEGetCustomFormats; property OnOLEGetData; property OnOLEGetDataObject; property OnOLEQueryContineDrag; property OnOLEGiveFeedback; property OnOLEQueryData; property OnPaintHeaderBkGnd; property OnPaintBkGnd; property OnResize; property OnScroll; property OnStartDock; property OnStartDrag; property OnUnDock; property OnViewChange; end; TEasyBaseTaskBand = class(TCustomEasyListview) protected function CreateColumnPaintInfo: TEasyPaintInfoBaseColumn; override; function CreateGroupPaintInfo: TEasyPaintInfoBaseGroup; override; function CreateItemPaintInfo: TEasyPaintInfoBaseItem; override; function GetPaintInfoColumn: TEasyPaintInfoTaskBandColumn; reintroduce; virtual; function GetPaintInfoGroup: TEasyPaintInfoTaskbandGroup; reintroduce; virtual; function GetPaintInfoItem: TEasyPaintInfoTaskBandItem; reintroduce; virtual; function GroupTestExpand(HitInfo: TEasyGroupHitTestInfoSet): Boolean; override; procedure DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); override; procedure DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); override; procedure DoItemCustomView(Item: TEasyItem; ViewStyle: TEasyListStyle; var View: TEasyViewItemClass); override; procedure SetPaintInfoColumn(const Value: TEasyPaintInfoTaskBandColumn); reintroduce; virtual; procedure SetPaintInfoGroup(const Value: TEasyPaintInfoTaskbandGroup); reintroduce; virtual; procedure SetPaintInfoItem(const Value: TEasyPaintInfoTaskBandItem); reintroduce; virtual; property PaintInfoColumn: TEasyPaintInfoTaskBandColumn read GetPaintInfoColumn write SetPaintInfoColumn; public constructor Create(AOwner: TComponent); override; end; TEasyTaskPanelBand = class(TEasyBaseTaskBand) private FAutoScrollPanels: Boolean; FOnGetTaskPanel: TEasyGetTaskPanelEvent; function GetGroups: TEasyGroupsTaskPanel; procedure SetGroups(const Value: TEasyGroupsTaskPanel); protected function CreateGroups: TEasyGroups; override; procedure CMMouseWheel(var Msg: TCMMouseWheel); message CM_MOUSEWHEEL; procedure DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); override; procedure DoGetTaskPanel(Sender: TEasyGroupTaskPanel; var TaskPanel: TEasyTaskPanelFormClass); virtual; procedure DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); override; procedure DoGroupExpand(Group: TEasyGroup); override; procedure PositionPanels; procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL; procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL; procedure WMWindowPosChanging(var Msg: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING; public constructor Create(AOwner: TComponent); override; published property Align; property Anchors; property AutoScrollPanels: Boolean read FAutoScrollPanels write FAutoScrollPanels default False; property BackGround; property BevelInner; property BevelOuter; property BevelWidth; property BiDiMode; property BorderWidth; property Color; property Constraints; property Ctl3D; property OnGetTaskPanel: TEasyGetTaskPanelEvent read FOnGetTaskPanel write FOnGetTaskPanel; property UseDockManager default True; property Font; property GroupFont; property Groups: TEasyGroupsTaskPanel read GetGroups write SetGroups; property HintAlignment; property HintType; property HotTrack; property IncrementalSearch; property ImagesGroup; property ImagesSmall; property PaintInfoGroup; property ParentBiDiMode; {$IFDEF COMPILER_7_UP}property ParentBackground;{$ENDIF} property ParentColor; property ParentCtl3D; property ParentFont; property ParentShowHint; property PopupMenu; property ShowThemedBorder; property ShowHint; property Selection; property Sort; property TabOrder; property TabStop; property Themed; property Visible; property WheelMouseDefaultScroll; property WheelMouseScrollModifierEnabled; property OnCanResize; property OnClick; property OnConstrainedResize; {$IFDEF COMPILER_5_UP} property OnContextPopup; {$ENDIF} property OnAutoSortGroupCreate; property OnDblClick; property OnDragDrop; property OnDragOver; property OnDockDrop; property OnDockOver; property OnEndDock; property OnEndDrag; property OnEndUpdate; property OnEnter; property OnExit; property OnGetSiteInfo; property OnGroupClick; property OnGroupCollapse; property OnGroupCollapsing; property OnGroupContextMenu; property OnGroupCustomView; property OnGroupDblClick; property OnGroupExpand; property OnGroupExpanding; property OnGroupFreeing; property OnGroupGetCaption; property OnGroupGetImageIndex; property OnGroupGetImageList; property OnGroupImageDraw; property OnGroupImageGetSize; property OnGroupImageDrawIsCustom; property OnGroupInitialize; property OnGroupPaintText; property OnGroupHotTrack; property OnGroupSetCaption; property OnGroupSetImageIndex; property OnGroupVisibilityChanged; property OnGroupVisibilityChanging; property OnHintCustomInfo; property OnHintCustomDraw; property OnHintPauseTime; property OnHintPopup; property OnKeyAction; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; property OnPaintBkGnd; property OnResize; property OnStartDock; property OnStartDrag; property OnUnDock; end; TEasyTaskBand = class(TEasyBaseTaskBand) protected procedure DoGroupCollapse(Group: TEasyGroup); override; procedure DoGroupExpand(Group: TEasyGroup); override; public property GlobalImages; property Items; property States; property Scrollbars; published property Align; property Anchors; property BevelInner; property BevelOuter; property BevelWidth; property BiDiMode; property BorderWidth; property CellSizes; property Color; property Constraints; property Ctl3D; property EditManager; property UseDockManager default True; property DragKind; property DragManager; property Font; property GroupFont; property Groups; property HintAlignment; property HintType; property HotTrack; property IncrementalSearch; property ImagesGroup; property ImagesSmall; property PaintInfoGroup: TEasyPaintInfoTaskbandGroup read GetPaintInfoGroup write SetPaintInfoGroup; property PaintInfoItem: TEasyPaintInfoTaskBandItem read GetPaintInfoItem write SetPaintInfoItem; property ParentBiDiMode; {$IFDEF COMPILER_7_UP}property ParentBackground;{$ENDIF} property ParentColor; property ParentCtl3D; property ParentFont; property ParentShowHint; property PopupMenu; property PopupMenuHeader; property ShowGroupMargins; property ShowThemedBorder; property ShowHint; property Selection; property Sort; property TabOrder; property TabStop; property Themed; property Visible; property WheelMouseDefaultScroll; property WheelMouseScrollModifierEnabled; property OnCanResize; property OnClick; property OnConstrainedResize; {$IFDEF COMPILER_5_UP} property OnContextPopup; {$ENDIF} property OnAutoSortGroupCreate; property OnDblClick; property OnDragDrop; property OnDragOver; property OnDockDrop; property OnDockOver; property OnEndDock; property OnEndDrag; property OnEndUpdate; property OnEnter; property OnExit; property OnGetDragImage; property OnGetSiteInfo; property OnGroupClick; property OnGroupCollapse; property OnGroupCollapsing; property OnGroupCompare; property OnGroupContextMenu; property OnGroupDblClick; property OnGroupExpand; property OnGroupExpanding; property OnGroupFreeing; property OnGroupGetCaption; property OnGroupGetImageIndex; property OnGroupGetImageList; property OnGroupImageDraw; property OnGroupImageGetSize; property OnGroupImageDrawIsCustom; property OnGroupInitialize; property OnGroupPaintText; property OnGroupHotTrack; property OnGroupSetCaption; property OnGroupSetImageIndex; property OnGroupSetDetail; property OnGroupVisibilityChanged; property OnGroupVisibilityChanging; property OnHeaderDblClick; property OnHeaderMouseDown; property OnHeaderMouseMove; property OnHeaderMouseUp; property OnHintCustomInfo; property OnHintCustomDraw; property OnHintPauseTime; property OnHintPopup; property OnIncrementalSearch; property OnItemCheckChange; property OnItemCheckChanging; property OnItemClick; property OnItemCompare; property OnItemContextMenu; property OnItemCreateEditor; property OnItemDblClick; property OnItemEditBegin; property OnItemEdited; property OnItemEditEnd; property OnItemEnableChange; property OnItemEnableChanging; property OnItemFreeing; property OnItemFocusChanged; property OnItemFocusChanging; property OnItemGetCaption; property OnItemGetGroupKey; property OnItemGetImageIndex; property OnItemGetImageList; property OnItemHotTrack; property OnItemImageDraw; property OnItemImageGetSize; property OnItemImageDrawIsCustom; property OnItemInitialize; property OnItemMouseDown; property OnItemPaintText; property OnItemSelectionChanged; property OnItemSelectionChanging; property OnItemSetCaption; property OnItemSetGroupKey; property OnItemSetImageIndex; property OnItemVisibilityChanged; property OnItemVisibilityChanging; property OnKeyAction; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; property OnOLEDragEnd; property OnOLEDragStart; property OnOLEDragEnter; property OnOLEDragOver; property OnOLEDragLeave; property OnOLEDragDrop; property OnOLEGetCustomFormats; property OnOLEGetData; property OnOLEQueryContineDrag; property OnOLEGiveFeedback; property OnOLEQueryData; property OnPaintBkGnd; property OnResize; property OnStartDock; property OnStartDrag; property OnUnDock; end; const EASYLISTSTYLETEXTS: array[TEasyListStyle] of string = ('Icon', 'Small Icon', 'List', 'Details', 'Thumbnail', 'Tile', 'FilmStrip', 'Grid'); EASYSORTALGORITHMS: array[TEasySortAlgorithm] of string = ('QuickSort', 'BubbleSort', 'MergeSort'); HEADERSUPPORTEDVIEWS = [elsReport, elsGrid]; VERTICALVIEWS = [elsIcon, elsSmallIcon, elsReport, elsThumbnail, elsTile, elsGrid]; THUMBNAILVIEWS = [elsThumbnail, elsFilmStrip]; MULTILINEVIEWS = [elsIcon, elsThumbnail, elsFilmStrip, elsTile]; procedure FillStringsWithEasyListStyles(Strings: TStrings); procedure FillStringsWithEasySortAlgorithms(Strings: TStrings); var AlphaBlender: TEasyAlphaBlender; implementation uses Math; const PERSISTENTOBJECTSTATES = [esosSelected, esosEnabled, esosVisible, esosChecked, esosBold]; // States that are stored to a stream for persistance H_STRINGEDITORMARGIN = 12; // Margin for String Editors in the Horz direction V_STRINGEDITORMARGIN = 2; // Margin for String Editors in the Vert direction var HeaderClipboardFormat: TClipFormat; type TWinControlHack = class(TWinControl); type PHeaderClipData = ^THeaderClipData; THeaderClipData = record Thread: THandle; Listview: TCustomEasyListview; Column: TEasyColumn; end; const MaxPixelCount = 65536; type TRGBArray = array[0..MaxPixelCount-1] OF TRGBQuad; pRGBArray = ^TRGBArray; // Very simple implementation for saving/loading the tree to disk with a Unicode // filename in NT. Use TnT Uniocode package for a full blown implementation TWideFileStream = class(THandleStream) public constructor Create(const FileName: WideString; Mode: Word); destructor Destroy; override; end; TWinControlCracker = class(TWinControl) end; function WeightPixels (const pixelA, pixelB, pixelWeightA, pixelWeightB: Cardinal): Byte; begin Result := Byte((pixelWeightA*pixelA + pixelWeightB*pixelB) DIV (pixelWeightA + pixelWeightB)) end {WeightPixels}; procedure BlendBits(Bits1, Bits2: TBitmap; WeightA, WeightB: Integer; BlurBits2: Boolean); var y, x: Integer; RowA, RowB, TargetRow, PrevRow, NextRow: pRGBArray; RGBArrayA, RGBArrayB, PrevRGBArrayB, NextRGBArrayB, PrevRowRGBArrayB, NextRowRGBArrayB: TRGBQuad; begin if (Bits1.Height > 0) and (Bits1.Width = Bits2.Width) and (Bits1.Height = Bits2.Height) then begin PrevRow := nil; for y := 0 to Bits1.Height - 1 do begin RowA := Bits1.ScanLine[y]; RowB := Bits2.ScanLine[y]; TargetRow := Bits2.ScanLine[y]; if y + 1 < Bits1.Height then NextRow := Bits2.ScanLine[y+1] else NextRow := nil; for x := 0 to Bits1.Width - 1 do begin RGBArrayA := RowA[x]; RGBArrayB := RowB[x]; if BlurBits2 and Assigned(NextRow) and Assigned(PrevRow) and (x > 0) and (x < Bits1.Width - 1) then begin PrevRGBArrayB := TargetRow[x-1]; NextRGBArrayB := TargetRow[x+1]; PrevRowRGBArrayB := PrevRow[x]; NextRowRGBArrayB := NextRow[x]; RGBArrayB.rgbBlue := ( PrevRow[x-1].rgbBlue + PrevRow[x+1].rgbBlue + NextRow[x-1].rgbBlue + NextRow[x+1].rgbBlue + PrevRowRGBArrayB.rgbBlue + NextRowRGBArrayB.rgbBlue + TargetRow[x].rgbBlue div 2+ PrevRGBArrayB.rgbBlue + NextRGBArrayB.rgbBlue) div 9; RGBArrayB.rgbGreen := (PrevRow[x-1].rgbGreen + PrevRow[x+1].rgbGreen + NextRow[x-1].rgbGreen + NextRow[x+1].rgbGreen + PrevRowRGBArrayB.rgbGreen + NextRowRGBArrayB.rgbGreen + TargetRow[x].rgbGreen div 2 + PrevRGBArrayB.rgbGreen + NextRGBArrayB.rgbGreen) div 9; RGBArrayB.rgbRed := ( PrevRow[x-1].rgbRed + PrevRow[x+1].rgbRed + NextRow[x-1].rgbRed + NextRow[x+1].rgbRed + PrevRowRGBArrayB.rgbRed + NextRowRGBArrayB.rgbRed + TargetRow[x].rgbRed div 2 + PrevRGBArrayB.rgbRed + NextRGBArrayB.rgbRed) div 9; end; RGBArrayB.rgbBlue := WeightPixels(RGBArrayA.rgbBlue, RGBArrayB.rgbBlue, WeightA, WeightB); RGBArrayB.rgbGreen := WeightPixels(RGBArrayA.rgbGreen, RGBArrayB.rgbGreen, WeightA, WeightB); RGBArrayB.rgbRed := WeightPixels(RGBArrayA.rgbRed, RGBArrayB.rgbRed, WeightA, WeightB); RowB[x] := RGBArrayB; end; PrevRow := TargetRow; end; end; end; function HeaderClipFormat: TFormatEtc; begin Result.cfFormat := HeaderClipboardFormat; Result.ptd := nil; Result.lindex := -1; Result.dwAspect := -1; Result.ptd := nil; Result.tymed := TYMED_HGLOBAL end; function DefaultSort(Column: TEasyColumn; Item1, Item2: TEasyCollectionItem): Integer; var Index: Integer; begin if not Assigned(Column) then Index := 0 else Index := Column.Position; Result := WideStrIComp(PWideChar(Item1.Captions[Index]), PWideChar( Item2.Captions[Index])); if Assigned(Column) and (Column.SortDirection = esdDescending) then Result := -Result end; procedure FillStringsWithEasyListStyles(Strings: TStrings); var ListStyle: TEasyListStyle; begin Strings.Clear; for ListStyle := low(TEasyListStyle) to high(TEasyListStyle) do Strings.Add(EASYLISTSTYLETEXTS[ListStyle]); end; procedure FillStringsWithEasySortAlgorithms(Strings: TStrings); var ListStyle: TEasySortAlgorithm; begin Strings.Clear; for ListStyle := low(TEasySortAlgorithm) to high(TEasySortAlgorithm) do Strings.Add(EASYSORTALGORITHMS[ListStyle]); end; function WideFileCreate(const FileName: WideString): Integer; begin if Win32Platform = VER_PLATFORM_WIN32_NT then Result := Integer(CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)) else Result := Integer(CreateFileA(PAnsiChar(AnsiString(PWideChar(FileName))), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)); end; function WideFileOpen(const FileName: WideString; Mode: LongWord): Integer; const AccessMode: array[0..2] of LongWord = ( GENERIC_READ, GENERIC_WRITE, GENERIC_READ or GENERIC_WRITE); ShareMode: array[0..4] of LongWord = ( 0, 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE); begin if Win32Platform = VER_PLATFORM_WIN32_NT then Result := Integer(CreateFileW(PWideChar(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) else Result := Integer(CreateFileA(PAnsiChar(AnsiString(FileName)), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)); end; { TWideFileStream } constructor TWideFileStream.Create(const FileName: WideString; Mode: Word); var CreateHandle: Integer; begin if Mode = fmCreate then begin CreateHandle := WideFileCreate(FileName); if CreateHandle < 0 then {$IFNDEF COMPILER_5_UP} raise EFCreateError.Create('Can not create file: ' + FileName); {$ELSE} raise EFCreateError.CreateResFmt(PResStringRec(@SFCreateError), [FileName]); {$ENDIF COMPILER_5_UP} end else begin CreateHandle := WideFileOpen(FileName, Mode); if CreateHandle < 0 then {$IFNDEF COMPILER_5_UP} raise EFCreateError.Create('Can not create file: ' + FileName); {$ELSE} raise EFCreateError.CreateResFmt(PResStringRec(@SFCreateError), [FileName]); {$ENDIF COMPILER_5_UP} end; inherited Create(CreateHandle); end; destructor TWideFileStream.Destroy; begin if Handle >= 0 then FileClose(Handle); inherited Destroy; end; { TEasyGroupItemOwnedPersistent } constructor TEasyOwnedPersistentGroupItem.Create(AnOwner: TEasyGroup); begin inherited Create(AnOwner.OwnerListview); FOwnerGroup := AnOwner end; { TEasyOwnedPersistent} constructor TEasyOwnedPersistent.Create(AnOwner: TCustomEasyListview); begin inherited Create; FOwnerListview := AnOwner; end; function TEasyOwnedPersistent.GetOwner: TPersistent; begin Result := FOwnerListview; end; procedure TEasyOwnedPersistent.LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin end; procedure TEasyOwnedPersistent.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin end; { TEasyInterfacedPersistent } function TEasyInterfacedPersistent.GetObj: TObject; begin Result := Self end; function TEasyInterfacedPersistent._AddRef: Integer; begin Result := InterlockedIncrement(FRefCount); end; function TEasyInterfacedPersistent._Release: Integer; begin Result := InterlockedDecrement(FRefCount); if (Result = 0) then Destroy; end; function TEasyInterfacedPersistent.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE end; procedure TEasyInterfacedPersistent.AfterConstruction; begin // Release the constructor's implicit refcount InterlockedDecrement(FRefCount); end; procedure TEasyInterfacedPersistent.BeforeDestruction; begin end; class function TEasyInterfacedPersistent.NewInstance: TObject; begin // Set an implicit refcount so that refcounting // during construction won't destroy the object. Result := inherited NewInstance; TEasyInterfacedPersistent(Result).FRefCount := 1; end; { TEasyOwnedInterfacedPersistent } constructor TEasyOwnedInterfacedPersistent.Create(AnOwner: TCustomEasyListview); begin inherited Create; FOwner := AnOwner; end; { TEasyMargins } constructor TEasyMargin.Create(AnOwner: TCustomEasyListview); begin inherited; FSize := 30; end; destructor TEasyMargin.Destroy; begin inherited Destroy; end; function TEasyMargin.RuntimeSize: Integer; begin if not Visible or not FOwnerListview.ShowGroupMargins then Result := 0 else Result := FSize end; procedure TEasyMargin.Assign(Source: TPersistent); var Temp: TEasyMargin; begin if Source is TEasyMargin then begin Temp := TEasyMargin(Source); FSize := Temp.Size; FVisible := Temp.Visible end end; procedure TEasyMargin.SetSize(Value: Integer); begin if Value <> FSize then begin if Value < 0 then FSize := 0 else FSize := Value; OwnerListview.Groups.Rebuild end end; procedure TEasyMargin.SetVisible(Value: Boolean); begin if Value <> FVisible then begin FVisible := Value; OwnerListview.Groups.Rebuild end end; { TEasyHeaderMargin } constructor TEasyHeaderMargin.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FVisible := True; end; function TEasyItems.Add(Data: TObject = nil): TEasyItem; begin Result := TEasyItem( inherited Add(Data)) end; function TEasyItems.AddCustom(CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; begin Result := nil; if Assigned(CustomItem) then begin Result := CustomItem.Create(Self); FList.Add(Result); ReIndexItems; DoItemAdd(Result, FList.Count - 1); Result.Data := Data; DoStructureChange end end; function TEasyItems.AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; begin Result := nil; if Assigned(DataInf) then begin Result := TEasyItemInterfaced.Create(Self); FList.Add(Result); ReIndexItems; DoItemAdd(Result, FList.Count - 1); Result.DataInf := DataInf; Result.Data := Data; DoStructureChange end end; function TEasyItems.AddVirtual(Data: TObject = nil): TEasyItemVirtual; begin Result := TEasyItemVirtual.Create(Self); FList.Add(Result); ReIndexItems; DoItemAdd(Result, FList.Count - 1); Result.Data := Data; DoStructureChange end; constructor TEasyItems.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner); FOwnerGroup := AnOwnerGroup; FItemClass := TEasyItemStored; end; function TEasyItems.InsertCustom(Index: Integer; CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; begin Result := CustomItem.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end; function TEasyItems.InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; begin Result := nil; if Assigned(DataInf) then begin Result := TEasyItemInterfaced.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.DataInf := DataInf; Result.Data := Data; DoStructureChange end end; function TEasyItems.InsertVirtual(Index: Integer; Data: TObject = nil): TEasyItemVirtual; begin Result := TEasyItemVirtual.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end; procedure TEasyItems.Clear(FreeItems: Boolean = True); begin OwnerListview.Selection.IncMultiChangeCount; OwnerListview.Selection.GroupSelectBeginUpdate; inherited Clear(FreeItems); OwnerListview.Selection.GroupSelectEndUpdate; OwnerListview.Selection.DecMultiChangeCount; end; procedure TEasyItems.Delete(Index: Integer); var Temp: TEasyItem; begin // Find the next or prev visible item Temp := nil; if not (csDestroying in OwnerListview.ComponentState) and Items[Index].Focused then begin Temp := OwnerGroup.OwnerGroups.NextVisibleItem(Items[Index]); if not Assigned(Temp) then Temp := OwnerGroup.OwnerGroups.PrevVisibleItem(Items[Index]); end; // Delete the item, it will also unfocus the item inherited; // Focus the next or prev visible item if Assigned(Temp) then Temp.Focused := True; end; destructor TEasyItems.Destroy; begin inherited; end; procedure TEasyItems.DoStructureChange; begin OwnerListview.IncrementalSearch.ResetSearch; OwnerListview.Groups.Rebuild(False); if OwnerListview.Sort.AutoSort then OwnerListview.Sort.SortAll; OwnerListview.DoItemStructureChange; end; procedure TEasyItems.Exchange(Index1, Index2: Integer); begin inherited; end; function TEasyItems.GetItem(Index: Integer): TEasyItem; begin // This is a bottle neck for large data sets. Do this direct instead of inherited Result := ( FList.List[Index]) end; function TEasyItems.Insert(Index: Integer; Data: TObject = nil): TEasyItem; begin Result := TEasyItem( inherited Insert(Index)); end; procedure TEasyItems.SetItem(Index: Integer; Value: TEasyItem); begin inherited Items[Index] := Value end; { TEasyGlobalItems} function TEasyGlobalItems.Add(Data: TObject = nil): TEasyItem; begin EnsureFirstGroup; Result := TEasyItem(GetLastGroup.Items.Add(Data)); end; function TEasyGlobalItems.AddCustom(CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; begin EnsureFirstGroup; Result := GetLastGroup.Items.AddCustom(CustomItem, Data); end; function TEasyGlobalItems.AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; begin EnsureFirstGroup; Result := GetLastGroup.Items.AddInterfaced(DataInf, Data); end; function TEasyGlobalItems.AddVirtual(Data: TObject = nil): TEasyItemVirtual; begin EnsureFirstGroup; Result := GetLastGroup.Items.AddVirtual(Data); end; procedure TEasyGlobalItems.Clear; begin FOwner.Groups.Clear; end; constructor TEasyGlobalItems.Create(AnOwner: TCustomEasyListview); begin inherited Create; FOwner := AnOwner; end; procedure TEasyGlobalItems.Delete(Index: Integer; ReIndex: Boolean = True); var Item: TEasyItem; begin // OwnerListview.Groups.Delete(Index); Item := Items[Index]; Item.OwnerGroup.Items.Delete(Item.Index); // OwnerListview.Groups.ReIndexItems(nil, ReIndex); end; procedure TEasyGlobalItems.EnsureFirstGroup; begin if FOwner.Groups.Count = 0 then FOwner.Groups.Add.Caption := DEFAULT_GROUP_NAME; end; procedure TEasyGlobalItems.Exchange(Index1, Index2: Integer); var Item1, Item2: TEasyItem; begin Item1 := Items[Index1]; Item2 := Items[Index2]; if Item1.OwnerItems = Item2.OwnerItems then Item1.OwnerItems.Exchange(Item1.Index, Item2.Index) else raise Exception.Create('exchange of items between different groups is not yet supported'); // TODO end; function TEasyGlobalItems.GetCount: Integer; var i: Integer; begin Result := 0; for i := FOwner.Groups.Count - 1 downto 0 do Inc(Result, FOwner.Groups[i].Items.Count); end; function TEasyGlobalItems.GetItem(Index: Integer): TEasyItem; begin Result := GetItemInternal(Index); if Result = nil then // index too big IndexError(Index); end; function TEasyGlobalItems.GetItemInternal(Index: Integer): TEasyItem; var i: Integer; ItemCount: Integer; begin // GetItemInternal translates an absolute index into an item. It simply // returns nil if the index is too big but raises an exception for negative // indexes. if Index < 0 then IndexError(Index); Result := nil; for i := 0 to FOwner.Groups.Count - 1 do begin ItemCount := FOwner.Groups[i].Items.Count; if Index < ItemCount then begin Result := FOwner.Groups[i].Items[Index]; break; end; Dec(Index, ItemCount); end; end; function TEasyGlobalItems.GetLastGroup: TEasyGroup; begin if FOwner.Groups.Count > 0 then Result := FOwner.Groups[FOwner.Groups.Count - 1] else Result := nil; end; procedure TEasyGlobalItems.IndexError(Index: Integer); begin {$IFDEF COMPILER_5_UP} TList.Error(SListIndexError, Index); {$ELSE} TList.Error('List index out of bounds (%d)', Index); {$ENDIF} end; function TEasyGlobalItems.IndexOf(Item: TEasyItem): Integer; var GroupIndex: Integer; begin Result := Item.Index; for GroupIndex := Item.OwnerGroup.Index - 1 downto 0 do Inc(Result, OwnerListview.Groups[GroupIndex].Items.Count); end; function TEasyGlobalItems.Insert(Index: Integer; Data: TObject = nil): TEasyItem; var Item: TEasyItem; begin Item := GetItemInternal(Index); if Item = nil then Result := Add else Result := Item.OwnerItems.Insert(Item.Index, Data); end; function TEasyGlobalItems.InsertCustom(Index: Integer; CustomItem: TEasyItemClass; Data: TObject = nil): TEasyItem; var Item: TEasyItem; begin Item := GetItemInternal(Index); if Item = nil then Result := AddCustom(CustomItem, Data) else Result := Item.OwnerItems.InsertCustom(Item.Index, CustomItem, Data); end; function TEasyGlobalItems.InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyItemInterfaced; var Item: TEasyItem; begin Item := GetItemInternal(Index); if Item = nil then Result := AddInterfaced(DataInf, Data) else Result := Item.OwnerItems.InsertInterfaced(Item.Index, DataInf, Data); end; function TEasyGlobalItems.InsertVirtual(Index: Integer; Data: TObject = nil): TEasyItemVirtual; var Item: TEasyItem; begin Item := GetItemInternal(Index); if Item = nil then Result := AddVirtual else Result := Item.OwnerItems.InsertVirtual(Item.Index, Data); end; procedure TEasyGlobalItems.SetItem(Index: Integer; const Value: TEasyItem); var Item: TEasyItem; begin Item := Items[Index]; Item.OwnerItems[Item.Index] := Value; end; procedure TEasyGlobalItems.SetReIndexDisable(const Value: Boolean); begin EnsureFirstGroup; FOwner.Groups.ReIndexDisable := Value; end; { TEasyGroups } constructor TEasyGroups.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FItemClass := TEasyGroupStored; FStreamGroups := True end; destructor TEasyGroups.Destroy; begin inherited Destroy; end; function TEasyGroups.Add(Data: TObject = nil): TEasyGroup; begin Result := TEasyGroup( inherited Add(Data)); end; function TEasyGroups.AddCustom(CustomGroup: TEasyGroupClass; Data: TObject = nil): TEasyGroup; begin Result := nil; if Assigned(CustomGroup) then begin Result := CustomGroup.Create(Self); FList.Add(Result); ReIndexItems; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end end; function TEasyGroups.AddInterfaced(const DataInf: IUnknown; Data: TObject = nil): TEasyGroupInterfaced; begin Result := nil; if Assigned(DataInf) then begin Result := TEasyGroupInterfaced.Create(Self); FList.Add(Result); ReIndexItems; Result.DataInf := DataInf; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end end; function TEasyGroups.AddVirtual(Data: TObject = nil): TEasyGroupVirtual; begin Result := TEasyGroupVirtual.Create(Self); FList.Add(Result); ReIndexItems; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end; function TEasyGroups.AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; begin Result := nil; if Assigned(Item) then Result := Item.OwnerGroup.Grid.AdjacentItem(Item, Direction); end; function TEasyGroups.CanMoveDown: Boolean; begin Result := not OwnerListview.Sort.AutoSort and (Count > 0) and ((LastItem.Index < OwnerListview.Items.Count - 1) or (LastItem.Index - FirstItem.Index > Count - 1)); end; function TEasyGroups.CanMoveUp: Boolean; begin Result := not OwnerListview.Sort.AutoSort and (Count > 0) and ((FirstItem.Index > 0) or (LastItem.Index - FirstItem.Index > Count - 1)); end; function TEasyGroups.FirstGroup: TEasyGroup; begin Result := FirstGroupInternal(False) end; function TEasyGroups.FirstGroupInRect(ViewportRect: TRect): TEasyGroup; // // Find the first group in the passed rectangle. It implicitly assumes // Visible Groups // var i: Integer; R: TRect; begin Result := nil; i := 0; while (i < Count) and not Assigned(Result) do begin if Groups[i].Visible then if IntersectRect(R, Groups[i].DisplayRect, ViewportRect) then Result := Groups[i]; Inc(i) end end; function TEasyGroups.FirstGroupInternal(VisibleOnly: Boolean): TEasyGroup; var GroupIndex: Integer; begin Result := nil; GroupIndex := 0; if Count > 0 then begin while not Assigned(Result) and (GroupIndex < Count) do begin if VisibleOnly then begin if Groups[GroupIndex].Visible then Result := Groups[GroupIndex] end else Result := Groups[GroupIndex]; Inc(GroupIndex) end; end end; function TEasyGroups.FirstInGroup(Group: TEasyGroup): TEasyItem; begin Result := FirstInGroupInternal(Group, False) end; function TEasyGroups.FirstInGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean): TEasyItem; var ItemIndex: Integer; begin Result := nil; ItemIndex := 0; if Assigned(Group) then begin if Assigned(Group.Items) then begin if Group.Items.Count > 0 then begin if VisibleOnly then begin while not Assigned(Result) and (ItemIndex < Group.Items.Count) do begin if Group.Items[ItemIndex].Visible then Result := Group.Items[ItemIndex]; Inc(ItemIndex) end end else Result := Group.Items[ItemIndex] end end end end; function TEasyGroups.FirstInitializedItem: TEasyItem; begin Result := FirstItemInternal(enitInitialized) end; function TEasyGroups.FirstItem: TEasyItem; begin Result := FirstItemInternal(enitAny) end; function TEasyGroups.FirstItemInRect(ViewportRect: TRect): TEasyItem; // // Find the first Item in the passed rectangle. It implicitly assumes // Visible Items // var Group: TEasyGroup; i: Integer; R, FullDisplayRect: TRect; begin Result := nil; i := 0; if OwnerListview.View = elsReport then begin Group := FirstGroupInRect(ViewportRect); while not Assigned(Result) and Assigned(Group) do begin if (Group.Items.Count > 0) and Group.Expanded then begin while not Assigned(Result) and (i < Group.Items.Count) do begin FullDisplayRect := OwnerListview.Header.ViewRect; FullDisplayRect.Top := Group.Items[i].DisplayRect.Top; FullDisplayRect.Bottom := Group.Items[i].DisplayRect.Bottom; if Group.Items[i].Visible and IntersectRect(R, FullDisplayRect, ViewportRect) then Result := Group.Items[i] else Inc(i) end end; i := 0; Group := NextGroupInRect(Group, ViewportRect); end end else begin Group := FirstGroupInRect(ViewportRect); while not Assigned(Result) and Assigned(Group) do begin if (Group.Items.Count > 0) and Group.Expanded then begin while not Assigned(Result) and (i < Group.Items.Count) do begin if Group.Items[i].Visible and IntersectRect(R, Group.Items[i].DisplayRect, ViewportRect) then Result := Group.Items[i] else Inc(i) end end; i := 0; Group := NextGroupInRect(Group, ViewportRect); end end end; function TEasyGroups.FirstItemInternal(NextItemType: TEasyNextItemType): TEasyItem; var GroupIndex, ItemIndex: Integer; begin Result := nil; GroupIndex := 0; ItemIndex := 0; if Count > 0 then begin while not Assigned(Result) and (GroupIndex < Count) do begin if Assigned(Groups[GroupIndex].Items) then begin if Groups[GroupIndex].Items.Count > 0 then begin case NextItemType of enitVisible: begin while not Assigned(Result) and (ItemIndex < Groups[GroupIndex].Items.Count) do begin if Groups[GroupIndex].Items[ItemIndex].Visible then Result := Groups[GroupIndex].Items[ItemIndex]; Inc(ItemIndex) end end; enitInitialized: begin while not Assigned(Result) and (ItemIndex < Groups[GroupIndex].Items.Count) do begin if Groups[GroupIndex].Items[ItemIndex].Initialized then Result := Groups[GroupIndex].Items[ItemIndex]; Inc(ItemIndex) end end; else Result := Groups[GroupIndex].Items[0]; end end; end; ItemIndex := 0; Inc(GroupIndex) end end end; function TEasyGroups.FirstVisibleGroup: TEasyGroup; begin Result := FirstGroupInternal(True) end; function TEasyGroups.FirstVisibleInGroup(Group: TEasyGroup): TEasyItem; begin Result := FirstInGroupInternal(Group, True) end; function TEasyGroups.FirstVisibleItem: TEasyItem; begin Result := FirstItemInternal(enitVisible) end; function TEasyGroups.GetCellHeight: Integer; begin if Count > 0 then Result := Groups[0].Grid.CellSize.Height else Result := 0 end; function TEasyGroups.GetCellWidth: Integer; begin if Count > 0 then Result := Groups[0].Grid.CellSize.Width else Result := 0 end; function TEasyGroups.GetGroup(Index: Integer): TEasyGroup; begin // Bottleneck, no inherited call Result := TEasyGroup( FList.List[Index]) end; function TEasyGroups.GetItemCount: Integer; var i: Integer; begin Result := 0; for i := 0 to FList.Count - 1 do Result := Result + TEasyGroup(FList[i]).ItemCount end; function TEasyGroups.GetViewRect: TRect; begin Result := Rect(0, 0, 0, 0); if LastVisibleGroup <> nil then Result.BottomRight := LastVisibleGroup.DisplayRect.BottomRight; end; function TEasyGroups.GetVisibleGroup(Index: Integer): TEasyGroup; begin Result := nil; if (Index > -1) and (Index < VisibleCount) then Result := TEasyGroup( VisibleList[Index]) end; function TEasyGroups.GroupByPoint(ViewportPoint: TPoint): TEasyGroup; var i: Integer; begin Result := nil; i := 0; while (i < Count) and not Assigned(Result) do begin if Groups[i].Visible and Groups[i].Enabled then if PtInRect(Groups[i].DisplayRect, ViewportPoint) then Result := Groups[i]; Inc(i) end end; function TEasyGroups.Insert(Index: Integer; Data: TObject = nil): TEasyGroup; begin Result := TEasyGroup( inherited Insert(Index, Data)) end; function TEasyGroups.InsertCustom(Index: Integer; CustomGroup: TEasyGroupClass; Data: TObject = nil): TEasyGroup; begin Result := nil; if Assigned(CustomGroup) then begin Result := CustomGroup.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end end; function TEasyGroups.InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject): TEasyGroupInterfaced; begin Result := nil; if Assigned(Data) then begin Result := TEasyGroupInterfaced.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.DataInf := DataInf; Result.Data := Data; DoStructureChange end end; function TEasyGroups.InsertVirtual(Index: Integer; Data: TObject = nil): TEasyGroupVirtual; begin Result := TEasyGroupVirtual.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end; function TEasyGroups.ItemByPoint(ViewportPoint: TPoint): TEasyItem; var Group: TEasyGroup; begin Result := nil; Group := GroupByPoint(ViewportPoint); if Assigned(Group) then Result := Group.ItemByPoint(ViewportPoint) end; function TEasyGroups.LastGroup: TEasyGroup; begin Result := LastGroupInternal(False) end; function TEasyGroups.LastGroupInternal(VisibleOnly: Boolean): TEasyGroup; var GroupIndex: Integer; begin Result := nil; if Count > 0 then begin if VisibleOnly then begin GroupIndex := Count - 1; while not Assigned(Result) and (GroupIndex > -1) do begin if Groups[GroupIndex].Visible then Result := Groups[GroupIndex] else Dec(GroupIndex) end end else Result := Groups[Count - 1] end end; function TEasyGroups.LastInGroup(Group: TEasyGroup): TEasyItem; begin Result := LastInGroupInternal(Group, False) end; function TEasyGroups.LastInGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean): TEasyItem; var ItemIndex: Integer; begin Result := nil; if Assigned(Group) then begin if Assigned(Group.Items) then begin ItemIndex := Group.Items.Count - 1; if VisibleOnly then begin while not Assigned(Result) and (ItemIndex > -1) do begin if Group.Items[ItemIndex].Visible then Result := Group.Items[ItemIndex] else Dec(ItemIndex) end end else Result := Group.Items[Group.Items.Count - 1] end end end; function TEasyGroups.LastInitializedItem: TEasyItem; begin Result := LastItemInternal(enitInitialized) end; function TEasyGroups.LastItem: TEasyItem; begin Result := LastItemInternal(enitAny) end; function TEasyGroups.LastItemInternal(NextItemType: TEasyNextItemType): TEasyItem; var ItemIndex, GroupIndex: Integer; begin Result := nil; if Count > 0 then begin GroupIndex := Count - 1; while not Assigned(Result) and (GroupIndex > -1) do begin if Assigned(Groups[GroupIndex].Items) then begin ItemIndex := Groups[GroupIndex].Items.Count - 1; while not Assigned(Result) and (ItemIndex > -1) do begin case NextItemType of enitVisible: begin if Groups[GroupIndex].Items[ItemIndex].Visible then Result := Groups[GroupIndex].Items[ItemIndex] else Dec(ItemIndex) end; enitInitialized: begin if Groups[GroupIndex].Items[ItemIndex].Visible then Result := Groups[GroupIndex].Items[ItemIndex] else Dec(ItemIndex) end else Result := Groups[GroupIndex].Items[ItemIndex] end end end; Dec(GroupIndex); end end end; function TEasyGroups.LastVisibleGroup: TEasyGroup; begin Result := LastGroupInternal(True) end; function TEasyGroups.LastVisibleInGroup(Group: TEasyGroup): TEasyItem; begin Result := LastInGroupInternal(Group, True) end; function TEasyGroups.LastVisibleItem: TEasyItem; begin Result := LastItemInternal(enitVisible) end; function TEasyGroups.MoveDown: Boolean; var AItem, ANextItem: TEasyItem; begin Result := CanMoveDown; if not Result then Exit; OwnerListview.BeginUpdate; try AItem := LastItem; while Assigned(AItem) do begin if AItem.Index < OwnerListview.Items.Count - 1 then begin ANextItem := OwnerListview.Items[AItem.Index + 1]; if not ANextItem.Selected then OwnerListview.Items.Exchange(AItem.Index, ANextItem.Index); end; AItem := PrevItem(AItem); end; finally OwnerListview.EndUpdate; end; LastItem.MakeVisible(emvAuto); OwnerListview.DoItemSelectionsChanged; end; function TEasyGroups.MoveUp: Boolean; var AItem, APrevItem: TEasyItem; begin Result := CanMoveUp; if not Result then Exit; OwnerListview.BeginUpdate; try AItem := FirstItem; while Assigned(AItem) do begin if AItem.Index > 0 then begin APrevItem := OwnerListview.Items[AItem.Index - 1]; if not APrevItem.Selected then OwnerListview.Items.Exchange(AItem.Index, APrevItem.Index); end; AItem := NextItem(AItem); end; finally OwnerListview.EndUpdate; end; FirstItem.MakeVisible(emvAuto); OwnerListview.DoItemSelectionsChanged; end; function TEasyGroups.NextEditableItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitEditable, esdForward) end; function TEasyGroups.NextGroup(Group: TEasyGroup): TEasyGroup; begin Result := NavigateGroupInternal(Group, False, esdForward) end; function TEasyGroups.NextGroupInRect(Group: TEasyGroup; ViewportRect: TRect): TEasyGroup; // // Find the next Groups in the passed rectangle. It implicitly assumes // Visible Groups // var i: Integer; ScratchR: TRect; Done: Boolean; begin Result := nil; Done := False; if Assigned(Group) then begin i := Group.Index + 1; while not Assigned(Result) and (i < Count) and not Done do begin if Groups[i].Visible then begin if IntersectRect(ScratchR, Groups[i].DisplayRect, ViewportRect) then Result := Groups[i] else Done := True end; Inc(i) end end end; function TEasyGroups.NavigateGroupInternal(Group: TEasyGroup; VisibleOnly: Boolean; Direction: TEasySearchDirection): TEasyGroup; var GroupIndex: Integer; begin Result := nil; GroupIndex := Group.Index; if Direction = esdForward then Inc(GroupIndex) else Dec(GroupIndex); while not Assigned(Result) and (GroupIndex < Count) and (GroupIndex > -1) do begin if VisibleOnly then begin if Groups[GroupIndex].Expanded and Groups[GroupIndex].Visible then Result := Groups[GroupIndex] else begin if Direction = esdForward then Inc(GroupIndex) else Dec(GroupIndex); end end else Result := Groups[GroupIndex] end end; function TEasyGroups.NextInitializedItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitInitialized, esdForward) end; function TEasyGroups.NextVisibleGroupWithVisibleItems(Group: TEasyGroup): TEasyGroup; // // Returns the next Visible Group that has at least one Visible Item // var Done: Boolean; begin Result := nil; if Assigned(Group) then begin Done := False; Result := Group; while not Done do begin Result := NavigateGroupInternal(Result, True, esdForward); if Assigned(Result) then Done := Result.VisibleCount > 0 else Done := True end end end; function TEasyGroups.NextInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; begin Result := NavigateInGroupInternal(Group, Item, False, esdForward) end; function TEasyGroups.NavigateInGroupInternal(Group: TEasyGroup; Item: TEasyItem; VisibleOnly: Boolean; Direction: TEasySearchDirection): TEasyItem; var ItemIndex: Integer; TempItem: TEasyItem; Count: Integer; begin Result := nil; if Assigned(Group) and Assigned(Item) then begin if Assigned(Group.Items) then begin ItemIndex := Item.FIndex; // Direct access for speed if Direction = esdForward then Inc(ItemIndex) else Dec(ItemIndex); Count := Group.Items.FList.Count; while not Assigned(Result) and (ItemIndex < Count) and (ItemIndex > -1) do begin // Direct Access for speed TempItem := Group.Items.FList.List[ItemIndex]; if VisibleOnly then begin // Direct access for speed if esosVisible in TempItem.State then Result := TempItem else begin if Direction = esdForward then Inc(ItemIndex) else Dec(ItemIndex) end end else Result := TempItem end end end end; function TEasyGroups.NextItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitAny, esdForward) end; function TEasyGroups.NextItemInRect(Item: TEasyItem; ViewportRect: TRect): TEasyItem; // // Find the next Item in the passed rectangle. It implicitly assumes // Visible Items // var Group: TEasyGroup; i: Integer; R, FullDisplayRect: TRect; Done: Boolean; begin Result := nil; Done := False; Group := Item.OwnerGroup; i := Item.Index + 1; if OwnerListview.View = elsReport then begin while not Assigned(Result) and Assigned(Group) and not Done do begin if (i < Group.Items.Count) and Group.Expanded and not Done then begin FullDisplayRect := OwnerListview.Header.ViewRect; FullDisplayRect.Top := Group.Items[i].DisplayRect.Top; FullDisplayRect.Bottom := Group.Items[i].DisplayRect.Bottom; if Group.Items[i].Visible then if IntersectRect(R, FullDisplayRect, ViewportRect) then Result := Group.Items[i] else Done := True else Inc(i) end else begin i := 0; Group := NextGroupInRect(Group, ViewportRect) end end end else begin while not Assigned(Result) and Assigned(Group) and not Done do begin if (i < Group.Items.Count) and Group.Expanded and not Done then begin if Group.Items[i].Visible then begin if IntersectRect(R, Group.Items[i].DisplayRect, ViewportRect) then Result := Group.Items[i] else begin if OwnerListview.IsVertView then Done := Group.Items[i].DisplayRect.Top > ViewportRect.Bottom else Done := Group.Items[i].DisplayRect.Left > ViewportRect.Right end end; Inc(i) end else begin i := 0; Group := NextGroupInRect(Group, ViewportRect) end end end end; function TEasyGroups.NavigateItemInternal(Item: TEasyItem; NextItemType: TEasyNextItemType; Direction: TEasySearchDirection): TEasyItem; var GroupIndex, ItemIndex, Column: Integer; Allow: Boolean; begin Result := nil; if Assigned(Item) then begin ItemIndex := Item.Index; GroupIndex := Item.OwnerGroup.Index; if Direction = esdForward then Inc(ItemIndex) else Dec(ItemIndex); while not Assigned(Result) and (GroupIndex < Count) and (GroupIndex > -1) do begin if Groups[GroupIndex].Expanded and Groups[GroupIndex].Enabled then begin while not Assigned(Result) and (ItemIndex < Groups[GroupIndex].Items.Count) and (ItemIndex > -1) do begin if NextItemType in [enitVisible, enitEditable] then begin if Assigned(Groups[GroupIndex].Items) then begin if Groups[GroupIndex].Items[ItemIndex].Visible then begin Result := Groups[GroupIndex].Items[ItemIndex]; if NextItemType = enitEditable then begin Allow := True; OwnerListview.DoItemEditBegin(Result, Column, Allow); if not Allow then Result := nil; end end end; if Direction = esdForward then Inc(ItemIndex) else Dec(ItemIndex) end else if NextItemType = enitInitialized then begin if Assigned(Groups[GroupIndex].Items) then begin if Groups[GroupIndex].Items[ItemIndex].Initialized then Result := Groups[GroupIndex].Items[ItemIndex] end; if Direction = esdForward then Inc(ItemIndex) else Dec(ItemIndex) end else Result := Groups[GroupIndex].Items[ItemIndex]; end; if Direction = esdForward then begin Inc(GroupIndex); ItemIndex := 0 end else begin Dec(GroupIndex); if (GroupIndex > -1) and Assigned(Groups[GroupIndex].Items) then ItemIndex := Groups[GroupIndex].Items.Count - 1; end end else begin ItemIndex := 0; if Direction = esdForward then Inc(GroupIndex) else Dec(GroupIndex); end end end end; function TEasyGroups.NextVisibleGroup(Group: TEasyGroup): TEasyGroup; begin Result := NavigateGroupInternal(Group, True, esdForward) end; function TEasyGroups.NextVisibleInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; begin Result := NavigateInGroupInternal(Group, Item, True, esdForward) end; function TEasyGroups.NextVisibleItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitVisible, esdForward) end; function TEasyGroups.PrevEditableItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitEditable, esdBackward) end; function TEasyGroups.PrevGroup(Group: TEasyGroup): TEasyGroup; begin Result := NavigateGroupInternal(Group, False, esdBackward) end; function TEasyGroups.PrevInitializedItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitInitialized, esdBackward) end; function TEasyGroups.PrevVisibleGroupWithVisibleItems(Group: TEasyGroup): TEasyGroup; // // Returns the prev Visible Group that has at least one Visible Item // var Done: Boolean; begin Result := nil; if Assigned(Group) then begin Done := False; Result := Group; while not Done do begin Result := NavigateGroupInternal(Result, True, esdBackward); if Assigned(Result) then Done := Result.VisibleCount > 0 else Done := True end end end; function TEasyGroups.PrevInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; begin Result := NavigateInGroupInternal(Group, Item, False, esdBackward) end; function TEasyGroups.PrevItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitAny, esdBackward) end; function TEasyGroups.PrevVisibleGroup(Group: TEasyGroup): TEasyGroup; begin Result := NavigateGroupInternal(Group, True, esdBackward) end; function TEasyGroups.PrevVisibleInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; begin Result := NavigateInGroupInternal(Group, Item, True, esdBackward) end; function TEasyGroups.PrevVisibleItem(Item: TEasyItem): TEasyItem; begin Result := NavigateItemInternal(Item, enitVisible, esdBackward) end; procedure TEasyGroups.Clear(FreeItems: Boolean = True); begin if Assigned(OwnerListview.Selection) then begin OwnerListview.Selection.IncMultiChangeCount; OwnerListview.Selection.GroupSelectBeginUpdate; end; inherited Clear(FreeItems); if Assigned(OwnerListview.Selection) then begin OwnerListview.Selection.DecMultiChangeCount; OwnerListview.Selection.GroupSelectEndUpdate; end; end; procedure TEasyGroups.CollapseAll; var i: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to Count - 1 do Groups[i].Expanded := False finally OwnerListview.EndUpdate end end; procedure TEasyGroups.DeleteGroup(Group: TEasyGroup); var Done: Boolean; TestGroup: TEasyGroup; begin Done := False; TestGroup := FirstGroup; while Assigned(TestGroup) and not Done do begin Done := TestGroup = Group; if Done then Delete(Group.Index) else TestGroup := NextGroup(TestGroup) end end; procedure TEasyGroups.DeleteItem(Item: TEasyItem); var Done: Boolean; TestItem: TEasyItem; Group: TEasyGroup; begin Done := False; TestItem := FirstItem; while Assigned(TestItem) and not Done do begin Done := TestItem = Item; if Done then begin Group := TestItem.OwnerGroup; Group.Items.Delete(Item.Index); end else TestItem := NextItem(TestItem) end end; procedure TEasyGroups.DeleteItems(ItemArray: TEasyItemArray); // // Optimized method of deleting multiple items, the items can be in any group // var i: Integer; Temp: TEasyItem; begin OwnerListview.Selection.IncMultiChangeCount; OwnerListview.Selection.GroupSelectBeginUpdate; try for i := 0 to Length(ItemArray) - 1 do begin Temp := ItemArray[i].OwnerGroup.FItems[ItemArray[i].Index]; Temp.Focused := False; Temp.Selected := False; Temp.Visible := False; end; for i := 0 to Length(ItemArray) - 1 do begin Temp := ItemArray[i].OwnerGroup.FItems[ItemArray[i].Index]; ItemArray[i].OwnerGroup.FItems[ItemArray[i].Index] := nil; Temp.Free; end; for i := 0 to Count - 1 do begin TEasyGroup( List[i]).FItems.FList.Pack; TEasyGroup( List[i]).FItems.ReIndexItems end finally OwnerListview.Selection.GroupSelectEndUpdate; OwnerListview.Selection.DecMultiChangeCount end end; procedure TEasyGroups.DoStructureChange; begin inherited DoStructureChange; Rebuild(False) end; procedure TEasyGroups.ExpandAll; var i: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to Count - 1 do Groups[i].Expanded := True finally OwnerListview.EndUpdate end end; procedure TEasyGroups.InitializeAll; var i, j: Integer; begin for i := 0 to Count - 1 do begin if Assigned(Groups[i].Items) then begin for j := 0 to Groups[i].Items.Count - 1 do Groups[i][j].Initialized := True end end end; procedure TEasyGroups.InvalidateItem(Item: TEasyCollectionItem; ImmediateUpdate: Boolean); begin if Assigned(Item) then Item.Invalidate(ImmediateUpdate) end; {$IFDEF COMPILER_6_UP} {$ELSE} {$ENDIF COMPILER_6_UP} procedure TEasyGroups.LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited LoadFromStream(S, Version); if StreamGroups then ReadItems(S); end; procedure TEasyGroups.MakeAllVisible; var i, j: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to Count - 1 do begin Groups[i].Visible := True; for j := 0 to Groups[i].ItemCount - 1 do Groups[i].Item[j].Visible := True end finally OwnerListview.EndUpdate() end end; procedure TEasyGroups.Move(Item: TEasyItem; NewGroup: TEasyGroup); begin if Assigned(Item) and Assigned(NewGroup) then begin Item.OwnerGroup.Items.Delete(Item.Index); NewGroup.Items.Add(Item); Item.FCollection := NewGroup.Items; DoStructureChange; end end; procedure TEasyGroups.Rebuild(Force: Boolean = False); var i, VisibleGroupIndex, VisibleItemIndex: Integer; ViewRect: TRect; begin if ((OwnerListview.UpdateCount = 0) or Force) and not(csLoading in OwnerListview.ComponentState) and (OwnerListview.HandleAllocated) then begin Include(FGroupsState, egsRebuilding); try VisibleList.Clear; VisibleList.Capacity := Count; VisibleGroupIndex := 0; VisibleItemIndex := 0; OwnerListview.Header.Rebuild(Force); SetRect(ViewRect, 0, 0, 0, 0); for i := 0 to Count - 1 do begin if Groups[i].Visible then begin VisibleList.Add(Groups[i]); Groups[i].FVisibleIndex := VisibleGroupIndex; Inc(VisibleGroupIndex); end else Groups[i].FVisibleIndex := -1; if i > 0 then Groups[i].Rebuild(Groups[i-1], VisibleItemIndex) else Groups[i].Rebuild(nil, VisibleItemIndex); UnionRect(ViewRect, ViewRect, Groups[i].DisplayRect); ViewRect.Left := 0; ViewRect.Top := 0; Groups[i].Items.ReIndexItems end; if OwnerListview.Selection.GroupSelections then OwnerListview.Selection.BuildSelectionGroupings(False); OwnerListview.Scrollbars.SetViewRect(ViewRect, True); finally Exclude(FGroupsState, egsRebuilding); end end end; procedure TEasyGroups.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S, Version); if StreamGroups then WriteItems(S); end; procedure TEasyGroups.SetCellHeight(Value: Integer); var i: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to Count - 1 do Groups[i].Grid.CellSize.Height := Value finally OwnerListview.EndUpdate end end; procedure TEasyGroups.SetCellWidth(Value: Integer); var i: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to Count - 1 do Groups[i].Grid.CellSize.Width := Value finally OwnerListview.EndUpdate end end; procedure TEasyGroups.SetGroup(Index: Integer; Value: TEasyGroup); begin inherited Items[Index] := Value end; procedure TEasyGroups.UnInitializeAll; var i, j: Integer; begin for i := 0 to Count - 1 do begin if Assigned(Groups[i].Items) then begin for j := 0 to Groups[i].Items.Count - 1 do Groups[i][j].Initialized := False end end end; { TEasyColumns } constructor TEasyColumns.Create(AnOwner: TCustomEasyListview); begin inherited; FItemClass := TEasyColumnStored end; destructor TEasyColumns.Destroy; begin inherited; end; function TEasyColumns.Add(Data: TObject = nil): TEasyColumn; begin Result := TEasyColumn( inherited Add(Data)); Result.Color := OwnerListview.Header.Color; end; function TEasyColumns.AddCustom(CustomItem: TEasyColumnClass; Data: TObject = nil): TEasyColumn; begin Result := nil; if Assigned(CustomItem) then begin Result := CustomItem.Create(Self); FList.Add(Result); Result.Color := OwnerListview.Header.Color; ReIndexItems; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end end; function TEasyColumns.AddInterfaced(const DataInf: IUnknown; Data: TObject): TEasyColumnInterfaced; begin Result := nil; if Assigned(DataInf) then begin Result := TEasyColumnInterfaced.Create(Self); FList.Add(Result); Result.Color := OwnerListview.Header.Color; ReIndexItems; Result.DataInf := DataInf; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end end; function TEasyColumns.AddVirtual(Data: TObject = nil): TEasyColumnVirtual; begin Result := TEasyColumnVirtual.Create(Self); FList.Add(Result); Result.Color := OwnerListview.Header.Color; ReIndexItems; Result.Data := Data; DoItemAdd(Result, FList.Count - 1); DoStructureChange end; function TEasyColumns.ColumnByPoint(ViewportPoint: TPoint): TEasyColumn; var i: Integer; begin Result := nil; i := 0; // Careful with a binary search here are the rectangles increase with Header.Postions not the Columns property while not Assigned(Result) and (i < Count) do begin if PtInRect(Columns[i].DisplayRect, ViewportPoint) then Result := Columns[i] else Inc(i) end end; function TEasyColumns.GetColumns(Index: Integer): TEasyColumn; begin Result := TEasyColumn( FList.List[Index]) end; function TEasyColumns.GetOwnerHeader: TEasyHeader; begin Result := OwnerListview.Header end; function TEasyColumns.Insert(Index: Integer; Data: TObject = nil): TEasyColumn; begin Result := TEasyColumn( inherited Insert(Index, Data)) end; function TEasyColumns.InsertCustom(Index: Integer; CustomColumn: TEasyColumnClass; Data: TObject = nil): TEasyColumn; begin Result := nil; if Assigned(CustomColumn) then begin Result := CustomColumn.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end end; function TEasyColumns.InsertInterfaced(Index: Integer; const DataInf: IUnknown; Data: TObject = nil): TEasyColumnInterfaced; begin Result := nil; if Assigned(DataInf) then begin Result := TEasyColumnInterfaced.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.DataInf := DataInf; Result.Data := Data; DoStructureChange end end; function TEasyColumns.InsertVirtual(Index: Integer; Data: TObject = nil): TEasyColumnVirtual; begin Result := TEasyColumnVirtual.Create(Self); FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end; procedure TEasyColumns.Clear(FreeItems: Boolean = True); begin inherited Clear(FreeItems); if Assigned(OwnerHeader) and Assigned(OwnerHeader.Positions) then begin OwnerHeader.Positions.Clear; OwnerHeader.Columns.VisibleList.Clear; end end; procedure TEasyColumns.DoItemAdd(Item: TEasyCollectionItem; Index: Integer); begin inherited DoItemAdd(Item, Index); end; procedure TEasyColumns.DoStructureChange; begin inherited DoStructureChange; OwnerListview.Header.Rebuild(False) end; procedure TEasyColumns.SetColumns(Index: Integer; Value: TEasyColumn); begin inherited Items[Index] := Value end; { TEasyGlobalImageManager } constructor TEasyGlobalImageManager.Create(AnOwner: TCustomEasyListview); begin inherited; FGroupExpandButton := TBitmap.Create; FGroupCollapseButton := TBitmap.Create; FColumnSortUp := TBitmap.Create; FColumnSortDown := TBitmap.Create; end; destructor TEasyGlobalImageManager.Destroy; begin inherited; FreeAndNil(FGroupExpandButton); FreeAndNil(FGroupCollapseButton); FreeAndNil(FColumnSortUp); FreeAndNil(FColumnSortDown); end; function TEasyGlobalImageManager.GetColumnSortDown: TBitmap; begin if FColumnSortDown.Empty then begin MakeTransparent(FColumnSortDown, clFuchsia); FColumnSortDown.LoadFromResourceName(hInstance, BITMAP_SORTARROWDOWN); end; Result := FColumnSortDown end; function TEasyGlobalImageManager.GetColumnSortUp: TBitmap; begin if FColumnSortUp.Empty then begin MakeTransparent(FColumnSortUp, clFuchsia); FColumnSortUp.LoadFromResourceName(hInstance, BITMAP_SORTARROWUP); end; Result := FColumnSortUp end; function TEasyGlobalImageManager.GetGroupCollapseImage: TBitmap; begin if FGroupCollapseButton.Empty then begin MakeTransparent(FGroupCollapseButton, clFuchsia); FGroupCollapseButton.LoadFromResourceName(hInstance, BITMAP_DEFAULTGROUPCOLLAPSED); end; Result := FGroupCollapseButton end; function TEasyGlobalImageManager.GetGroupExpandImage: TBitmap; begin if FGroupExpandButton.Empty then begin MakeTransparent(FGroupExpandButton, clFuchsia); FGroupExpandButton.LoadFromResourceName(hInstance, BITMAP_DEFAULTGROUPEXPANDED); end; Result := FGroupExpandButton end; procedure TEasyGlobalImageManager.MakeTransparent(Bits: TBitmap; TransparentColor: TColor); begin Bits.Transparent := True; Bits.TransparentColor := TransparentColor end; procedure TEasyGlobalImageManager.SetColumnSortDown(Value: TBitmap); begin FColumnSortDown.Assign(Value) end; procedure TEasyGlobalImageManager.SetColumnSortUp(Value: TBitmap); begin FColumnSortUp.Assign(Value) end; procedure TEasyGlobalImageManager.SetGroupCollapseImage(const Value: TBitmap); begin FGroupExpandButton.Assign(Value); end; procedure TEasyGlobalImageManager.SetGroupExpandImage(const Value: TBitmap); begin GroupCollapseButton.Assign(Value); end; { TEasyGroup } constructor TEasyGroup.Create(ACollection: TEasyCollection); begin inherited; FExpanded := True; FItems := TEasyItems.Create(OwnerListview, Self); FVisibleItems := TList.Create; end; destructor TEasyGroup.Destroy; begin SetDestroyFlags; if OwnerListview.Selection.FocusedGroup = Self then OwnerListview.Selection.FocusedGroup := nil; Selected := False; Focused := False; FItems.Free; // don't nil the reference the items may need it as they are destroyed. inherited; FreeAndNil(FGrid); FreeAndNil(FVisibleItems); FreeAndNil(FView); end; function TEasyGroup.BoundsRectBottomMargin: TRect; begin if MarginBottom.Visible and OwnerListview.ShowGroupMargins then begin Result := DisplayRect; Result.Top := Result.Bottom - MarginBottom.RuntimeSize; Result.Right := Result.Right - MarginRight.RuntimeSize; Result.Left := Result.Left + MarginLeft.RuntimeSize; end else Result := Rect(0, 0, 0, 0); end; function TEasyGroup.BoundsRectLeftMargin: TRect; begin if MarginLeft.Visible and OwnerListview.ShowGroupMargins then begin Result := DisplayRect; Result.Right := Result.Left + MarginLeft.RuntimeSize end else Result := Rect(0, 0, 0, 0); end; function TEasyGroup.BoundsRectRightMargin: TRect; begin if MarginRight.Visible and OwnerListview.ShowGroupMargins then begin Result := DisplayRect; Result.Left := Result.Right - MarginRight.RuntimeSize end else Result := Rect(0, 0, 0, 0); end; function TEasyGroup.BoundsRectTopMargin: TRect; begin if MarginTop.Visible and OwnerListview.ShowGroupMargins then begin Result := DisplayRect; Result.Bottom := Result.Top + MarginTop.RuntimeSize; Result.Right := Result.Right - MarginRight.RuntimeSize; Result.Left := Result.Left + MarginLeft.RuntimeSize; end else Result := Rect(0, 0, 0, 0); end; function TEasyGroup.BoundsRectBkGnd: TRect; begin Result := DisplayRect; Result.Left := Result.Left + MarginLeft.RuntimeSize; Result.Right := Result.Right - MarginRight.RuntimeSize; Result.Top := Result.Top + MarginTop.RuntimeSize; Result.Bottom := Result.Bottom - MarginBottom.RuntimeSize; if Result.Bottom < Result.Top then Result.Bottom := Result.Top; if Result.Right < Result.Left then Result.Right := Result.Left end; function TEasyGroup.CanChangeBold(NewValue: Boolean): Boolean; begin Result := True end; function TEasyGroup.CanChangeCheck(NewValue: Boolean): Boolean; begin Result := Enabled; end; function TEasyGroup.CanChangeEnable(NewValue: Boolean): Boolean; begin Result := True; end; function TEasyGroup.CanChangeFocus(NewValue: Boolean): Boolean; begin // Unsupported Result := False; end; function TEasyGroup.CanChangeHotTracking(NewValue: Boolean): Boolean; begin // Unsupported Result := True; end; function TEasyGroup.CanChangeSelection(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoGroupSelectionChanging(Self, Result) end; function TEasyGroup.CanChangeVisibility(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoGroupVisibilityChanging(Self, Result) end; function TEasyGroup.DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; begin Result:= OwnerListview.ImagesGroup end; function TEasyGroup.EditAreaHitPt(ViewportPoint: TPoint): Boolean; begin Result := View.EditAreaHitPt(Self, ViewportPoint) end; function TEasyGroup.GetBandBlended: Boolean; begin Result := PaintInfo.BandBlended end; function TEasyGroup.GetBandColor: TColor; begin Result := PaintInfo.BandColor end; function TEasyGroup.GetBandColorFade: TColor; begin Result := PaintInfo.BandColorFade end; function TEasyGroup.GetBandEnabled: Boolean; begin Result := PaintInfo.BandEnabled end; function TEasyGroup.GetBandFullWidth: Boolean; begin Result := PaintInfo.BandFullWidth end; function TEasyGroup.GetBandIndent: Integer; begin Result := PaintInfo.BandIndent end; function TEasyGroup.GetBandLength: Integer; begin Result := PaintInfo.BandLength end; function TEasyGroup.GetBandMargin: Integer; begin Result := PaintInfo.BandMargin end; function TEasyGroup.GetBandRadius: Byte; begin Result := PaintInfo.BandRadius end; function TEasyGroup.GetBandThickness: Integer; begin Result := PaintInfo.BandThickness end; function TEasyGroup.GetClientRect: TRect; begin Result := Rect( FDisplayRect.Left + MarginLeft.RuntimeSize, FDisplayRect.Top + MarginTop.RuntimeSize, FDisplayRect.Right - MarginRight.RuntimeSize, FDisplayRect.Bottom - MarginBottom.RuntimeSize) end; function TEasyGroup.GetDefaultGridClass: TEasyGridGroupClass; begin Result := nil; case OwnerListview.View of elsIcon: Result := TEasyGridIconGroup; elsSmallIcon: Result := TEasyGridSmallIconGroup; elsList: Result := TEasyGridListGroup; elsReport: Result := TEasyGridReportGroup; elsThumbnail: Result := TEasyGridThumbnailGroup; elsTile: Result := TEasyGridTileGroup; elsFilmStrip: Result := TEasyGridFilmStripGroup; elsGrid: Result := TEasyGridGridGroup; end end; function TEasyGroup.GetDefaultViewClass: TEasyViewGroupClass; begin Result := TEasyViewGroup end; function TEasyGroup.GetExpandable: Boolean; begin Result := PaintInfo.Expandable end; function TEasyGroup.GetExpandImageIndent: Integer; begin Result := PaintInfo.ExpandImageIndent end; function TEasyGroup.GetGrid: TEasyGridGroup; begin if Assigned(FGrid) then begin if FGrid.ClassType <> GridClass then FreeAndNil(FGrid); end; if not Assigned(FGrid) then begin FGrid := GridClass.Create(OwnerListview, Self); case OwnerListview.View of elsIcon: FGrid.CellSize.Assign(OwnerListview.CellSizes.Icon); elsSmallIcon: FGrid.CellSize.Assign(OwnerListview.CellSizes.SmallIcon); elsList: FGrid.CellSize.Assign(OwnerListview.CellSizes.List); elsReport: FGrid.CellSize.Assign(OwnerListview.CellSizes.Report); elsThumbnail: FGrid.CellSize.Assign(OwnerListview.CellSizes.Thumbnail); elsTile: FGrid.CellSize.Assign(OwnerListview.CellSizes.Tile); elsFilmStrip: FGrid.CellSize.Assign(OwnerListview.CellSizes.FilmStrip); elsGrid: FGrid.CellSize.Assign(OwnerListview.CellSizes.Grid); end end; Result := FGrid; end; function TEasyGroup.GetGridClass: TEasyGridGroupClass; begin Result := nil; OwnerListview.DoCustomGrid(Self, OwnerListview.View, Result); if not Assigned(Result) then Result := GetDefaultGridClass end; function TEasyGroup.GetItem(Index: Integer): TEasyItem; begin Result := Items[Index] end; function TEasyGroup.GetItemCount: Integer; begin Result := Items.Count end; function TEasyGroup.GetMarginBottom: TEasyFooterMargin; begin Result := PaintInfo.MarginBottom as TEasyFooterMargin end; function TEasyGroup.GetMarginLeft: TEasyMargin; begin Result := PaintInfo.MarginLeft end; function TEasyGroup.GetMarginRight: TEasyMargin; begin Result := PaintInfo.MarginRight end; function TEasyGroup.GetMarginTop: TEasyHeaderMargin; begin Result := PaintInfo.MarginTop end; function TEasyGroup.GetOwnerGroups: TEasyGroups; begin Result := TEasyGroups( Collection) end; function TEasyGroup.GetOwnerListview: TCustomEasyListview; begin Result := TEasyGroups( Collection).OwnerListview end; function TEasyGroup.GetPaintInfo: TEasyPaintInfoBaseGroup; begin Result := inherited PaintInfo as TEasyPaintInfoBaseGroup end; function TEasyGroup.GetView: TEasyViewGroup; begin if Assigned(FView) then begin if FView.ClassType <> ViewClass then FreeAndNil(FView) end; if not Assigned(FView) then FView := ViewClass.Create(Self); Result := FView end; function TEasyGroup.GetViewClass: TEasyViewGroupClass; begin Result := nil; if Assigned(OwnerListview) then OwnerListview.DoGroupCustomView(Self, OwnerListview.View, Result); if not Assigned(Result) then Result := GetDefaultViewClass end; function TEasyGroup.GetVisibleCount: Integer; begin Result := FVisibleItems.Count end; function TEasyGroup.GetVisibleItem(Index: Integer): TEasyItem; begin Result := nil; if (Index > -1) and (Index < VisibleItems.Count) then Result := TEasyItem( VisibleItems[Index]) end; function TEasyGroup.HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyGroupHitTestInfoSet): Boolean; /// // Returns information about what, if anything, was hit at the passed point in // the group. Returns true if anything was hit. // var RectArray: TEasyRectArrayObject; R: TRect; begin HitInfo := []; // First need to see what Frame of the group was hit, and then the individual // rectangle for each element in the Frame is retrieved if PtInRect(BoundsRectTopMargin, ViewportPoint) then begin Include(HitInfo, egtOnHeader); View.GroupRectArray(Self, egmeTop, BoundsRectTopMargin, RectArray); end else if PtInRect(BoundsRectBottomMargin, ViewportPoint) then begin Include(HitInfo, egtOnFooter); View.GroupRectArray(Self, egmeBottom, BoundsRectBottomMargin, RectArray); end else if PtInRect(BoundsRectLeftMargin, ViewportPoint) then begin Include(HitInfo, egtOnLeftMargin); View.GroupRectArray(Self, egmeLeft, BoundsRectLeftMargin, RectArray); end else if PtInRect(BoundsRectRightMargin, ViewportPoint) then begin Include(HitInfo, egtOnRightMargin); View.GroupRectArray(Self, egmeRight, BoundsRectRightMargin, RectArray); end; if HitInfo <> [] then begin R := RectArray.IconRect; // Make the blank area between the image and text part of the image R.Right := R.Right + OwnerListview.PaintInfoGroup.CaptionIndent; if PtInRect(R, ViewportPoint) then Include(HitInfo, egtOnIcon) else if PtInRect(RectArray.TextRect, ViewportPoint) then Include(HitInfo, egtOnText) else if PtInRect(RectArray.LabelRect, ViewportPoint) then Include(HitInfo, egtOnLabel) else if PtInRect(RectArray.ExpandButtonRect, ViewportPoint) then Include(HitInfo, egtOnExpandButton) else if PtInRect(RectArray.BandRect, ViewportPoint) then Include(HitInfo, egtOnBand) else if PtInRect(RectArray.CheckRect, ViewportPoint) then Include(HitInfo, egtOnCheckbox); end; Result := HitInfo <> [] end; function TEasyGroup.ItemByPoint(ViewportPoint: TPoint): TEasyItem; var i: Integer; begin Result := nil; i := 0; while not Assigned(Result) and (i < Items.Count) do begin if PtInRect(Items[i].DisplayRect, ViewportPoint) then Result := Items[i]; Inc(i) end; end; function TEasyGroup.LocalPaintInfo: TEasyPaintInfoBasic; begin Result := OwnerListview.PaintInfoGroup end; function TEasyGroup.SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHit(Self, SelectViewPortRect, SelectType) end; function TEasyGroup.SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHitPt(Self, ViewportPoint, SelectType) end; procedure TEasyGroup.Freeing; begin OwnerListview.DoGroupFreeing(Self) end; procedure TEasyGroup.GainingBold; begin Invalidate(False) end; procedure TEasyGroup.GainingCheck; var i: Integer; begin for i := 0 to Items.Count - 1 do if Items[i].Visible then Items[i].Checked := True; if Visible then Include(FState, esosChecked); Invalidate(False) end; procedure TEasyGroup.GainingEnable; var i: Integer; begin for i := 0 to Items.Count - 1 do Items[i].Enabled := True; Include(FState, esosEnabled); Invalidate(False) end; procedure TEasyGroup.GainingFocus; begin // Unsupported end; procedure TEasyGroup.GainingGhosted; begin Invalidate(False) end; procedure TEasyGroup.GainingHilight; begin // Unsupported end; procedure TEasyGroup.GainingHotTracking(MousePos: TPoint); begin OwnerListview.DoGroupHotTrack(Self, ehsEnable, MousePos); Invalidate(True) end; procedure TEasyGroup.GainingSelection; begin OwnerListview.DoGroupSelectionChanged(Self) end; procedure TEasyGroup.GainingVisibility; var i: Integer; begin OwnerListview.DoGroupVisibilityChanged(Self); for i := 0 to Items.Count - 1 do Items[i].Visible := True end; procedure TEasyGroup.Initialize; begin OwnerListview.DoGroupInitialize(Self) end; procedure TEasyGroup.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); if not Assigned(Items) then Items := TEasyItems.Create(OwnerListview, Self) else Items.Clear; Items.ReadItems(S); OwnerListview.DoGroupLoadFromStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyGroup.LosingBold; begin Invalidate(False) end; procedure TEasyGroup.LosingCheck; var i: Integer; begin for i := 0 to Items.Count - 1 do Items[i].Checked := False; Exclude(FState, esosChecked); Invalidate(False) end; procedure TEasyGroup.LosingEnable; var i: Integer; begin for i := 0 to Items.Count - 1 do Items[i].Enabled := False; Exclude(FState, esosEnabled); Invalidate(False) end; procedure TEasyGroup.LosingFocus; begin // Unsupported end; procedure TEasyGroup.LosingGhosted; begin Invalidate(False) end; procedure TEasyGroup.LosingHilight; begin // Unsupported end; procedure TEasyGroup.LosingHotTracking; begin OwnerListview.DoGroupHotTrack(Self, ehsDisable, Point(0, 0)); Invalidate(True) end; procedure TEasyGroup.LosingSelection; begin OwnerListview.DoGroupSelectionChanged(Self) end; procedure TEasyGroup.LosingVisibility; var i: Integer; begin for i := 0 to Items.Count - 1 do Items[i].Visible := False; OwnerListview.DoGroupVisibilityChanged(Self); end; procedure TEasyGroup.Paint(MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; ACanvas: TCanvas); begin View.Paint(Self, MarginEdge, ObjRect, ACanvas) end; procedure TEasyGroup.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); begin if Assigned(Grid) then Grid.Rebuild(PrevGroup, NextVisibleItemIndex) end; procedure TEasyGroup.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); Items.WriteItems(S); OwnerListview.DoGroupSaveToStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyGroup.SetBandBlended(Value: Boolean); begin if Value <> BandBlended then begin PaintInfo.BandBlended := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandColor(Value: TColor); begin if Value <> BandColor then begin PaintInfo.BandColor := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandColorFade(Value: TColor); begin if Value <> BandColorFade then begin PaintInfo.BandColorFade := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandEnabled(Value: Boolean); begin if Value <> BandEnabled then begin PaintInfo.BandEnabled := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandFullWidth(Value: Boolean); begin if Value <> BandFullWidth then begin PaintInfo.BandFullWidth := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandIndent(Value: Integer); begin if Value <> BandIndent then begin PaintInfo.BandIndent := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandLength(Value: Integer); begin if Value <> BandLength then begin PaintInfo.BandLength := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandMargin(Value: Integer); begin if Value <> BandMargin then begin PaintInfo.BandMargin := Value; Invalidate(False) end end; procedure TEasyGroup.SetBandRadius(Value: Byte); begin if Value <> BandRadius then begin PaintInfo.BandRadius:= Value; Invalidate(False) end end; procedure TEasyGroup.SetBandThickness(Value: Integer); begin if Value <> BandThickness then begin PaintInfo.BandThickness := Value; Invalidate(False) end end; procedure TEasyGroup.SetExpandable(Value: Boolean); begin if Value <> Expandable then begin PaintInfo.Expandable := Value; Invalidate(False) end end; procedure TEasyGroup.SetExpanded(Value: Boolean); begin if Value <> FExpanded then begin OwnerListview.BeginUpdate; try FExpanded := Value; if Value then OwnerListview.DoGroupExpand(Self) else OwnerListview.DoGroupCollapse(Self); OwnerListview.Groups.Rebuild(True); finally OwnerListview.EndUpdate; end end end; procedure TEasyGroup.SetExpandImageIndent(Value: Integer); begin if Value <> ExpandImageIndent then begin PaintInfo.ExpandImageIndent := Value; Invalidate(False) end end; procedure TEasyGroup.SetItem(Index: Integer; Value: TEasyItem); begin if (Index > -1) and (Index < Items.Count) then Items[Index] := Value end; procedure TEasyGroup.SetMarginBottom(Value: TEasyFooterMargin); begin if Value <> MarginBottom then begin PaintInfo.MarginBottom := Value; Invalidate(False) end end; procedure TEasyGroup.SetMarginLeft(Value: TEasyMargin); begin if Value <> MarginLeft then begin PaintInfo.MarginLeft := Value; Invalidate(False) end end; procedure TEasyGroup.SetMarginRight(Value: TEasyMargin); begin if Value <> MarginRight then begin PaintInfo.MarginRight := Value; Invalidate(False) end end; procedure TEasyGroup.SetMarginTop(Value: TEasyHeaderMargin); begin if Value <> MarginTop then begin PaintInfo.MarginTop := Value; Invalidate(False) end end; procedure TEasyGroup.SetPaintInfo(const Value: TEasyPaintInfoBaseGroup); begin inherited PaintInfo := Value end; function TEasyViewGroup.CustomExpandImages: Boolean; begin Result := not OwnerListview.GroupCollapseButton.Empty or not OwnerListview.GroupExpandButton.Empty end; function TEasyViewGroup.EditAreaHitPt(Group: TEasyGroup; ViewportPoint: TPoint): Boolean; begin Result := False end; function TEasyViewGroup.GetImageList(Group: TEasyGroup): TCustomImageList; begin Result := Group.ImageList[-1, eisSmall] end; function TEasyViewGroup.SelectionHit(Group: TEasyGroup; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; begin Result := False end; function TEasyViewGroup.SelectionHitPt(Group: TEasyGroup; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; begin Result := False end; { TEasyGroupView } procedure TEasyViewGroup.GetCollapseExpandImages(var Expand, Collapse: TBitmap); begin Expand := nil; Collapse := nil; if not OwnerListview.GroupCollapseButton.Empty then Collapse := OwnerListview.GroupCollapseButton else Collapse := OwnerListview.GlobalImages.GroupCollapseButton; if not OwnerListview.GroupExpandButton.Empty then Expand := OwnerListview.GroupExpandButton else Expand := OwnerListview.GlobalImages.GroupExpandButton; end; procedure TEasyViewGroup.GetExpandImageSize(Group: TEasyGroup; var ImageW, ImageH: Integer); var ExpandImage, CollapseImage: TBitmap; begin ImageW := 0; ImageH := 0; GetCollapseExpandImages(ExpandImage, CollapseImage); if Assigned(ExpandImage) and Assigned(CollapseImage) then begin ImageW := ExpandImage.Width; ImageH := ExpandImage.Height; if CollapseImage.Width > ImageW then ImageW := CollapseImage.Width; if CollapseImage.Height > ImageH then ImageH := CollapseImage.Height end end; procedure TEasyViewGroup.GetImageSize(Group: TEasyGroup; var ImageW, ImageH: Integer); var Images: TCustomImageList; IsCustom: Boolean; begin ImageW := 0; ImageH := 0; Group.ImageDrawIsCustom(nil, IsCustom); if IsCustom then Group.ImageDrawGetSize(nil, ImageW, ImageH) else begin Images := GetImageList(Group); if (Group.ImageIndexes[0] > -1) and Assigned(Images) then begin ImageW := Images.Width; ImageH := Images.Height end end; end; procedure TEasyViewGroup.GroupRectArray(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; var RectArray: TEasyRectArrayObject); // // Grabs all the rectangles for the items within a cell in one call // If PaintInfo is nil then the information is fetched automaticlly // var TextSize: TSize; HeaderBand, FooterBand: TRect; TempRectArray: TEasyRectArrayObject; ImageW, ImageH, ExpandImageW, ExpandImageH, BandOffset: Integer; begin Group.Initialized := True; FillChar(RectArray, SizeOf(RectArray), #0); RectArray.GroupRect := ObjRect; RectArray.BackGndRect := Group.BoundsRectBkGnd; GetImageSize(Group, ImageW, ImageH); GetExpandImageSize(Group, ExpandImageW, ExpandImageH); ExpandImageW := Round( ExpandImageW + GetDeviceCaps(OwnerListview.Canvas.Handle, LOGPIXELSX)/96); if MarginEdge in [egmeTop, egmeBottom] then begin if Group.BandEnabled then BandOffset := Group.BandThickness + 2 * Group.BandMargin else BandOffset := 0; // Calculate the Expansion button first for the Header only if Group.Expandable and (MarginEdge = egmeTop) then RectArray.ExpandButtonRect := Rect(RectArray.GroupRect.Left + Group.ExpandImageIndent, RectArray.GroupRect.Top, RectArray.GroupRect.Left + ExpandImageW + Group.ExpandImageIndent, RectArray.GroupRect.Bottom - BandOffset) else // Make the ExpandButton R a width of 0 RectArray.ExpandButtonRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Top, RectArray.GroupRect.Left, RectArray.GroupRect.Bottom - BandOffset); if (Group.CheckType <> ectNone) and (MarginEdge in [egmeTop]) then begin RectArray.CheckRect := Checks.Bound[Group.CheckSize]; case Group.VAlignment of cvaTop: OffsetRect(RectArray.CheckRect, RectArray.ExpandButtonRect.Right + Group.CheckIndent, ObjRect.Top + 2); cvaBottom: OffsetRect(RectArray.CheckRect, RectArray.ExpandButtonRect.Right + Group.CheckIndent, ObjRect.Bottom - BandOffset - RectHeight(RectArray.CheckRect) - 2); cvaCenter: OffsetRect(RectArray.CheckRect, RectArray.ExpandButtonRect.Right + Group.CheckIndent, (ObjRect.Top + ((RectHeight(ObjRect) - BandOffset) - RectHeight(RectArray.CheckRect)) div 2)); end end else begin // CheckRect is a 0 width RectArray.CheckRect := ObjRect; RectArray.CheckRect.Left := RectArray.ExpandButtonRect.Right; RectArray.CheckRect.Right := RectArray.ExpandButtonRect.Right; end; // Now Calculate the image for the header or the footer if Group.ImageIndex > -1 then RectArray.IconRect := Rect(RectArray.CheckRect.Right + Group.ImageIndent, RectArray.GroupRect.Top, RectArray.CheckRect.Right + ImageW + Group.ImageIndent, RectArray.GroupRect.Bottom - BandOffset) else // Make the IconR a width of 0 RectArray.IconRect := Rect(RectArray.CheckRect.Right, RectArray.CheckRect.Top, RectArray.CheckRect.Right, RectArray.CheckRect.Bottom - BandOffset); // Now the Label rect may be calculated for the header or footer RectArray.LabelRect := Rect(RectArray.IconRect.Right + Group.CaptionIndent, RectArray.ExpandButtonRect.Top, RectArray.GroupRect.Right, RectArray.ExpandButtonRect.Bottom); // Calculate the text size for the text based on the above font if Assigned(OwnerListview.ScratchCanvas) then begin LoadTextFont(Group, OwnerListview.ScratchCanvas); TextSize := TextExtentW(Group.Caption, OwnerListview.ScratchCanvas.Font); end else begin TextSize.cx := 0; TextSize.cy := 0; end; // Use the calculated label rectangle to position where the text goes RectArray.TextRect := Rect(RectArray.LabelRect.Left, RectArray.LabelRect.Top, RectArray.LabelRect.Left + TextSize.cx, RectArray.LabelRect.Top + TextSize.cy); if RectArray.TextRect.Right > RectArray.LabelRect.Right then RectArray.TextRect.Right := RectArray.LabelRect.Right; if RectArray.TextRect.Bottom > RectArray.LabelRect.Bottom then RectArray.TextRect.Bottom := RectArray.LabelRect.Bottom; case Group.Alignment of taLeftJustify: OffsetRect(RectArray.TextRect, 0, 0); taRightJustify: OffsetRect(RectArray.TextRect, RectWidth(RectArray.LabelRect) - (RectWidth(RectArray.TextRect)), 0); taCenter: OffsetRect(RectArray.TextRect, (RectWidth(RectArray.LabelRect) - RectWidth(RectArray.TextRect)) div 2, 0); end; case Group.VAlignment of cvaBottom: OffsetRect(RectArray.TextRect, 0, RectHeight(RectArray.GroupRect) - (RectHeight(RectArray.TextRect) + BandOffset)); cvaCenter: OffsetRect(RectArray.TextRect, 0, ((RectHeight(RectArray.GroupRect) - BandOffset) - RectHeight(RectArray.TextRect)) div 2); end; if Group.BandEnabled then begin if Group.BandFullWidth then RectArray.BandRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Bottom - Group.BandMargin - Group.BandThickness, RectArray.GroupRect.Right, RectArray.GroupRect.Bottom - Group.BandMargin) else RectArray.BandRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Bottom - 2 * Group.BandMargin - Group.BandThickness, RectArray.GroupRect.Left + Group.BandLength, RectArray.GroupRect.Bottom - Group.BandMargin); OffsetRect(RectArray.BandRect, Group.BandIndent, 0); end; end else begin // Calculate the margin rectangles // Need to send nil so the user attributes are fetched for the header GroupRectArray(Group, egmeTop, Group.BoundsRectTopMargin, TempRectArray); HeaderBand := TempRectArray.BandRect; // Need to send nil so the user attributes are fetched for the footer GroupRectArray(Group, egmeBottom, Group.BoundsRectBottomMargin, TempRectArray); FooterBand := TempRectArray.BandRect; if MarginEdge = egmeLeft then RectArray.BandRect := Rect(RectArray.GroupRect.Left + (RectWidth(RectArray.GroupRect) - Group.BandThickness) div 2, HeaderBand.Top, RectArray.GroupRect.Right, FooterBand.Bottom - 1); if MarginEdge = egmeRight then RectArray.BandRect := Rect(RectArray.GroupRect.Left, HeaderBand.Top, RectArray.GroupRect.Right - (RectWidth(RectArray.GroupRect) - Group.BandThickness) div 2, FooterBand.Bottom - 1) end; end; procedure TEasyViewGroup.LoadTextFont(Group: TEasyGroup; ACanvas: TCanvas); begin if Assigned(ACanvas) then begin ACanvas.Font.Assign(OwnerListview.GroupFont); ACanvas.Brush.Style := bsClear; if Group.Focused then begin if OwnerListview.Focused then ACanvas.Font.Color := clHighlightText; end; if Group.Bold then ACanvas.Font.Style := ACanvas.Font.Style + [fsBold]; OwnerListview.DoGroupPaintText(Group, ACanvas); end end; procedure TEasyViewGroup.Paint(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; ACanvas: TCanvas); // // Calls the sub Paint methods to do a complete Paint cycle for the Group // var RectArray: TEasyRectArrayObject; begin if not IsRectEmpty(ObjRect) then begin CanvasStore.StoreCanvasState(ACanvas); try GroupRectArray(Group, MarginEdge, ObjRect, RectArray); PaintBefore(Group, ACanvas, MarginEdge, ObjRect, RectArray); PaintBackground(Group, ACanvas, MarginEdge, ObjRect, RectArray); if MarginEdge = egmeTop then PaintCheckBox(Group, ACanvas, RectArray); PaintSelectionRect(Group, ACanvas, ObjRect, RectArray); PaintFocusRect(Group, ACanvas, MarginEdge, ObjRect, RectArray); PaintText(Group, MarginEdge, ACanvas, ObjRect, RectArray); PaintBand(Group, ACanvas, MarginEdge, ObjRect, RectArray); PaintExpandButton(Group, ACanvas, MarginEdge, ObjRect, RectArray); PaintImage(Group, ACanvas, MarginEdge, ObjRect, RectArray); PaintAfter(Group, ACanvas, MarginEdge, ObjRect, RectArray); finally CanvasStore.RestoreCanvasState(ACanvas) end end end; procedure TEasyViewGroup.PaintAfter(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewGroup.PaintBackground(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge;ObjRect: TRect; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewGroup.PaintBand(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paints the banding in none, one, ..., all margins of the Group var i: Integer; Red1, Red2, Green1, Green2, Blue1, Blue2, RC, GC, BC, BandTop: Integer; RStep, GStep, BStep : Double; RGBVal, BlendStop: Longword; CellR: TRect; begin if Group.BandEnabled and not IsRectEmpty(RectArray.BandRect) then begin CellR := ObjRect; if MarginEdge in [egmeBottom, egmeTop] then begin BandTop := RectArray.BandRect.Top + Group.BandMargin; // Draw the Banding if Group.BandBlended then begin if (Group.BandLength > 0) then begin // Calulate the stepping to create the blended banding RGBVal := ColorToRGB(Group.BandColor); Red1 := GetRValue(RGBVal); Green1 := GetGValue(RGBVal); Blue1 := GetBValue(RGBVal); RGBVal := ColorToRGB(Group.BandColorFade); Red2 := GetRValue(RGBVal); Green2 := GetGValue(RGBVal); Blue2 := GetBValue(RGBVal); if Group.BandFullWidth then BlendStop := RectWidth(CellR) else BlendStop := Group.BandLength; RStep := (Red2-Red1)/BlendStop; GStep := (Green2-Green1)/BlendStop; BStep := (Blue2-Blue1)/BlendStop; ACanvas.Pen.Color := Group.BandColor; // Draw the Banding for i := 0 to BlendStop do begin if Group.BandFullWidth then begin ACanvas.MoveTo(CellR.Left + i, BandTop); ACanvas.LineTo(CellR.Left + i, BandTop + Group.BandThickness); end else begin ACanvas.MoveTo(RectArray.BandRect.Left + i, BandTop); ACanvas.LineTo(RectArray.BandRect.Left + i, BandTop + Group.BandThickness); end; RC:=Round(Red1 + i*RStep); GC:=Round(Green1 +i*GStep); BC:=Round(Blue1 + i*BStep); ACanvas.Pen.Color := RGB(RC, GC, BC); end end end else begin ACanvas.Pen.Color := Group.BandColor; if Group.BandFullWidth then begin for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(CellR.Left, BandTop + i); ACanvas.LineTo(CellR.Right, BandTop + i); end end else begin for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left, BandTop + i); ACanvas.LineTo(RectArray.BandRect.Left + Group.BandLength, BandTop + i); end end end end else begin if (MarginEdge in [egmeRight]) and Group.BandBlended then ACanvas.Pen.Color := Group.BandColorFade else ACanvas.Pen.Color := Group.BandColor; if MarginEdge = egmeLeft then begin // Draw the horizontal stubs on the top and bottom for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left + Group.BandRadius, RectArray.BandRect.Top + i); ACanvas.LineTo(RectArray.BandRect.Right + 1, RectArray.BandRect.Top + i) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left + Group.BandRadius, RectArray.BandRect.Bottom - i); ACanvas.LineTo(RectArray.BandRect.Right + 1, RectArray.BandRect.Bottom - i) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left + i, RectArray.BandRect.Top + Group.BandRadius); ACanvas.LineTo(RectArray.BandRect.Left + i, RectArray.BandRect.Bottom - Group.BandRadius + 1) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left + Group.BandRadius, RectArray.BandRect.Top); AngleArc(ACanvas.Handle, RectArray.BandRect.Left + Group.BandRadius, RectArray.BandRect.Top + Group.BandRadius, Group.BandRadius - i, 90, 90); ACanvas.MoveTo(RectArray.BandRect.Left, RectArray.BandRect.Bottom - Group.BandRadius); AngleArc(ACanvas.Handle, RectArray.BandRect.Left + Group.BandRadius, RectArray.BandRect.Bottom - Group.BandRadius, Group.BandRadius - i, 180, 90); end end else begin // Draw the horizontal stubs on the top and bottom for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left, RectArray.BandRect.Top + i); ACanvas.LineTo(RectArray.BandRect.Right - Group.BandRadius + 1, RectArray.BandRect.Top + i) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Left, RectArray.BandRect.Bottom - i); ACanvas.LineTo(RectArray.BandRect.Right - Group.BandRadius + 1, RectArray.BandRect.Bottom - i) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Right - i, RectArray.BandRect.Top + Group.BandRadius); ACanvas.LineTo(RectArray.BandRect.Right - i, RectArray.BandRect.Bottom - Group.BandRadius + 1) end; for i := 0 to Group.BandThickness - 1 do begin ACanvas.MoveTo(RectArray.BandRect.Right, RectArray.BandRect.Top + Group.BandRadius); AngleArc(ACanvas.Handle, RectArray.BandRect.Right - Group.BandRadius, RectArray.BandRect.Top + Group.BandRadius, Group.BandRadius - i, 0, 90); ACanvas.MoveTo(RectArray.BandRect.Right - Group.BandRadius, RectArray.BandRect.Bottom); AngleArc(ACanvas.Handle, RectArray.BandRect.Right - Group.BandRadius, RectArray.BandRect.Bottom - Group.BandRadius, Group.BandRadius - i, 270, 90); end end end end end; procedure TEasyViewGroup.PaintBefore(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewGroup.PaintCheckBox(Group: TEasyGroup; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); begin if not ((Group.CheckType = ectNone) or (Group.CheckType = ettNoneWithSpace)) then PaintCheckboxCore(Group.CheckType, // TEasyCheckType OwnerListview, // TCustomEasyListview ACanvas, // TCanvas RectArray.CheckRect, // TRect Group.Enabled, // IsEnabled Group.Checked, // IsChecked Group.CheckPending and (ebcsCheckboxClickPending in OwnerListview.States), // IsHot Group.CheckFlat, // IsFlat Group.CheckHovering, // IsHovering Group.CheckPending, // IsPending Group, Group.CheckSize); end; procedure TEasyViewGroup.PaintExpandButton(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paints the [+] button for collapable groups // var Image, ExpandImage, CollapseImage: TBitmap; {$IFDEF USETHEMES} Part, uState: Longword; R: TRect; {$ENDIF} begin if MarginEdge in [egmeTop] then begin GetCollapseExpandImages(ExpandImage, CollapseImage); {$IFDEF USETHEMES} if Group.OwnerListview.DrawWithThemes and not CustomExpandImages then begin Part := TVP_GLYPH; if Group.Expanded then uState := GLPS_OPENED else uState := GLPS_CLOSED; R := RectArray.ExpandButtonRect; R.Top := R.Top + (RectHeight(RectArray.ExpandButtonRect) - RectWidth(RectArray.ExpandButtonRect)) div 2; R.Bottom := R.Top + RectWidth(R); DrawThemeBackground(Group.OwnerListview.Themes.TreeviewTheme, ACanvas.Handle, Part, uState, R, nil); Exit; end; {$ENDIF} // If the border is the header and it is expandable then must draw the // "+" expand box if Group.Expandable and (MarginEdge = egmeTop) then begin // Choose correct image if Group.Expanded then Image := CollapseImage else Image := ExpandImage; // Draw the image if Assigned(Image) then begin case Group.VAlignment of cvaTop: ACanvas.Draw(RectArray.ExpandButtonRect.Left + (RectWidth(RectArray.ExpandButtonRect) - Image.Width) div 2, RectArray.ExpandButtonRect.Top + 2, Image); cvaBottom: ACanvas.Draw(RectArray.ExpandButtonRect.Left + (RectWidth(RectArray.ExpandButtonRect) - Image.Width) div 2, RectArray.ExpandButtonRect.Bottom - 2 - Image.Height, Image); cvaCenter: ACanvas.Draw(RectArray.ExpandButtonRect.Left + (RectWidth(RectArray.ExpandButtonRect) - Image.Width) div 2, RectArray.ExpandButtonRect.Top + (RectHeight(RectArray.ExpandButtonRect) - Image.Height) div 2, Image); end end end end else begin end end; procedure TEasyViewGroup.PaintFocusRect(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paint the caption area of a group margin for a focused state // var R: TRect; begin if Group.Focused and (MarginEdge = egmeForeground) and not IsRectEmpty(RectArray.GroupRect) then begin R := RectArray.GroupRect; InflateRect(R, -4, -4); ACanvas.Brush.Color := Group.OwnerListview.Color; ACanvas.Font.Color := clBlack; DrawFocusRect(ACanvas.Handle, R); end end; procedure TEasyViewGroup.PaintImage(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paints the Icon/Bitmap to the group margin // var ImageIndex, OverlayIndex, fStyle: Integer; Images: TCustomImageList; IsCustom: Boolean; begin if MarginEdge in [egmeTop, egmeBottom] then begin Group.ImageDrawIsCustom(nil, IsCustom); if IsCustom then Group.ImageDraw(nil, ACanvas, RectArray, AlphaBlender) else begin Images := GetImageList(Group); if MarginEdge = egmeTop then begin ImageIndex := Group.ImageIndex; OverlayIndex := Group.ImageOverlayIndex end else begin ImageIndex := Group.MarginBottom.ImageIndex; OverlayIndex := Group.MarginBottom.ImageOverlayIndex end; // Draw the image in the ImageList if available if Assigned(Images) and (Group.ImageIndex > -1) then begin fStyle := ILD_TRANSPARENT; if OverlayIndex > -1 then begin ImageList_SetOverlayImage(Images.Handle, OverlayIndex, 1); fStyle := fStyle or INDEXTOOVERLAYMASK(1) end; // Get the "normalized" rectangle for the image RectArray.IconRect.Left := RectArray.IconRect.Left + (RectWidth(RectArray.IconRect) - Images.Width) div 2; case Group.VAlignment of cvaTop: RectArray.IconRect.Top := RectArray.IconRect.Top + 2; cvaBottom: RectArray.IconRect.Top := RectArray.IconRect.Bottom - (Images.Height + 2); cvaCenter: RectArray.IconRect.Top := RectArray.IconRect.Top + (RectHeight(RectArray.IconRect) - Images.Height) div 2; end; ImageList_DrawEx(Images.Handle, ImageIndex, ACanvas.Handle, RectArray.IconRect.Left, RectArray.IconRect.Top, 0, 0, CLR_NONE, CLR_NONE, fStyle); end end end end; procedure TEasyViewGroup.PaintSelectionRect(Group: TEasyGroup; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paint the caption area of a group margin for a selected state // begin if Group.Selected and not IsRectEmpty(RectArray.TextRect) and (Group.Caption <> '') then begin ACanvas.Brush.Color := clHighlight; InflateRect(RectArray.TextRect, 2, 2); ACanvas.FillRect(RectArray.TextRect); InflateRect(RectArray.TextRect, 2, 2); end end; procedure TEasyViewGroup.PaintText(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); // // Paints the caption within the group margin // var DrawTextFlags: TCommonDrawTextWFlags; Caption: WideString; Alignment: TAlignment; VAlignment: TCommonVAlignment; begin if not IsRectEmpty(RectArray.TextRect) and (Group.Caption <> '') then begin LoadTextFont(Group, ACanvas); if MarginEdge = egmeTop then begin Caption := Group.Caption; Alignment := Group.Alignment; VAlignment := Group.VAlignment; end else begin Caption := Group.MarginBottom.Caption; Alignment := Group.MarginBottom.Alignment; VAlignment := Group.MarginBottom.VAlignment; end; DrawTextFlags := [dtEndEllipsis]; // if PaintInfo.Caption.RTLReading then // Include(DrawTextFlags, dtRTLReading); case Alignment of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case VAlignment of cvaTop: Include(DrawTextFlags, dtTop); cvaCenter: Include(DrawTextFlags, dtVCenter); cvaBottom: Include(DrawTextFlags, dtBottom); end; // if PaintInfo.Caption.RTLReading then // Include(DrawTextFlags, dtRTLReading); DrawTextFlags := DrawTextFlags + [dtSingleLine]; DrawTextWEx(ACanvas.Handle, Caption, RectArray.TextRect, DrawTextFlags, 1); end end; { TEasyColumn } constructor TEasyColumn.Create(ACollection: TEasyCollection); begin inherited; FDropDownButton := TEasyColumnDropDownButton.Create(Self); FSortDirection := esdNone; FAutoToggleSortGlyph := True; FClickable := True; FWidth := 50; FPosition := OwnerColumns.Count; AutoSizeOnDblClk := True; end; destructor TEasyColumn.Destroy; begin SetDestroyFlags; if OwnerListview.Selection.FFocusedColumn = Self then OwnerListview.Selection.FocusedColumn := nil; if OwnerListview.Header.HotTrackedColumn = Self then OwnerListview.Header.HotTrackedColumn := nil; if OwnerListview.Header.PressColumn = Self then OwnerListview.Header.PressColumn := nil; if OwnerListview.EditManager.TabMoveFocusColumn = Self then OwnerListview.EditManager.TabMoveFocusColumn := nil; if OwnerListview.Selection.FocusedColumn = Self then OwnerListview.Selection.FocusedColumn := nil; if OwnerListview.Header.DropDownHoverColumn = Self then OwnerListview.Header.DropDownHoverColumn := nil; FreeAndNil(FDropDownButton); inherited Destroy; FreeAndNil(FView); end; function TEasyColumn.CanChangeBold(NewValue: Boolean): Boolean; begin Result := True end; function TEasyColumn.CanChangeCheck(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoColumnCheckChanging(Self, Result) end; function TEasyColumn.CanChangeEnable(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoColumnEnableChanging(Self, Result) end; function TEasyColumn.CanChangeFocus(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoColumnFocusChanging(Self, Result) end; function TEasyColumn.CanChangeHotTracking(NewValue: Boolean): Boolean; begin Result := True; end; function TEasyColumn.CanChangeSelection(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoColumnSelectionChanging(Self, Result) end; function TEasyColumn.CanChangeVisibility(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoColumnVisibilityChanging(Self, Result) end; function TEasyColumn.DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; begin Result := OwnerListview.Header.Images end; function TEasyColumn.EditAreaHitPt(ViewportPoint: TPoint): Boolean; begin Result := View.EditAreaHitPt(Self, ViewportPoint) end; function TEasyColumn.GetAlignment: TAlignment; begin Result := FAlignment end; function TEasyColumn.GetColor: TColor; begin Result := PaintInfo.Color end; function TEasyColumn.GetDefaultViewClass: TEasyViewColumnClass; begin Result := TEasyViewColumn end; function TEasyColumn.GetHotTrack: Boolean; begin Result := PaintInfo.HotTrack end; function TEasyColumn.GetImagePosition: TEasyHeaderImagePosition; begin Result := PaintInfo.ImagePosition end; function TEasyColumn.GetOwnerColumns: TEasyColumns; begin Result := TEasyColumns(Collection) end; function TEasyColumn.GetOwnerHeader: TEasyHeader; begin Result := OwnerListview.Header end; function TEasyColumn.GetPaintInfo: TEasyPaintInfoColumn; begin // Dangerous but necessary. The TaskPanel has its own PaintInfo to not publish // any properites. It will have a class type error using "is". The two types // are "equal" from a memory foot print so this will work. Result := TEasyPaintInfoColumn( inherited PaintInfo) end; function TEasyColumn.GetSortGlyphAlign: TEasySortGlyphAlign; begin Result := PaintInfo.SortGlyphAlign end; function TEasyColumn.GetSortGlyphIndent: Integer; begin Result := PaintInfo.SortGlyphIndent end; function TEasyColumn.GetStyle: TEasyHeaderButtonStyle; begin Result := PaintInfo.Style end; function TEasyColumn.GetView: TEasyViewColumn; begin if Assigned(FView) then begin if ViewClass <> FView.ClassType then FreeAndNil(FView) end; if not Assigned(FView) then FView := ViewClass.Create(OwnerListview); Result := FView; end; function TEasyColumn.GetViewClass: TEasyViewColumnClass; begin Result := nil; if Assigned(OwnerListview) then OwnerListview.DoColumnCustomView(Self, Result); if not Assigned(Result) then Result := GetDefaultViewClass end; function TEasyColumn.LocalPaintInfo: TEasyPaintInfoBasic; begin Result := OwnerListview.PaintInfoColumn end; function TEasyColumn.PaintMouseHovering: Boolean; begin Result := (OwnerListview.Header.HotTrackedColumn = Self) and HotTrack and not (OwnerListview.DragManager.Dragging or OwnerListview.DragRect.Dragging) end; function TEasyColumn.SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHit(Self, SelectViewportRect, SelectType) end; function TEasyColumn.SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHitPt(Self, ViewportPoint, SelectType) end; procedure TEasyColumn.AutoSizeToFit; var iIndex: Integer; W, i, j: Integer; Group: TEasyGroup; Canvas: TCanvas; Item: TEasyItem; Caption: WideString; Size: TSize; ImageW, ImageH: Integer; begin iIndex := Index; Canvas := OwnerListview.Canvas; W := 0; for i := 0 to OwnerListview.Groups.Count - 1 do for j := 0 to OwnerListview.Groups[i].ItemCount - 1 do begin Group := OwnerListview.Groups[i]; Item := Group.Items[j]; Item.View.LoadTextFont(Item, iIndex, Canvas, False); OwnerListview.DoItemPaintText(Item, Index, Canvas); Caption := Item.Captions[iIndex]; Size := TextExtentW(Caption, Canvas); Size.cx := Size.cx + {2 * LABEL_MARGIN +} 8; Item.View.GetImageSize(Item, Self, ImageW, ImageH, eikNormal); if ImageW > 0 then Size.cx := Size.cx + ImageW + ImageIndent; Item.View.GetImageSize(Item, Self, ImageW, ImageH, eikState); if ImageW > 0 then Size.cx := Size.cx + ImageW; if CheckType <> ectNone then Size.cx := Size.cx + CheckIndent + RectWidth(Checks.Bound[CheckSize]); if Size.cx > W then W := Size.cx; end; OwnerListview.Groups.BeginUpdate(False); try Width := W; if OwnerListview.Selection.FullRowSelect then OwnerListview.Groups.Rebuild(True); finally OwnerListview.Groups.EndUpdate; end end; procedure TEasyColumn.Freeing; begin OwnerListview.DoColumnFreeing(Self) end; procedure TEasyColumn.GainingBold; begin Invalidate(False) end; procedure TEasyColumn.GainingCheck; begin OwnerListview.DoColumnCheckChanged(Self) end; procedure TEasyColumn.GainingEnable; begin OwnerListview.DoColumnEnableChanged(Self) end; procedure TEasyColumn.GainingFocus; begin OwnerListview.DoColumnFocusChanged(Self) end; procedure TEasyColumn.GainingGhosted; begin Invalidate(False) end; procedure TEasyColumn.GainingHilight; begin // Unsupported end; procedure TEasyColumn.GainingHotTracking(MousePos: TPoint); begin // Unsupported end; procedure TEasyColumn.GainingSelection; begin OwnerListview.DoColumnSelectionChanged(Self) end; procedure TEasyColumn.GainingVisibility; begin OwnerListview.BeginUpdate; OwnerListview.DoColumnVisibilityChanged(Self); OwnerListview.EndUpdate(False); end; function TEasyColumn.HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyColumnHitTestInfoSet): Boolean; var RectArray: TEasyRectArrayObject; R: TRect; begin HitInfo := []; if Assigned(View) then begin View.ItemRectArray(Self, RectArray); R := RectArray.IconRect; // Make the blank area between the image and text part of the image R.Right := R.Right + OwnerListview.PaintInfoColumn.CaptionIndent; if PtInRect(R, ViewportPoint) then Include(HitInfo, ectOnText); if PtInRect(RectArray.IconRect, ViewportPoint) then Include(HitInfo, ectOnIcon); if PtInRect(RectArray.CheckRect, ViewportPoint) then Include(HitInfo, ectOnCheckbox); if PtInRect(RectArray.LabelRect, ViewportPoint) then Include(HitInfo, ectOnLabel); end; Result := HitInfo <> []; end; procedure TEasyColumn.Initialize; begin OwnerListview.DoColumnInitialize(Self) end; procedure TEasyColumn.Invalidate(ImmediateUpdate: Boolean); var R: TRect; begin if OwnerListview.UpdateCount = 0 then begin if OwnerListview.HandleAllocated then begin R := Rect(0, 0, OwnerListview.ClientWidth, OwnerHeader.Height); OwnerListview.SafeInvalidateRect(@R, ImmediateUpdate); end end end; procedure TEasyColumn.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); S.ReadBuffer(FAlignment, SizeOf(FAlignment)); S.ReadBuffer(FAutoSizeOnDblClk, SizeOf(FAutoSizeOnDblClk)); if Version > 1 then S.ReadBuffer(FAutoSortOnClick, SizeOf(FAutoSortOnClick)); S.ReadBuffer(FAutoSpring, SizeOf(FAutoSpring)); S.ReadBuffer(FAutoToggleSortGlyph, SizeOf(FAutoToggleSortGlyph)); S.ReadBuffer(FPosition, SizeOf(FPosition)); S.ReadBuffer(FSortDirection, SizeOf(FSortDirection)); S.ReadBuffer(FStyle, SizeOf(FStyle)); S.ReadBuffer(FClickable, SizeOf(FClickable)); S.ReadBuffer(FWidth, SizeOf(FWidth)); OwnerListview.DoColumnLoadFromStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyColumn.LosingBold; begin Invalidate(False) end; procedure TEasyColumn.LosingCheck; begin OwnerListview.DoColumnCheckChanged(Self) end; procedure TEasyColumn.LosingEnable; begin OwnerListview.DoColumnEnableChanged(Self) end; procedure TEasyColumn.LosingFocus; begin OwnerListview.DoColumnFocusChanged(Self) end; procedure TEasyColumn.LosingGhosted; begin Invalidate(False) end; procedure TEasyColumn.LosingHilight; begin // Unsupported end; procedure TEasyColumn.LosingHotTracking; begin // Unsupported end; procedure TEasyColumn.LosingSelection; begin OwnerListview.DoColumnSelectionChanged(Self) end; procedure TEasyColumn.LosingVisibility; begin OwnerListview.BeginUpdate; OwnerListview.DoColumnVisibilityChanged(Self); OwnerListview.EndUpdate(False); end; procedure TEasyColumn.MakeVisible(Position: TEasyMakeVisiblePos); var RectArray: TEasyRectArrayObject; ViewRect: TRect; ColumnW, ViewW: Integer; begin if Visible then begin View.ItemRectArray(Self, RectArray); ViewRect := OwnerListview.ClientInViewportCoords; ColumnW := RectArray.BoundsRect.Right - RectArray.BoundsRect.Left; ViewW := RectWidth(ViewRect); if not ((RectArray.BoundsRect.Left >= ViewRect.Left) and ( RectArray.BoundsRect.Right <= ViewRect.Right)) then begin case Position of emvTop: // or Left begin if ViewRect.Left < RectArray.BoundsRect.Left then OwnerListview.Scrollbars.OffsetX := RectArray.BoundsRect.Left; end; emvMiddle: begin if ColumnW < ViewW then OwnerListview.Scrollbars.OffsetX := RectArray.BoundsRect.Left - ((ViewW - ColumnW) div 2); end; emvBottom: // or right begin OwnerListview.Scrollbars.OffsetX := RectArray.BoundsRect.Right - ColumnW; end; emvAuto: begin if ViewRect.Left < RectArray.BoundsRect.Left then OwnerListview.Scrollbars.OffsetX := RectArray.BoundsRect.Left; end end end end end; procedure TEasyColumn.Paint(ACanvas: TCanvas; HeaderType: TEasyHeaderType); begin View.Paint(Self, ACanvas, HeaderType) end; procedure TEasyColumn.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); S.WriteBuffer(FAlignment, SizeOf(FAlignment)); S.WriteBuffer(FAutoSizeOnDblClk, SizeOf(FAutoSizeOnDblClk)); S.WriteBuffer(FAutoSortOnClick, SizeOf(FAutoSortOnClick)); S.WriteBuffer(FAutoSpring, SizeOf(FAutoSpring)); S.WriteBuffer(FAutoToggleSortGlyph, SizeOf(FAutoToggleSortGlyph)); S.WriteBuffer(FPosition, SizeOf(FPosition)); S.WriteBuffer(FSortDirection, SizeOf(FSortDirection)); S.WriteBuffer(FStyle, SizeOf(FStyle)); S.WriteBuffer(FClickable, SizeOf(FClickable)); S.WriteBuffer(FWidth, SizeOf(FWidth)); OwnerListview.DoColumnSaveToStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyColumn.SetAlignment(Value: TAlignment); begin if Value <> FAlignment then begin FAlignment := Value; Invalidate(False); end end; procedure TEasyColumn.SetAutoSpring(const Value: Boolean); begin FAutoSpring := Value; end; procedure TEasyColumn.SetColor(Value: TColor); begin PaintInfo.Color := Value end; procedure TEasyColumn.SetHotTrack(Value: Boolean); begin PaintInfo.HotTrack := Value end; procedure TEasyColumn.SetImagePosition(Value: TEasyHeaderImagePosition); begin PaintInfo.ImagePosition := Value end; procedure TEasyColumn.SetPaintInfo(Value: TEasyPaintInfoColumn); begin inherited PaintInfo := Value end; procedure TEasyColumn.SetPosition(Value: Integer); var OldPos, i: Integer; begin if Value > OwnerColumns.Count - 1 then Value := OwnerColumns.Count - 1 else if Value < 0 then Value := 0; if OwnerColumns.Count = 1 then FPosition := 0 else begin if Value <> FPosition then begin OldPos := FPosition; if Value > OldPos then begin for i := 0 to OwnerColumns.Count - 1 do begin if (OwnerColumns[i].FPosition >= OldPos) and (OwnerColumns[i].FPosition <= Value) then Dec(OwnerColumns[i].FPosition) end end else begin for i := 0 to OwnerColumns.Count - 1 do begin if (OwnerColumns[i].FPosition >= Value) and (OwnerColumns[i].FPosition <= OldPos) then Inc(OwnerColumns[i].FPosition) end end; FPosition := Value; end; OwnerHeader.Rebuild(False); OwnerHeader.Invalidate(False) end end; procedure TEasyColumn.SetSortDirection(Value: TEasySortDirection); begin if Value <> FSortDirection then begin FSortDirection := Value; OwnerHeader.Invalidate(False); if FSortDirection <> esdNone then begin OwnerListview.Selection.FocusedColumn := Self; if OwnerListview.Sort.AutoSort then OwnerListview.Sort.SortAll end end end; procedure TEasyColumn.SetSortGlpyhAlign(Value: TEasySortGlyphAlign); begin PaintInfo.SortGlyphAlign := Value end; procedure TEasyColumn.SetSortGlyphIndent(Value: Integer); begin PaintInfo.SortGlyphIndent := Value end; procedure TEasyColumn.SetStyle(Value: TEasyHeaderButtonStyle); begin if FStyle <> Value then begin FStyle := Value; Invalidate(False) end end; procedure TEasyColumn.SetWidth(Value: Integer); var R: TRect; begin if FWidth <> Value then begin if Value < 0 then Value := 0; FWidth := Value; OwnerHeader.Rebuild(False); if OwnerListview.View = elsReport then begin // if OwnerHeader.ViewRect.Right > OwnerListview.ClientWidth then begin R := OwnerListview.Scrollbars.ViewRect; R.Right := OwnerHeader.ViewRect.Right; OwnerListview.Scrollbars.SetViewRect(R, True) end; end end end; { TEasyEditManager } function TEasyEditManager.GetEditing: Boolean; begin Result := FEditing or Assigned(TabMoveFocusItem); end; procedure TEasyEditManager.BeginEdit(Item: TEasyItem; Column: TEasyColumn); // // Starts an editor within the passed Item // We create a local message loop and break out of it when any of the normal // conditions are met to stop the edit, such as: Hitting the Escape key, // scrolling with the wheel, clicking out side of the editor and switching // away from the application. // var Msg: TMSG; Pt: TPoint; Allow, Dispatch, EditDone: Boolean; NCHit: Longword; OldFocus: TWinControl; iColumn: Integer; procedure FinishEdit; begin if not EditDone then begin Editor.Hide; FEditing := False; OwnerListview.DoItemEditEnd(Item); Editor.Finalize; FEditItem := nil; FEditFinished := True; EditDone := True end end; function TestAcceptEdit: Boolean; begin Result := Editor.AcceptEdit; if not Result then Editor.SetEditorFocus end; begin if not Editing and not (csDestroying in OwnerListview.ComponentState) then begin EditDone := False; FEditFinished := False; if Assigned(Item) and Enabled then begin Item.MakeVisible(emvAuto); FEditItem := Item; Allow := True; if Assigned(Column) then iColumn := Column.Index else iColumn := 0; OwnerListview.DoItemEditBegin(Item, iColumn, Allow); if (OwnerListview.View = elsReport) and (iColumn < OwnerListview.Header.Columns.Count) then begin OwnerListview.Header.Columns[iColumn].MakeVisible(emvAuto); end else iColumn := 0; if OwnerListview.Header.Columns.Count > iColumn then EditColumn := OwnerListview.Header.Columns[iColumn] else EditColumn := nil; if Allow then begin Application.HookMainWindow(MainWindowHook); AppHooked := True; Editor := nil; OwnerListview.DoItemCreateEditor(Item, FEditor); if Assigned(Editor) then begin OldFocus := Screen.ActiveControl; Editor.Initialize(Item, EditColumn); FEditing := True; Item.Invalidate(True); Editor.Show; Editor.SetEditorFocus; try while not FEditFinished do begin GetMessage(Msg, 0, 0, 0); Dispatch := True; if Msg.message = WM_SETFOCUS then beep; if not FEditFinished then begin if Msg.message = WM_KEYDOWN then begin if Msg.wParam = VK_ESCAPE then FinishEdit end end; // Need to pass the tab to the lsitview if TabMoveFocus is enabled if Msg.message = WM_KEYDOWN then begin // This key combo selects all text in the interface objects, don't allow it to beep if ((GetKeyState(VK_CONTROL) and $8000 <> 0) and ((Msg.wParam = Ord('a')) or (Msg.wParam = Ord('A')))) then begin Editor.SelectAll; Dispatch := False; end; if (Msg.wParam = VK_TAB) and OwnerListview.EditManager.TabMoveFocus then begin if TestAcceptEdit then begin if GetAsyncKeyState(VK_CONTROL) and $8000 <> 0 then begin if OwnerListview.EditManager.TabEditColumns then begin OwnerListview.EditManager.TabMoveFocusColumn := OwnerListview.Header.PrevVisibleColumn(EditColumn); // Stay on the same item if there is another column if Assigned(OwnerListview.EditManager.TabMoveFocusColumn) then OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.EditManager.EditItem else begin OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.Groups.PrevEditableItem(OwnerListview.EditManager.EditItem); OwnerListview.EditManager.TabMoveFocusColumn := OwnerListview.Header.LastColumn; end end else OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.Groups.PrevEditableItem(OwnerListview.EditManager.EditItem); end else begin if OwnerListview.EditManager.TabEditColumns then begin OwnerListview.EditManager.TabMoveFocusColumn := OwnerListview.Header.NextVisibleColumn(EditColumn); // Stay on the same item if there is another column if Assigned(OwnerListview.EditManager.TabMoveFocusColumn) then OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.EditManager.EditItem else OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.Groups.NextEditableItem(OwnerListview.EditManager.EditItem); end else OwnerListview.EditManager.TabMoveFocusItem := OwnerListview.Groups.NextEditableItem(OwnerListview.EditManager.EditItem); end; EndEdit; PostMessage(OwnerListview.Handle, WM_TABMOVEFOCUS, 0, 0); Dispatch := False; end end end; if not FEditFinished then if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_MBUTTONDOWN) or (Msg.message = WM_RBUTTONDOWN) then begin Pt := SmallPointToPoint(TSmallPoint(Msg.lParam)); ClientToScreen(Msg.hwnd, Pt); ScreenToClient(OwnerListview.Handle, Pt); if not Editor.PtInEditControl(Pt) then begin Dispatch := False; if TestAcceptEdit then begin FinishEdit; // Allow the default click action to occur after canceling the edit. Dispatch := True end end; end; if not FEditFinished then begin if (Msg.message = WM_MOUSEWHEEL) or (Msg.message = CM_MOUSEWHEEL) then begin FinishEdit end end; if not FEditFinished then if (Msg.message = WM_NCLBUTTONDOWN) or (Msg.message = WM_NCMBUTTONDOWN) or (Msg.message = WM_NCRBUTTONDOWN) then begin NCHit := SendMessage(Msg.hWnd, WM_NCHITTEST, Msg.wParam, Msg.lParam); if not (NCHit = HTCAPTION) then begin FinishEdit; end end; if not FEditFinished then begin if (Msg.message = WM_HOOKAPPACTIVATE) then begin FinishEdit end end; if Dispatch then begin TranslateMessage(Msg); DispatchMessage(Msg); end; end finally if AppHooked then Application.UnhookMainWindow(MainWindowHook); AppHooked := False; FinishEdit; OldFocus.SetFocus; Editor := nil; EditColumn := nil; end end; end end end; end; constructor TEasyEditManager.Create(AnOwner: TCustomEasyListview); begin inherited; FFont := TFont.Create; Color := clWindow; Font.Assign(AnOwner.Font); AutoEditDelayTime := 300; end; destructor TEasyEditManager.Destroy; begin FreeAndNil(FFont); inherited; end; procedure TEasyEditManager.EndEdit; // // Flags the Edit Manager to stop editing. The local message loop in BeginEdit // alway polls this flag to quit // begin StopAutoEditTimer; if AppHooked and not (csDestroying in OwnerListview.ComponentState) then Application.UnhookMainWindow(MainWindowHook); AppHooked := False; FEditFinished := True end; function TEasyEditManager.MainWindowHook(var Message: TMessage): Boolean; // // Need to hook the Main so we can end the edit if the application is switched // away from // begin Result := False; if Assigned(OwnerListview) then begin if (Message.Msg = WM_ACTIVATEAPP) and OwnerListview.HandleAllocated then PostMessage(OwnerListview.Handle, WM_HOOKAPPACTIVATE, 0, 0) end end; procedure TEasyEditManager.SetEnabled(const Value: Boolean); begin FEnabled := Value; EndEdit; end; procedure TEasyEditManager.SetFont(const Value: TFont); begin Font.Assign(Value) end; procedure TEasyEditManager.StartAutoEditTimer; // // Starts the AutoEditTimer, the timer will be cancelled if the user moves the // mouse a specified distance before the timer elapses // begin StopAutoEditTimer; if Enabled then begin Timer := TTimer.Create(nil); Timer.OnTimer := TimerEvent; Timer.Interval := AutoEditDelayTime; Timer.Enabled := True; FTimerRunning := True end end; procedure TEasyEditManager.TimerEvent(Sender: TObject); // // The Timer Event method. If called the Focused Item will be edited. // begin StopAutoEditTimer; if Assigned(OwnerListview.Selection.FocusedItem) then BeginEdit(OwnerListview.Selection.FocusedItem as TEasyItem, nil) end; procedure TEasyEditManager.StopAutoEditTimer; // // Shuts down the AutoEditTimer // begin if TimerRunning then begin if Assigned(Timer) then FreeAndNil(FTimer); FTimerRunning := False end end; { TEasyEnumFormatEtcManager } function TEasyEnumFormatEtcManager.Clone(out Enum: IEnumFormatEtc): HResult; // Creates a exact copy of the current object. var EnumFormatEtc: TEasyEnumFormatEtcManager; begin Result := S_OK; // Think positive EnumFormatEtc := TEasyEnumFormatEtcManager.Create; // Does not increase COM reference if Assigned(EnumFormatEtc) then begin SetLength(EnumFormatEtc.FFormats, Length(Formats)); // Make copy of Format info Move(FFormats[0], EnumFormatEtc.FFormats[0], Length(Formats) * SizeOf(TFormatEtc)); // Set COM reference to 1 Enum := EnumFormatEtc as IEnumFormatEtc; end else Result := E_UNEXPECTED end; constructor TEasyEnumFormatEtcManager.Create; begin inherited Create; InternalIndex := 0; end; destructor TEasyEnumFormatEtcManager.Destroy; begin inherited; end; function TEasyEnumFormatEtcManager.Next(celt: Integer; out elt; pceltFetched: PLongint): HResult; // Another EnumXXXX function. This function returns the number of objects // requested by the caller in celt. The return buffer, elt, is a pointer to an} // array of, in this case, TFormatEtc structures. The total number of // structures returned is placed in pceltFetched. pceltFetched may be nil if // celt is only asking for one structure at a time. var i: integer; begin if Assigned(Formats) then begin i := 0; while (i < celt) and (InternalIndex < Length(Formats)) do begin TeltArray( elt)[i] := Formats[InternalIndex]; inc(i); inc(FInternalIndex); end; // while if assigned(pceltFetched) then pceltFetched^ := i; if i = celt then Result := S_OK else Result := S_FALSE end else Result := E_UNEXPECTED end; function TEasyEnumFormatEtcManager.Reset: HResult; begin InternalIndex := 0; Result := S_OK end; function TEasyEnumFormatEtcManager.Skip(celt: Integer): HResult; // Allows the caller to skip over unwanted TFormatEtc structures. Simply adds // celt to the index as long as it does not skip past the last structure in // the list. begin if Assigned(Formats) then begin if InternalIndex + celt < Length(Formats) then begin InternalIndex := InternalIndex + celt; Result := S_OK end else Result := S_FALSE end else Result := E_UNEXPECTED end; procedure TEasyDataObjectManager.DoGetCustomFormats(var Formats: TFormatEtcArray); begin if Assigned(Listview) then Listview.DoOLEGetCustomFormats(Formats); end; procedure TEasyDataObjectManager.DoOnGetData(const FormatEtcIn: TFormatEtc; var Medium: TStgMedium; var Handled: Boolean); begin if Assigned(Listview) then Listview.DoOLEGetData(FormatEtcIn, Medium, Handled); end; procedure TEasyDataObjectManager.DoOnQueryGetData(const FormatEtcIn: TFormatEtc; var FormatAvailable: Boolean; var Handled: Boolean); begin if Assigned(Listview) then Listview.DoQueryOLEData(FormatEtcIn, FormatAvailable, Handled); end; procedure TEasyOLEDragManager.ClearDragItem; begin FDragItem := nil end; procedure TEasyOLEDragManager.ClearDropTarget; begin // Unhilight the current Drop Target if Assigned(DropTarget) then begin DropTarget.Hilighted := False; OwnerListview.Groups.InvalidateItem(DropTarget, True); end; FDropTarget := nil; end; constructor TEasyOLEDragManager.Create(AnOwner: TCustomEasyListview); begin inherited; HilightDropTarget := True end; destructor TEasyOLEDragManager.Destroy; begin Registered := False; inherited; end; procedure TEasyOLEDragManager.DefaultImage(Sender: TCustomEasyListview; Image: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); var R: TRect; Bits: TBitmap; begin if Assigned(Image) then begin TransparentColor := OwnerListview.Color; R := Rect(DragStartPt.X - (Image.Width div 2), DragStartPt.Y - (Image.Height div 2), DragStartPt.X + (Image.Width div 2), DragStartPt.Y + (Image.Height div 2)); HotSpot.X := (R.Right - R.Left) div 2; HotSpot.Y := (R.Bottom - R.Top) div 2; if R.Left < 0 then HotSpot.X := HotSpot.X + R.Left; if R.Top < 0 then HotSpot.Y := HotSpot.Y + R.Top; IntersectRect(R, R, OwnerListview.ClientRect); Bits := TBitmap.Create; try Bits.PixelFormat := pf32Bit; Bits.Width := Sender.Width; Bits.Height := Sender.Height; Bits.Canvas.Brush.Color := OwnerListview.Color; Bits.Canvas.FillRect(Rect(0, 0, Sender.Width, Sender.Height)); OwnerListview.DoPaintRect(Bits.Canvas, R, True); BitBlt(Image.Canvas.Handle, 0, 0, Image.Width, Image.Height, Bits.Canvas.Handle, R.Left, R.Top, SRCCOPY); finally Bits.Free; end; Handled := True; end end; procedure TEasyOLEDragManager.DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); var ViewPortPoint: TPoint; Item: TEasyItem; begin if OwnerListview.IsHeaderMouseMsg(PointToSmallPoint(WindowPoint), True) then Effects := cdeNone else begin ViewPortPoint := OwnerListview.Scrollbars.MapWindowToView(WindowPoint); Item := OwnerListview.Groups.ItemByPoint(ViewportPoint); if Assigned(Item) then begin if Item.SelectionHitPt(ViewportPoint, eshtClickSelect) then begin if Item <> DropTarget then ClearDropTarget; FDropTarget := Item; if Assigned(DropTarget) then begin if HilightDropTarget then Item.Hilighted := True; OwnerListview.Groups.InvalidateItem(Item, True) end end else ClearDropTarget end else ClearDropTarget end end; procedure TEasyOLEDragManager.DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin ClearDragItem; ClearDropTarget; FDragTarget := False; end; procedure TEasyOLEDragManager.DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); begin ClearDropTarget; FDragTarget := False; end; procedure TEasyOLEDragManager.DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin FDragTarget := True; end; procedure TEasyOLEDragManager.DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); begin OwnerListview.DoGetDragImage(Bitmap, DragStartPt, HotSpot, TransparentColor, Handled); end; procedure TEasyOLEDragManager.DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); begin OwnerListview.DoOLEDragEnd(ADataObject, DragResult, ResultEffect, KeyStates); DataObject := nil; end; procedure TEasyOLEDragManager.DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); begin OwnerListview.DoOLEDragStart(ADataObject, AvailableEffects, AllowDrag); end; function TEasyOLEDragManager.DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; begin Result := WindowPoint.Y > OwnerListview.ClientHeight - AutoScrollMargin end; function TEasyOLEDragManager.DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; begin Result := WindowPoint.Y - OwnerListview.Header.RuntimeHeight < AutoScrollMargin end; procedure TEasyOLEDragManager.FinalizeDrag(KeyState: TCommonKeyStates); // Does not mean the action actually occured it means that InitializeDrag was // called and this is it matching call. EndDrag means that the drag actually // occured begin inherited; ClearDragItem; end; function TEasyOLEDragManager.InitializeDrag(HitItem: TEasyItem; WindowPoint: TPoint; KeyState: TCommonKeyStates): Boolean; // Does not mean that the action will be a Drag, it just means get ready for one // just in case. begin Result := False; if Enabled then begin if Assigned(HitItem) and ( ((cksLButton in KeyState) and (cmbLeft in MouseButton)) or ((cksMButton in KeyState) and (cmbMiddle in MouseButton)) or ((cksRButton in KeyState) and (cmbRight in MouseButton))) then begin if HitItem.SelectionHitPt(OwnerListview.Scrollbars.MapWindowToView(WindowPoint), eshtClickSelect) then begin FDragItem := HitItem; Result := True end end else FDragItem := nil end end; procedure TEasyOLEDragManager.ImageSize(var Width: Integer; var Height: Integer); begin Width := DragImageWidth; Height := DragImageHeight end; procedure TEasyOLEDragManager.SetEnabled(const Value: Boolean); begin inherited; Registered := Value; end; procedure TEasyOLEDragManager.VCLDragStart; begin FDragItem := OwnerListview.Selection.FocusedItem; if DragMode = dmAutomatic then OwnerListview.BeginDrag(True); end; { TEasySelectionManager } function TEasySelectionManager.GetFocusedColumn: TEasyColumn; begin if not Assigned(FFocusedColumn) then FFocusedColumn := OwnerListview.Header.FirstColumn; Result := FFocusedColumn; end; function TEasySelectionManager.SelectedToArray: TEasyItemArray; var Item: TEasyItem; i: Integer; begin SetLength(Result, Count); Item := First; i := 0; while Assigned(Item) do begin Result[i] := Item; Inc(i); Item := Next(Item) end end; procedure TEasySelectionManager.ActOnAll(SelectType: TEasySelectionType; ExceptItem: TEasyItem); var i, j: Integer; begin if Enabled then begin IncMultiChangeCount; GroupSelectBeginUpdate; try // If unselecting we can optimize for the more common situation by stopping when // there are no more selected items. if SelectType = ecstUnSelect then begin i := 0; while (i < OwnerListview.Groups.Count) and (Count > 0) do begin j := 0; while (j < OwnerListview.Groups[i].Items.Count) and (Count > 0) do begin if ExceptItem <> OwnerListview.Groups[i].Items[j] then OwnerListview.Groups[i].Items[j].Selected := False; Inc(j) end; Inc(i) end end else begin for i := 0 to OwnerListview.Groups.Count - 1 do begin case SelectType of ecstSelect: begin j := 0; while (j < OwnerListview.Groups[i].Items.Count) do begin if ExceptItem <> OwnerListview.Groups[i].Items[j] then OwnerListview.Groups[i].Items[j].Selected := True; Inc(j) end; end; ecstInvert: begin j := 0; while (j < OwnerListview.Groups[i].Items.Count) do begin if ExceptItem <> OwnerListview.Groups[i].Items[j] then OwnerListview.Groups[i].Items[j].Selected := not OwnerListview.Groups[i].Items[j].Selected; Inc(j) end; end; end end end; OwnerListview.DragManager.ClearDragItem; finally GroupSelectEndUpdate; DecMultiChangeCount end end end; procedure TEasySelectionManager.BuildSelectionGroupings(Force: Boolean); // // Builds the necessary information to group the selections like eMule, called // for every selection change. This could get slow with thousands of items. // var i: Integer; GroupList: TEasySelectionGroupList; Group: TEasyGroup; Item, NextItem: TEasyItem; begin // It is possible that during streaming the items can be created but if not (csLoading in OwnerListview.ComponentState) and (Force or (GroupSelections and (FGroupSelectUpdateCount = 0){ and (OwnerListview.UpdateCount = 0) won't work with keyboard})) then begin // Windows.Beep(5000, 200); GroupList := nil; for i := 0 to OwnerListview.Groups.Count - 1 do begin Group := TEasyGroup( OwnerListview.Groups.List[i]); Item := OwnerListview.Groups.FirstVisibleInGroup(Group); while Assigned(Item) do begin // Do a ReleaseSelectionGroup directly for speed if Assigned(Item) and Assigned(Item.SelectionGroup) then begin Item.FSelectionGroup.DecRef; Item.FSelectionGroup := nil end; if (esosSelected in Item.State) then begin NextItem := OwnerListview.Groups.NextVisibleInGroup(Group, Item); // Do a ReleaseSelectionGroup directly for speed if Assigned(NextItem) and Assigned(NextItem.SelectionGroup) then begin NextItem.FSelectionGroup.DecRef; NextItem.FSelectionGroup := nil end; // Direct access for speed while Assigned(NextItem) and (esosSelected in NextItem.State) do begin if not Assigned(GroupList) then begin GroupList := TEasySelectionGroupList.Create; GroupList.Add(Item); GroupList.IncRef; GroupList.DisplayRect := Item.DisplayRect; GroupList.FirstItem := Item; Item.SelectionGroup := GroupList; end; GroupList.Add(NextItem); UnionRect(Item.SelectionGroup.FDisplayRect, Item.SelectionGroup.DisplayRect, NextItem.DisplayRect); GroupList.IncRef; NextItem.SelectionGroup := GroupList; NextItem := OwnerListview.Groups.NextVisibleInGroup(Group, NextItem); end; GroupList := nil; Item := NextItem; end; Item := OwnerListview.Groups.NextVisibleInGroup(Group, Item); end; end end end; procedure TEasySelectionManager.ClearAll; begin ActOnAll(ecstUnSelect, nil); end; procedure TEasySelectionManager.ClearAllExcept(Item: TEasyItem); begin ActOnAll(ecstUnSelect, Item); OwnerListview.DragManager.ClearDragItem; end; constructor TEasySelectionManager.Create(AnOwner: TCustomEasyListview); begin inherited; FEnabled := True; FColor := clHighlight; FBorderColor := clHighlight; FInactiveBorderColor := clInactiveBorder; FInactiveColor := clInactiveBorder; FInactiveTextColor := clBlack; FTextColor := clHighlightText; FRoundRectRadius := 4; FBlendColorSelRect := clHighlight; FBorderColorSelRect := clHighlight; FBlendColorIcon := clHighlight; BlendAlphaImage := 128; BlendAlphaSelRect := 70; BlendAlphaTextRect := 128; FAlphaBlend := False; FUseFocusRect := True; FMouseButton := [cmbLeft]; MouseButtonSelRect := [cmbLeft, cmbRight]; FGradientColorBottom := $FCEFD5; FGradientColorTop := $FDF8F1; FBlendIcon := True end; destructor TEasySelectionManager.Destroy; begin inherited; end; procedure TEasySelectionManager.DecMultiChangeCount; begin Dec(FMultiChangeCount); if MultiChangeCount <= 0 then begin MultiChangeCount := 0; if ItemsToggled > 0 then OwnerListview.DoItemSelectionsChanged end end; procedure TEasySelectionManager.DeleteSelected(SelectPrevItem: Boolean = False); var NextToSelect: Integer; AItem: TEasyItem; begin if Count <> 0 then begin NextToSelect := -1; OwnerListview.BeginUpdate; try if SelectPrevItem then NextToSelect := First.Index - 1; OwnerListview.Groups.DeleteItems(SelectedToArray); finally OwnerListview.EndUpdate; if SelectPrevItem and (OwnerListview.Groups.ItemCount > 0) then begin if NextToSelect < 0 then NextToSelect := 0 else if NextToSelect >= OwnerListview.Groups.ItemCount then NextToSelect := OwnerListview.Groups.ItemCount - 1; AItem := OwnerListview.Items[NextToSelect]; AItem.Selected := True; AItem.Focused := True; end end end end; procedure TEasySelectionManager.DragSelect(KeyStates: TCommonKeyStates); // Handles the selection of items during a drag select operation var CoverR: TRect; Item: TEasyItem; begin if Enabled and MultiSelect then begin IncMultiChangeCount; GroupSelectBeginUpdate; try // Get the rectangle that covers any area that need to be tested for change UnionRect(CoverR, OwnerListview.DragRect.PrevRect, OwnerListview.DragRect.SelectionRect); if not IsRectEmpty(CoverR) then begin Item := OwnerListview.Groups.FirstItemInRect(CoverR); while Assigned(Item) do begin if cksControl in KeyStates then begin if Item.SelectionHit( OwnerListview.DragRect.SelectionRect, eshtDragSelect) xor Item.SelectionHit(OwnerListview.DragRect.PrevRect, eshtDragSelect) then Item.Selected := not Item.Selected; end else begin // First see if we need to select an item if Item.SelectionHit(OwnerListview.DragRect.SelectionRect, eshtDragSelect) then Item.Selected := True else begin // If we did not select the item see if it is in the Previous rectanagle // and it needs to be unselected if Item.SelectionHit(OwnerListview.DragRect.PrevRect, eshtDragSelect) then Item.Selected := False; end end; Item := OwnerListview.Groups.NextItemInRect(Item, CoverR) end end finally GroupSelectEndUpdate; DecMultiChangeCount end end end; function TEasySelectionManager.First: TEasyItem; // // Gets the first Selected item // var Item: TEasyItem; begin Result := nil; Item := OwnerListview.Groups.FirstVisibleItem; while not Assigned(Result) and Assigned(Item) do begin if Item.Selected then Result := Item; Item := OwnerListview.Groups.NextVisibleItem(Item) end end; function TEasySelectionManager.FirstInGroup(Group: TEasyGroup): TEasyItem; // // Gets the first Selected item in the specified group from UIObject list // var Item: TEasyItem; begin Result := nil; Item := OwnerListview.Groups.FirstInGroup(Group); while not Assigned(Result) and Assigned(Item) do begin if Item.Selected then Result := Item; Item := OwnerListview.Groups.NextInGroup(Group, Item) end end; procedure TEasySelectionManager.FocusFirst; var Item: TEasyItem; begin ClearAll; Item := OwnerListview.Groups.FirstItem; if Assigned(Item) and Enabled then Item.Focused := True; end; procedure TEasySelectionManager.GainingSelection(Item: TEasyItem); begin if not MultiSelect then ClearAllExcept(Item); Inc(OwnerListview.Selection.FCount); if not MultiSelect then FocusedItem := Item; Inc(FItemsToggled); NotifyOwnerListview end; function TEasySelectionManager.GetAutoScroll: Boolean; begin Result := OwnerListview.DragRect.AutoScroll end; function TEasySelectionManager.GetAutoScrollAccelerator: Byte; begin Result := OwnerListview.DragRect.AutoScrollAccelerator end; function TEasySelectionManager.GetAutoScrollDelay: Integer; begin Result := OwnerListview.DragRect.AutoScrollDelay end; function TEasySelectionManager.GetAutoScrollMargin: Integer; begin Result := OwnerListview.DragRect.AutoScrollMargin end; function TEasySelectionManager.GetAutoScrollTime: Integer; begin Result := OwnerListview.DragRect.AutoScrollTime end; function TEasySelectionManager.GetEnableDragSelect: Boolean; begin Result := OwnerListview.DragRect.Enabled end; function TEasySelectionManager.GeTCommonMouseButton: TCommonMouseButtons; begin Result := FMouseButton end; function TEasySelectionManager.GetMouseButtonSelRect: TCommonMouseButtons; begin Result := OwnerListview.DragRect.MouseButton end; function TEasySelectionManager.GetSelecting: Boolean; begin Result := OwnerListview.DragRect.Dragging end; procedure TEasySelectionManager.GroupSelectBeginUpdate; begin Inc(FGroupSelectUpdateCount) end; procedure TEasySelectionManager.GroupSelectEndUpdate; begin Dec(FGroupSelectUpdateCount); if FGroupSelectUpdateCount <= 0 then begin FGroupSelectUpdateCount := 0; // OwnerListview.Groups.ReIndexItems(nil, True); BuildSelectionGroupings(False); end end; procedure TEasySelectionManager.IncMultiChangeCount; begin if MultiChangeCount = 0 then ItemsToggled := 0; Inc(FMultiChangeCount) end; procedure TEasySelectionManager.InvalidateVisibleSelected(ValidateWindow: Boolean); var Item: TEasyItem; begin if Enabled then begin Item := OwnerListview.Groups.FirstItemInRect(OwnerListview.ClientRect); while Assigned(Item) do begin if Item.Selected or Item.Focused then Item.Invalidate(False); Item := OwnerListview.Groups.NextItemInRect(Item, OwnerListview.ClientRect) end end end; procedure TEasySelectionManager.Invert; begin ActOnAll(ecstInvert, nil); end; procedure TEasySelectionManager.LosingSelection(Item: TEasyItem); begin Dec(OwnerListview.Selection.FCount); Item.ReleaseSelectionGroup; Inc(FItemsToggled); NotifyOwnerListview end; procedure TEasySelectionManager.NotifyOwnerListview; begin if (MultiChangeCount = 0) and (ItemsToggled > 0) then begin OwnerListview.DoItemSelectionsChanged; ItemsToggled := 0 end end; procedure TEasySelectionManager.SelectAll; begin if MultiSelect then ActOnAll(ecstSelect, nil); end; function TEasySelectionManager.Next(Item: TEasyItem): TEasyItem; // // Gets the next Selected item in the UIObject list // begin Result := nil; Item := OwnerListview.Groups.NextVisibleItem(Item); while not Assigned(Result) and Assigned(Item) do begin if Item.Selected then Result := Item; Item := OwnerListview.Groups.NextVisibleItem(Item) end end; function TEasySelectionManager.NextInGroup(Group: TEasyGroup; Item: TEasyItem): TEasyItem; // // Gets the next Selected item in the specified group from UIObject list // begin Result := nil; Item := OwnerListview.Groups.NextInGroup(Group, Item); while not Assigned(Result) and Assigned(Item) do begin if Item.Selected then Result := Item; Item := OwnerListview.Groups.NextInGroup(Group, Item) end end; procedure TEasySelectionManager.SelectFirst; var Item: TEasyItem; begin ClearAll; Item := OwnerListview.Groups.FirstItem; if Assigned(Item) and Enabled then begin Item.Focused := True; Item.Selected := True end end; procedure TEasySelectionManager.SelectGroupItems(Group: TEasyGroup; ClearOtherItems: Boolean); var i, j: Integer; begin if Enabled and MultiSelect and Assigned(Group) then begin IncMultiChangeCount; GroupSelectBeginUpdate; try if ClearOtherItems then begin for i := 0 to OwnerListview.Groups.Count - 1 do begin if OwnerListview.Groups[i] <> Group then for j := 0 to OwnerListview.Groups[i].Items.Count - 1 do OwnerListview.Groups[i].Items[j].Selected := False; end; end; for i := 0 to Group.Items.Count - 1 do Group.Items[i].Selected := True finally GroupSelectEndUpdate; DecMultiChangeCount end end end; procedure TEasySelectionManager.SelectRange(FromItem, ToItem: TEasyItem; RectSelect: Boolean; ClearFirst: Boolean); procedure SwapItems(var Item1, Item2: TEasyItem); var Temp: TEasyItem; begin Temp := Item1; Item1 := Item2; Item2 := Temp end; var R: TRect; begin if Enabled and MultiSelect then begin IncMultiChangeCount; GroupSelectBeginUpdate; try if ClearFirst then ClearAll; if Assigned(FromItem) and Assigned(ToItem) then begin if RectSelect then begin UnionRect(R, FromItem.DisplayRect, ToItem.DisplayRect); SelectRect(R, False); end else begin if FromItem.OwnerGroup = ToItem.OwnerGroup then begin if FromItem.Index > ToItem.Index then SwapItems(FromItem, ToItem) end else begin if FromItem.OwnerGroup.Index > ToItem.OwnerGroup.Index then SwapItems(FromItem, ToItem) end; while Assigned(FromItem) and (FromItem <> ToItem) do begin FromItem.Selected := True; FromItem := OwnerListview.Groups.NextVisibleItem(FromItem) end; ToItem.Selected := True; end end finally GroupSelectEndUpdate; DecMultiChangeCount end end end; procedure TEasySelectionManager.SelectRect(ViewportSelRect: TRect; ClearFirst: Boolean); var Temp: TEasyItem; begin if Enabled and MultiSelect then begin GroupSelectBeginUpdate; IncMultiChangeCount; try if ClearFirst then ClearAll; Temp := OwnerListview.Groups.FirstItemInRect(ViewportSelRect); while Assigned(Temp) do begin Temp.Selected := True; Temp := OwnerListview.Groups.NextItemInRect(Temp, ViewportSelRect); end finally GroupSelectEndUpdate; DecMultiChangeCount end end end; procedure TEasySelectionManager.SetAnchorItem(Value: TEasyItem); begin if Assigned(Value) then begin if Value.Visible and Value.Enabled then FAnchorItem := Value; end else FAnchorItem := nil end; procedure TEasySelectionManager.SetAutoScroll(Value: Boolean); begin OwnerListview.DragRect.AutoScroll := Value end; procedure TEasySelectionManager.SetAutoScrollAccelerator(Value: Byte); begin OwnerListview.DragRect.AutoScrollAccelerator := Value end; procedure TEasySelectionManager.SetAutoScrollDelay(Value: Integer); begin OwnerListview.DragRect.AutoScrollDelay := Value end; procedure TEasySelectionManager.SetAutoScrollMargin(Value: Integer); begin OwnerListview.DragRect.AutoScrollMargin := Value end; procedure TEasySelectionManager.SetAutoScrollTime(Value: Integer); begin OwnerListview.DragRect.AutoScrollTime := Value end; procedure TEasySelectionManager.SetBlendIcon(Value: Boolean); begin if FBlendIcon <> Value then begin FBlendIcon := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetBlurAlphaBkGnd(const Value: Boolean); begin if FBlurAlphaBkGnd <> Value then begin FBlurAlphaBkGnd := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetEnabled(const Value: Boolean); begin if FEnabled <> Value then begin if not Value then ClearAll; FEnabled := Value; end; end; procedure TEasySelectionManager.SetEnableDragSelect(Value: Boolean); begin OwnerListview.DragRect.Enabled := Value end; procedure TEasySelectionManager.SetFocusedColumn(Value: TEasyColumn); var OldFocused: TEasyColumn; begin if FFocusedColumn <> Value then begin OldFocused := FFocusedColumn; FFocusedColumn := Value; if Assigned(FFocusedColumn) then FFocusedColumn.Invalidate(True); if Assigned(OldFocused) then OldFocused.Invalidate(True); end end; procedure TEasySelectionManager.SetFocusedGroup(const Value: TEasyGroup); //var // ChangeFocus: Boolean; // OldGroup: TEasyGroup; begin // OldGroup := FFocusedGroup; (* if Assigned(Value) then begin if Value.Visible and Value.Enabled then begin if FFocusedGroup <> Value then begin if Assigned(OldGroup) then OldGroup.Focused := False; ChangeFocus := True; // The user may not have allowed the focus to change if Assigned(OldGroup) then ChangeFocus := not OldGroup.Focused; if ChangeFocus then begin Value.Focused := True; FFocusedGroup := Value end end end end else begin FFocusedGroup := nil; if Assigned(OldGroup) then OldGroup.Focused := False; end *) end; procedure TEasySelectionManager.SetFocusedItem(Value: TEasyItem); var ChangeFocus: Boolean; OldItem: TEasyCollectionItem; RectArray: TEasyRectArrayObject; begin OldItem := FFocusedItem; if Assigned(Value) then begin if Value.Visible and Value.Enabled then begin if FFocusedItem <> Value then begin if Assigned(OldItem) then OldItem.Focused := False; ChangeFocus := True; // The user may not have allowed the focus to change if Assigned(OldItem) then ChangeFocus := not OldItem.Focused; if ChangeFocus then begin FFocusedItem := Value; // Resize the Groups in case the full focus text was bigger than // the group Value.Focused := True; // During Deletion this can lead to weird recurssion if not Value.Destroying then begin Value.ItemRectArray(nil, OwnerListview.ScratchCanvas, RectArray); // Rebuild the grid if the focused text will overlap the bottom of the // group if RectArray.FullTextRect.Bottom > Value.OwnerGroup.ClientRect.Bottom then Value.OwnerListview.Groups.Rebuild(True); end end end end end else begin FFocusedItem := nil; if Assigned(OldItem) then begin if Assigned(OldItem) then begin OldItem.Focused := False; // Resize the Groups in case the full focus text was bigger than // the group // During Deletion this can lead to weird recurssion if not OldItem.Destroying then begin (* OwnerListview.Grid.CacheGroupInfo; OwnerListview.Scrollbars.SetViewRect(OwnerListview.Grid.ViewRect, True); *) end end end end end; procedure TEasySelectionManager.SeTCommonMouseButton(Value: TCommonMouseButtons); begin FMouseButton := Value end; procedure TEasySelectionManager.SetFullCellPaint(Value: Boolean); begin if Value <> FFullCellPaint then begin FFullCellPaint := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetFullItemPaint(Value: Boolean); begin if Value <> FFullItemPaint then begin FFullItemPaint := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetGradient(const Value: Boolean); begin if FGradient <> Value then begin FGradient := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetGradientColorBottom(const Value: TColor); begin if FGradientColorBottom <> Value then begin FGradientColorBottom := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetGradientColorTop(const Value: TColor); begin if FGradientColorTop <> Value then begin FGradientColorTop := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasySelectionManager.SetGroupSelections(Value: Boolean); begin if Value <> FGroupSelections then begin OwnerListview.BeginUpdate; try FGroupSelections := Value; BuildSelectionGroupings(True) finally OwnerListview.EndUpdate end end end; procedure TEasySelectionManager.SetMouseButtonSelRect(Value: TCommonMouseButtons); begin OwnerListview.DragRect.MouseButton := Value end; procedure TEasySelectionManager.SetMultiSelect(const Value: Boolean); begin if FMultiSelect <> Value then begin FMultiSelect := Value; ClearAll end end; { TEasyCheckManager } function TEasyCheckManager.CheckedToArray: TEasyItemArray; var Item: TEasyItem; i: Integer; begin SetLength(Result, Count); Item := First; i := 0; while Assigned(Item) do begin Result[i] := Item; Inc(i); Item := Next(Item) end end; procedure TEasyCheckManager.CheckAll; // // Checks all the Visible items in the EasyControl // var i: Integer; begin for i := 0 to OwnerListview.Groups.Count - 1 do OwnerListview.Groups.Groups[i].Checked := True end; procedure TEasyCheckManager.CheckAllInGroup(Group: TEasyGroup); // // Checks all the Visible items in a particular group // begin Group.Checked := True end; function TEasyCheckManager.First: TEasyItem; // // Gets the first checked item in the control and prepares for the GetNext iteration // //var // Found: Boolean; // i: Integer; begin // Found := False; // i := 0; (* while (i < OwnerListview.UIObjects.ItemCount) and not Found do begin Result := OwnerListview.UIObjects.Items[i]; Found := Result.Checked; if not Found then Inc(i) end; if not Found then *) Result := nil; end; function TEasyCheckManager.FirstInGroup(Group: TEasyGroup): TEasyCollectionItem; // // Gets the first checked item in a particular grouip and prepares for the GetNextInGroup iteration // var Found: Boolean; i: Integer; begin Result := nil; Exit; Found := False; i := 0; while (i < Group.Items.Count) and not Found do begin Result := Group.Items[i]; // By definition if the item is checked is must be visible Found := Result.Checked; if not Found then Inc(i) end; if not Found then Result := nil; end; function TEasyCheckManager.Next(Item: TEasyItem): TEasyItem; // // Gets the next checked item in the control, depends on GetFirst to be called first // //var // Found: Boolean; // i: Integer; begin // Found := False; (* i := Item.VisibleIndex; Inc(i); while (i < OwnerListview.UIObjects.ItemCount) and not Found do begin Result := OwnerListview.UIObjects.Items[i]; Found := Result.Checked; if not Found then Inc(i) end; if not Found then *) Result := nil; end; function TEasyCheckManager.NextInGroup(Item: TEasyItem): TEasyItem; // // Gets the next checked item in a particular group, depends on GetFirstInGroup to be called first // begin Result := nil; Assert(True = False, 'TEasyCheckManager.GetNextCheckedInGroup not implemented yet'); Exit; end; procedure TEasyCheckManager.DeleteChecked; var Items: TEasyItemArray; i: Integer; begin OwnerListview.BeginUpdate; try Items := CheckedToArray; // Set the item in the list to nil and free the item try for i := 0 to Length(Items) - 1 do begin Items[i].OwnerGroup.Items[Items[i].Index] := nil; Items[i].Free; end; finally // now pack the group lists to elimiate the nil pointers for i := 0 to OwnerListview.Groups.Count - 1 do OwnerListview.Groups[i].Items.FList.Pack; end; finally OwnerListview.EndUpdate; end end; procedure TEasyCheckManager.SetPendingObject(Value: TEasyCollectionItem); begin if Value <> FPendingObject then begin if Assigned(FPendingObject) then FPendingObject.CheckPending := False; FPendingObject := Value; if Assigned(FPendingObject) then FPendingObject.CheckPending := True; end end; procedure TEasyCheckManager.UnCheckAll; // // Unchecks all Visible items in the control // var i: Integer; begin OwnerListview.BeginUpdate; try for i := 0 to OwnerListview.Groups.Count - 1 do OwnerListview.Groups.Groups[i].Checked := False; finally OwnerListview.EndUpdate; end end; procedure TEasyCheckManager.UnCheckAllInGroup(Group: TEasyGroup); // // Unchecks all Visible items in a particular group // begin OwnerListview.BeginUpdate; try Group.Checked := False finally OwnerListview.EndUpdate; end end; { TEasyScrollbarManager } constructor TEasyScrollbarManager.Create(AnOwner: TCustomEasyListview); begin inherited; FHorzEnabled := True; FVertEnabled := True; FSnapHorzView := True; end; destructor TEasyScrollbarManager.Destroy; begin inherited; end; function TEasyScrollbarManager.GetHorzBarVisible: Boolean; begin if Assigned(OwnerListview) and OwnerListview.HandleAllocated then Result := GetWindowLong(OwnerListview.Handle, GWL_STYLE) and WS_HSCROLL <> 0 else Result := False; end; function TEasyScrollbarManager.GetLine: Integer; begin Result := OwnerListview.Groups.CellHeight end; function TEasyScrollbarManager.GetMaxOffsetX: Integer; var ScrollTmp: Integer; begin Result := ViewWidth - OwnerListview.ClientWidth; if (not OwnerListview.IsVertView) and (HorzBarVisible) then begin ScrollTmp := Result - (Result mod OwnerListview.CellSizes.List.Width); Result := ScrollTmp + OwnerListview.CellSizes.List.Width; end; if Result < 0 then Result := 0; end; function TEasyScrollbarManager.GetMaxOffsetY: Integer; begin Result := ViewHeight - OwnerListview.ClientHeight + OwnerListview.Header.RuntimeHeight {+ OwnerListview.Columns.Footer.SizeTotal}; if Result < 0 then Result := 0; end; function TEasyScrollbarManager.GetVertBarVisible: Boolean; begin if Assigned(OwnerListview) and OwnerListview.HandleAllocated then Result := GetWindowLong(OwnerListview.Handle, GWL_STYLE) and WS_VSCROLL <> 0 else Result := False; end; function TEasyScrollbarManager.GetViewHeight: Integer; begin Result := ViewRect.Bottom - ViewRect.Top end; function TEasyScrollbarManager.GetViewWidth: Integer; begin Result := ViewRect.Right - ViewRect.Left end; function TEasyScrollbarManager.MapViewToWindow(ViewportPoint: TPoint; AccountForHeader: Boolean = True): TPoint; begin Result.X := ViewportPoint.X - OffsetX; Result.Y := ViewportPoint.Y - OffsetY; if AccountForHeader then Inc(Result.Y, OwnerListview.Header.RuntimeHeight) end; function TEasyScrollbarManager.MapViewRectToWindowRect(ViewPortRect: TRect; AccountForHeader: Boolean = True): TRect; begin Result.TopLeft := MapViewToWindow(ViewPortrect.TopLeft, AccountForHeader); Result.BottomRight := MapViewToWindow(ViewPortRect.BottomRight, AccountForHeader); end; function TEasyScrollbarManager.MapViewToWindow(ViewportPoint: TSmallPoint; AccountForHeader: Boolean = True): TPoint; begin Result := MapViewToWindow(SmallPointToPoint(ViewportPoint), AccountForHeader) end; function TEasyScrollbarManager.MapWindowToView(WindowPoint: TPoint; AccountForHeader: Boolean = True): TPoint; begin Result.X := WindowPoint.X + OffsetX; Result.Y := WindowPoint.Y + OffsetY; if AccountForHeader then Dec(Result.Y, OwnerListview.Header.RuntimeHeight) end; function TEasyScrollbarManager.MapWindowRectToViewRect(WindowRect: TRect; AccountForHeader: Boolean = True): TRect; begin Result.TopLeft := MapWindowToView(WindowRect.TopLeft, AccountForHeader); Result.BottomRight := MapWindowToView(WindowRect.BottomRight, AccountForHeader); end; function TEasyScrollbarManager.MapWindowToView(WindowPoint: TSmallPoint; AccountForHeader: Boolean = True): TPoint; begin Result := MapWindowToView(SmallPointToPoint(WindowPoint), AccountForHeader); end; procedure TEasyScrollbarManager.ReCalculateScrollbars(Redraw: Boolean; Force: Boolean); const ALL_SCROLLFLAGS = SIF_PAGE or SIF_POS or SIF_RANGE; var Info: TScrollInfo; HorzWasVisible, VertWasVisible, HorzNeeded, VertNeeded, RebuildNeeded: Boolean; R: TRect; begin // Performance hit if not checking for update. if not Rebuilding and (Assigned(OwnerListview) and OwnerListview.HandleAllocated) and ((OwnerListview.UpdateCount = 0) or Force) then begin FRebuilding := True; HorzWasVisible := False; VertWasVisible := False; try // If the window is resizing our offset may become invalid and we need to // "pull" the offset with the resize ValidateOffsets(FOffsetX, FOffsetY); HorzWasVisible := HorzBarVisible; HorzNeeded := (ViewWidth - 1 > OwnerListview.ClientWidth) and (OwnerListview.Height > GetSystemMetrics(SM_CYHSCROLL)); VertWasVisible := VertBarVisible; VertNeeded := (ViewHeight + OwnerListview.Header.RuntimeHeight - 1 > OwnerListview.ClientHeight) and (OwnerListview.Width > GetSystemMetrics(SM_CYVSCROLL)); GetClientRect(OwnerListview.Handle, R); RebuildNeeded := False; if HorzEnabled then begin if HorzWasVisible xor HorzNeeded then begin ShowScrollBar(OwnerListview.Handle, SB_HORZ, HorzNeeded); RebuildNeeded := True; end end else ShowScrollBar(OwnerListview.Handle, SB_HORZ, False); if VertEnabled then begin if VertWasVisible xor VertNeeded then begin ShowScrollBar(OwnerListview.Handle, SB_VERT, VertNeeded); RebuildNeeded := True; end; end else ShowScrollBar(OwnerListview.Handle, SB_VERT, False);; if RebuildNeeded then OwnerListview.Groups.Rebuild(True); FillChar(Info, SizeOf(Info), #0); Info.cbSize := SizeOf(Info); Info.fMask := ALL_SCROLLFLAGS; Info.nMin := 0; if VertEnabled and VertBarVisible then begin Info.nMax := ViewHeight + OwnerListview.Header.RuntimeHeight - 1; Info.nPos := Abs(OffsetY); if OwnerListview.ClientHeight < 0 then Info.nPage := 0 else Info.nPage := OwnerListview.ClientHeight; end else begin Info.nMax := 0; Info.nPos := 0; Info.nPage := 0; end; SetScrollInfo(OwnerListview.Handle, SB_VERT, Info, Redraw); FillChar(Info, SizeOf(Info), #0); Info.cbSize := SizeOf(Info); Info.fMask := ALL_SCROLLFLAGS; Info.nMin := 0; if HorzEnabled and HorzBarVisible then begin Info.nMax := ViewWidth - 1; Info.nPos := Abs(OffsetX); if OwnerListview.ClientWidth < 0 then Info.nPage := 0 else Info.nPage := OwnerListview.ClientWidth; end else begin Info.nMax := 0; Info.nPos := 0; Info.nPage := 0; end; SetScrollInfo(OwnerListview.Handle, SB_HORZ, Info, Redraw); // If the window is resizing our offset may become invalid and we need to // "pull" the offset with the resize ValidateOffsets(FOffsetX, FOffsetY); finally FRebuilding := False; if (not HorzWasVisible and HorzBarVisible) or (not VertWasVisible and VertBarVisible) then RedrawWindow(OwnerListview.Handle, nil, 0, RDW_FRAME or RDW_INVALIDATE or RDW_ERASENOW); end end end; procedure TEasyScrollbarManager.SetHorzEnabled( const Value: Boolean); begin if FHorzEnabled <> Value then begin FHorzEnabled := Value; ReCalculateScrollbars(True, False); OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyScrollbarManager.SetOffsetX(const Value: Integer); begin if FOffsetX <> Value then Scroll(Value - OffsetX, 0); end; procedure TEasyScrollbarManager.SetOffsetY(const Value: Integer); begin if FOffsetY <> Value then Scroll(0, Value - OffsetY); end; procedure TEasyScrollbarManager.SetVertEnabled( const Value: Boolean); begin if FVertEnabled <> Value then begin FVertEnabled := Value; ReCalculateScrollbars(True, False); OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyScrollbarManager.SetViewRect(AViewRect: TRect; InvalidateWindow: Boolean); var WasX, WasY: Boolean; begin if not EqualRect(AViewRect, FViewRect) then begin WasX := HorzBarVisible; WasY := VertBarVisible; FViewRect := AViewRect; ReCalculateScrollbars(True, False); if (InvalidateWindow or (WasX and not HorzBarVisible) or (WasY and not VertBarVisible)) then OwnerListview.SafeInvalidateRect(nil, False); end else if InvalidateWindow then OwnerListview.SafeInvalidateRect(nil, False); end; procedure TEasyScrollbarManager.ValidateOffsets(var AnOffsetX, AnOffsetY: Integer); // "Pulls" the offset to keep in sync with the client window. This is especially // for when the window is resizing and the offset is near the bottom of the page. // Without this the Scroll Manager could detect that the scrollbars are not needed // any more and hide them leaving the window scrolled to the last known point! var LastCol: Boolean; begin if Assigned(OwnerListview) then begin if SnapHorzView and not OwnerListview.IsVertView then begin LastCol := AnOffsetX > ViewWidth - OwnerListview.CellSizes.List.Width; if AnOffsetX mod OwnerListview.CellSizes.List.Width <> 0 then AnOffsetX := OwnerListview.CellSizes.List.Width * (AnOffsetX div OwnerListview.CellSizes.List.Width); if (AnOffsetX mod OwnerListview.CellSizes.List.Width > OwnerListview.CellSizes.List.Width div 2) or LastCol then AnOffsetX := AnOffsetX + OwnerListview.CellSizes.List.Width end; if AnOffsetY > MaxOffsetY then AnOffsetY := MaxOffsetY; if AnOffsetX > MaxOffsetX then AnOffsetX := MaxOffsetX; if AnOffsetY < 0 then AnOffsetY := 0; if AnOffsetX < 0 then AnOffsetX := 0; end else begin AnOffsetX := 0; AnOffsetY := 0 end end; function TEasyScrollbarManager.ViewableViewportRect: TRect; // // Returns, in Viewport Coordinates, the rectangle that is current visible to // the user in the window. // begin Result := MapWindowRectToViewRect(OwnerListview.ClientRect) end; procedure TEasyScrollbarManager.WMHScroll(var Msg: TWMVScroll); // Called from the WM_HSCROLL message of the owner window to implement the scroll var Info: TScrollInfo; ClientR: TRect; DeltaX: Integer; begin if Assigned(OwnerListview) then begin DeltaX := 0; // Get the 32 Bit Position FillChar(Info, SizeOf(Info), #0); Info.cbSize := SizeOf(Info); Info.fMask := SIF_POS or SIF_TRACKPOS; GetScrollInfo(OwnerListview.Handle, SB_HORZ, Info); ClientR :=OwnerListview.ClientRect; if not OwnerListview.IsVertView and SnapHorzView then begin case Msg.ScrollCode of SB_BOTTOM: DeltaX := (ViewRect.Right - ViewRect.Left) - OffsetX; SB_ENDSCROLL: DeltaX := 0; SB_LINEDOWN: DeltaX := OwnerListview.CellSizes.List.Width; SB_LINEUP: DeltaX := -OwnerListview.CellSizes.List.Width; SB_PAGEDOWN: DeltaX := OwnerListview.CellSizes.List.Width; SB_PAGEUP: DeltaX := -OwnerListview.CellSizes.List.Width; SB_THUMBPOSITION: begin DeltaX := Info.nPos - OffsetX; DeltaX := (DeltaX - (DeltaX mod OwnerListview.CellSizes.List.Width)); end; SB_THUMBTRACK: begin DeltaX := Info.nTrackPos - OffsetX; if ((MaxOffsetX - Info.nTrackPos) < OwnerListview.CellSizes.List.Width) then DeltaX := MaxOffsetX else DeltaX := (DeltaX - (DeltaX mod OwnerListview.CellSizes.List.Width)); end; SB_TOP: DeltaX := -(ViewRect.Right - ViewRect.Left) - OffsetX; end // case end else begin case Msg.ScrollCode of SB_BOTTOM: DeltaX := (ViewRect.Right - ViewRect.Left) - OffsetX; SB_ENDSCROLL: DeltaX := 0; SB_LINEDOWN: DeltaX := Line; SB_LINEUP: DeltaX := -Line; SB_PAGEDOWN: DeltaX := ClientR.Right - ClientR.Left; SB_PAGEUP: DeltaX := -(ClientR.Right - ClientR.Left); SB_THUMBPOSITION: DeltaX := Info.nTrackPos - OffsetX; SB_THUMBTRACK: DeltaX := Info.nTrackPos - OffsetX; SB_TOP: DeltaX := -OffsetY end; end; Scroll(DeltaX, 0); end else OffsetX := 0 end; procedure TEasyScrollbarManager.WMKeyDown(var Msg: TWMKeyDown); // Call from the WM_KEYDOWN message of the owner window to check for keys that // are related to scrolling the window var NewMsg: TWMScroll; SkipScroll: Boolean; begin FillChar(NewMsg, SizeOf(NewMsg), #0); SkipScroll := False; case Msg.CharCode of VK_HOME: NewMsg.ScrollCode := SB_TOP; VK_END: NewMsg.ScrollCode := SB_BOTTOM; VK_NEXT: NewMsg.ScrollCode := SB_PAGEDOWN; VK_PRIOR: NewMsg.ScrollCode := SB_PAGEUP; VK_UP: NewMsg.ScrollCode := SB_LINEUP; VK_DOWN: NewMsg.ScrollCode := SB_LINEDOWN; VK_LEFT: NewMsg.ScrollCode := SB_LINEUP; VK_RIGHT: NewMsg.ScrollCode := SB_LINEDOWN; else SkipScroll := True; end; if not SkipScroll then begin if Msg.CharCode in [VK_LEFT, VK_RIGHT] then WMHScroll(NewMsg) else WMVScroll(NewMsg) end end; procedure TEasyScrollbarManager.WMVScroll(var Msg: TWMVScroll); // Call from the WM_VSCROLL message of the owner window to implement the scroll var Info: TScrollInfo; ClientR: TRect; DeltaY: Integer; begin if Assigned(OwnerListview) then begin DeltaY := 0; // Get the 32 Bit Position FillChar(Info, SizeOf(Info), #0); Info.cbSize := SizeOf(Info); Info.fMask := SIF_TRACKPOS; GetScrollInfo(OwnerListview.Handle, SB_VERT, Info); ClientR := OwnerListview.ClientRect; case Msg.ScrollCode of SB_BOTTOM: DeltaY := (ViewRect.Bottom - ViewRect.Top) - OffsetY; SB_ENDSCROLL: DeltaY := 0; SB_LINEDOWN: DeltaY := Line; SB_LINEUP: DeltaY := -Line; SB_PAGEDOWN: DeltaY := (ClientR.Bottom - ClientR.Top); SB_PAGEUP: DeltaY := -(ClientR.Bottom - ClientR.Top); SB_THUMBPOSITION: DeltaY := Info.nTrackPos - OffsetY; SB_THUMBTRACK: DeltaY := Info.nTrackPos - OffsetY; SB_TOP: DeltaY := -OffsetY; end; Scroll(0, DeltaY); end else OffsetY := 0 end; procedure TEasyScrollbarManager.Scroll(DeltaX, DeltaY: Integer); var OldOffsetX, OldOffsetY: Integer; begin OldOffsetY := OffsetY; OldOffsetX := OffsetX; FOffsetX := OffsetX + DeltaX; FOffsetY := OffsetY + DeltaY; ValidateOffsets(FOffsetX, FOffsetY); if (OffsetX <> OldOffsetX) or (OffsetY <> OldOffsetY) then begin ReCalculateScrollbars(True, True); OwnerListview.DoScroll(OldOffsetX - FOffsetX, OldOffsetY - FOffsetY); OwnerListview.SafeInvalidateRect(nil, False); end end; { TEasyBackgroundManager } procedure TEasyBackgroundManager.Assign(Source: TPersistent); var ASource: TEasyBackgroundManager; begin if Source is TEasyBackgroundManager then begin ASource := TEasyBackgroundManager(Source); Image.Assign(ASource.Image); FEnabled := ASource.Enabled; FOffsetX := ASource.OffsetX; FOffsetY := ASource.OffsetY; FTile := ASource.Tile; end end; procedure TEasyBackgroundManager.AssignTo(Target: TPersistent); var ATarget: TEasyBackgroundManager; begin if Target is TEasyBackgroundManager then begin ATarget := TEasyBackgroundManager(Target); ATarget.Image.Assign(Image); ATarget.FEnabled := Enabled; ATarget.FOffsetX := OffsetX; ATarget.FOffsetY := OffsetY; ATarget.FTile := Tile; end end; procedure TEasyBackgroundManager.ChangeBitmapBits(Sender: TObject); begin Image.PixelFormat := pf32Bit; AlphaImage.PixelFormat := pf32Bit; OwnerListview.SafeInvalidateRect(nil, False); end; constructor TEasyBackgroundManager.Create(AnOwner: TCustomEasyListview); begin inherited; FImage := TBitmap.Create; FImage.PixelFormat := pf32Bit; FImage.OnChange := ChangeBitmapBits; FAlphaImage := TBitmap.Create; FAlphaImage.PixelFormat := pf32Bit; FAlphaImage.OnChange := ChangeBitmapBits; FTile := True; FOffsetX := 0; FOffsetY := 0; FBlendMode := cbmConstantAlphaAndColor; FBlendAlpha := 128; FAlphaBlend := False; FCaptionAlignment := taCenter; FCaptionVAlignment := cvaCenter; FCaptionSingleLine := True; FCaptionShowOnlyWhenEmpty := True; FAlphaBlender := TEasyAlphaBlender.Create; end; destructor TEasyBackgroundManager.Destroy; begin FImage.OnChange := nil; FreeAndNil(FImage); FreeAndNil(FAlphaImage); FreeAndNil(FAlphaBlender); inherited; end; procedure TEasyBackgroundManager.PaintTo(ACanvas: TCanvas; ARect: TRect; PaintDefault: Boolean); var Row, Column, X, Y: Integer; BkGndR, TempR: TRect; OldOrigin: TPoint; Bitmap: TBitmap; DrawTextFlags: TCommonDrawTextWFlags; ShowCaption, DoDefault: Boolean; begin DoDefault := True; OwnerListview.DoPaintBkGnd(ACanvas, ARect, AlphaBlender, DoDefault); if DoDefault then begin if Assigned(Image) and not Image.Empty and Enabled then begin ACanvas.Brush.Color := OwnerListview.Color; ACanvas.FillRect(ARect); if AlphaBlend and HasMMX then begin Bitmap := TBitmap.Create; Bitmap.Width := Image.Width; Bitmap.Height := Image.Height; Bitmap.PixelFormat := pf32Bit; Bitmap.Assign(Image); if BlendMode = cbmConstantAlphaAndColor then MPCommonUtilities.AlphaBlend(0, Bitmap.Canvas.Handle, Rect(0, 0, Bitmap.Width, Bitmap.Height), Point(0, 0), BlendMode, BlendAlpha, ColorToRGB(OwnerListview.Color)) else if (Image.Width = AlphaImage.Width) and (Image.Height = AlphaImage.Height) then // AlphaBlend it with the background bitmap MPCommonUtilities.AlphaBlend(AlphaImage.Canvas.Handle, Bitmap.Canvas.Handle, Rect(0, 0, Bitmap.Width, Bitmap.Height), Point(0, 0), BlendMode, BlendAlpha, ColorToRGB(OwnerListview.Color)); end else Bitmap := Image; Bitmap.Canvas.Lock; try // Needed to make IntersectRect work correctly. InflateRect(ARect, Bitmap.Width, Bitmap.Height); if Tile then begin // Need to keep BitBlt from needing negative numbers. It will not work with them X := OffsetX mod Bitmap.Width; if OffsetX > 0 then X := -(Bitmap.Width - X); Y := OffsetY mod Bitmap.Height; if OffsetY > 0 then Y := -(Bitmap.Height - Y); SetViewportOrgEx(ACanvas.Handle, X, Y, @OldOrigin); try BkGndR := Rect(0, 0, Bitmap.Width, Bitmap.Height); for Row := 0 to (OwnerListview.ClientHeight div Bitmap.Height + 1) do begin for Column := 0 to (OwnerListview.ClientWidth div Bitmap.Width + 1) do begin if IntersectRect(TempR, ARect, BkGndR) then begin if Transparent then ACanvas.Draw(BkGndR.Left, BkGndR.Top, Bitmap) else BitBlt(ACanvas.Handle, BkGndR.Left, BkGndR.Top, BkGndR.Right, BkGndR.Bottom, Bitmap.Canvas.Handle, 0, 0, SRCCOPY) end; OffsetRect(BkGndR, Bitmap.Width, 0); end; OffsetRect(BkGndR, -BkGndR.Left, Bitmap.Height); end; finally SetViewportOrgEx(ACanvas.Handle, OldOrigin.X, OldOrigin.Y, nil); InflateRect(ARect, -Bitmap.Width, -Bitmap.Height); end end else begin SetViewportOrgEx(ACanvas.Handle, OffsetX, OffsetY, @OldOrigin); BkGndR := Rect(0, 0, Bitmap.Width, Bitmap.Height); if Transparent then ACanvas.Draw(BkGndR.Left, BkGndR.Top, Bitmap) else BitBlt(ACanvas.Handle, BkGndR.Left, BkGndR.Top, BkGndR.Right, BkGndR.Bottom, Bitmap.Canvas.Handle, 0, 0, SRCCOPY); SetViewportOrgEx(ACanvas.Handle, OldOrigin.X, OldOrigin.Y, nil); end finally Bitmap.Canvas.UnLock; if AlphaBlend then Bitmap.Free end end else if PaintDefault then begin ACanvas.Brush.Color := OwnerListview.Color; ACanvas.FillRect(ARect); end; if CaptionShow then begin if CaptionShowOnlyWhenEmpty then ShowCaption := (OwnerListview.Groups.ItemCount = 0) and (Caption <> '') else ShowCaption := Caption <> ''; if ShowCaption then begin BkGndR := OwnerListview.ClientRect; if IntersectRect(TempR, ARect, BkGndR) then begin InflateRect(BkGndR, -8, -8); ACanvas.Font.Assign(OwnerListview.Font); ACanvas.Brush.Style := bsClear; DrawTextFlags := [dtEndEllipsis]; case CaptionAlignment of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case CaptionVAlignment of cvaTop: Include(DrawTextFlags, dtTop); cvaBottom: Include(DrawTextFlags, dtBottom); cvaCenter: Include(DrawTextFlags, dtVCenter); end; if CaptionSingleLine then Include(DrawTextFlags, dtSingleLine); DrawTextWEx(ACanvas.Handle, Caption, BkGndR, DrawTextFlags, -1); end end end end end; procedure TEasyBackgroundManager.SetAlphaBlend(const Value: Boolean); begin if FAlphaBlend <> Value then begin FAlphaBlend := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetAlphaImage(const Value: TBitmap); begin FAlphaImage.Assign(Value); OwnerListview.SafeInvalidateRect(nil, False) end; procedure TEasyBackgroundManager.SetBlendAlpha(const Value: Integer); begin if FBlendAlpha <> Value then begin FBlendAlpha := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaption(const Value: WideString); begin if FCaption <> Value then begin FCaption := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaptionAlignment(const Value: TAlignment); begin if FCaptionAlignment <> Value then begin FCaptionAlignment := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaptionShow(const Value: Boolean); begin if FCaptionShow <> Value then begin FCaptionShow := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaptionShowOnlyWhenEmpty(const Value: Boolean); begin if FCaptionShowOnlyWhenEmpty <> Value then begin FCaptionShowOnlyWhenEmpty := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaptionSingleLine(const Value: Boolean); begin if FCaptionSingleLine <> Value then begin FCaptionSingleLine := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCaptionVAlignment(const Value: TCommonVAlignment); begin if FCaptionVAlignment <> Value then begin FCaptionVAlignment := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetCommonBlendMode(const Value: TCommonBlendMode); begin if FBlendMode <> Value then begin FBlendMode := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetEnabled(const Value: Boolean); begin if FEnabled <> Value then begin FEnabled := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetImage(const Value: TBitmap); begin FImage.Assign(Value); OwnerListview.SafeInvalidateRect(nil, False) end; procedure TEasyBackgroundManager.SetOffsetX(const Value: Integer); begin if FOffsetX <> Value then begin FOffsetX := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetOffsetY(const Value: Integer); begin if FOffsetY <> Value then begin FOffsetY := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetTile(const Value: Boolean); begin if FTile <> Value then begin FTile := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyBackgroundManager.SetTransparent(const Value: Boolean); begin if FTransparent <> Value then begin FTransparent := Value; OwnerListview.SafeInvalidateRect(nil, False); Image.Transparent := Value; Image.TransparentMode := tmAuto; end end; procedure TEasyBackgroundManager.WMWindowPosChanging(var Msg: TWMWindowPosChanging); begin if OffsetTrack then begin // If SWP_NOSIZE is in the flags then the cx, cy params can be garbage if Msg.WindowPos.flags and SWP_NOSIZE = 0 then begin FOffsetX := FOffsetX + (Msg.WindowPos.cx - OwnerListview.Width); FOffsetY := FOffsetY + (Msg.WindowPos.cy - OwnerListview.Height); end end end; function TEasyDropTargetManager.DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; var Effect: TCommonDropEffect; Effects: TCommonDropEffects; Keys: TCommonKeyStates; StgMedium: TStgMedium; begin if Assigned(DropTargetHelper) then DropTargetHelper.DragEnter(Owner.Handle, dataObj, Pt, dwEffect); if Owner.DragManager.Enabled then begin Keys := KeyToKeyStates(grfKeyState); Effects := DropEffectToDropEffectStates(dwEffect); // Get the "Windows Style" effect with the key modifiers Effect := KeyStateToDropEffect(Keys); Owner.DoOLEDropTargetDragEnter(dataObj, KeyToKeyStates(grfKeyState), pt, DropEffectToDropEffectStates(dwEffect), Effect); // Decide if this is a Header Drag and Drop or an Item Drag and Drop // Note that if we use a Windows supplied IDataObject it will return TRUE for QueryGetData // so we must really try to get the data to be sure if Succeeded(dataObj.GetData(HeaderClipFormat, StgMedium)) then DragManager := Owner.Header.DragManager else DragManager := Owner.DragManager; if Assigned(DragManager) then DragManager.DragEnter(dataObj, nil, Owner.ScreenToClient(pt), Keys, Effect); dwEffect := DropEffectStateToDropEffect(Effect); end else dwEffect := DROPEFFECT_NONE; Result := S_OK; end; function TEasyDropTargetManager.DragLeave: HResult; begin if Assigned(DropTargetHelper) then DropTargetHelper.DragLeave; Owner.DoOLEDropTargetDragLeave; // Just pass some dummy parameters as they are not important for OLE drag drop if Assigned(DragManager) then DragManager.DragEnd(nil, Point(0, 0), []); Result := S_OK end; function TEasyDropTargetManager.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; var Effect: TCommonDropEffect; Effects: TCommonDropEffects; Keys: TCommonKeyStates; begin if Assigned(DropTargetHelper) then DropTargetHelper.DragOver(Pt, dwEffect); if Owner.DragManager.Enabled then begin Keys := KeyToKeyStates(grfKeyState); Effects := DropEffectToDropEffectStates(dwEffect); // Get the "Windows Style" effect with the key modifiers Effect := KeyStateToDropEffect(Keys); Owner.DoOLEDropTargetDragOver(KeyToKeyStates(grfKeyState), pt, Effects, Effect); if Assigned(DragManager) then DragManager.Drag(nil, Owner.ScreenToClient(pt), Keys, Effect); dwEffect := DropEffectStateToDropEffect(Effect); end else dwEffect := DROPEFFECT_NONE; Result := S_OK end; function TEasyDropTargetManager.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; var Effect: TCommonDropEffect; Effects: TCommonDropEffects; Keys: TCommonKeyStates; Handled: Boolean; begin if Assigned(DropTargetHelper) then DropTargetHelper.Drop(dataObj, Pt, dwEffect); Keys := KeyToKeyStates(grfKeyState); Effects := DropEffectToDropEffectStates(dwEffect); // Get the "Windows Style" effect with the key modifiers Effect := KeyStateToDropEffect(Keys); Handled := False; Owner.DoOLEDropTargetDragDrop(dataObj, KeyToKeyStates(grfKeyState), pt, DropEffectToDropEffectStates(dwEffect), Effect, Handled); if Assigned(DragManager) and not Handled then DragManager.DragDrop(Owner.ScreenToClient(pt), Keys, Effect); dwEffect := DropEffectStateToDropEffect(Effect); Result := S_OK end; function TEasyDropTargetManager.GetDropTargetHelper: IDropTargetHelper; begin if not Assigned(FDropTargetHelper) and IsWin2000 then if CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IID_IDropTargetHelper, FDropTargetHelper) <> S_OK then FDropTargetHelper := nil; Result := FDropTargetHelper end; { TEasyDropSourceManager } function TEasyDropSourceManager.GiveFeedback(dwEffect: Integer): HResult; var UseDefaultCursors: Boolean; begin Result := DRAGDROP_S_USEDEFAULTCURSORS; UseDefaultCursors := True; Owner.DoOLEDropSourceGiveFeedback(DropEffectToDropEffectStates(dwEffect), UseDefaultCursors); // The application has set the cursor style if not UseDefaultCursors then Result := S_OK end; function TEasyDropSourceManager.QueryContinueDrag(fEscapePressed: BOOL; grfKeyState: Integer): HResult; var QueryResult: TEasyQueryDragResult; KeyStates: TCommonKeyStates; begin KeyStates := KeyToKeyStates(grfKeyState); if fEscapePressed then QueryResult := eqdrQuit else begin if cksButton in KeyStates then QueryResult := eqdrContinue else QueryResult := eqdrQuit end; // If no buttons are down anymore then the user dropped the objects if not(cksButton in KeyStates) then QueryResult := eqdrDrop; // Allow the application to modify if desired Owner.DoOLEDropSourceQueryContineDrag(fEscapePressed, KeyStates, QueryResult); if QueryResult = eqdrQuit then Result := DRAGDROP_S_CANCEL else if QueryResult = eqdrContinue then Result := S_OK else if QueryResult = eqdrDrop then Result := DRAGDROP_S_DROP else Result := E_UNEXPECTED end; function TCustomEasyDragManagerBase.DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; begin Result := False; end; function TCustomEasyDragManagerBase.DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; begin Result := False; end; { TEasyBaseDragManager } procedure TCustomEasyDragManagerBase.AutoScrollWindow; // This is called to autoscroll the window var Pt: TPoint; begin if Assigned(OwnerListview.Scrollbars) and OwnerListview.HandleAllocated then begin // Only scroll after an initial delay is met. This is defined as the mouse // is in constantly the autoscroll area for AutoScrollDelay time if AutoScrollDelayMet then begin // It is just easier to grab the mouse position on the screen to do the // autoscroll for various operation (drag drop, drag select, etc.) Pt := OwnerListview.ScreenToClient(Mouse.CursorPos); if PtInAutoScrollUpRegion(Pt) then DoAutoScroll(0, -(ScrollDeltaUp(Pt) * AutoScrollAccelerator)) else if PtInAutoScrollDownRegion(Pt) then DoAutoScroll(0, ScrollDeltaDown(Pt) * AutoScrollAccelerator); if OwnerListview.Scrollbars.SnapHorzView then begin if PtInAutoScrollLeftRegion(Pt) then DoAutoScroll(-(OwnerListview.CellSizes.List.Width), 0) else if PtInAutoScrollRightRegion(Pt) then DoAutoScroll(OwnerListview.CellSizes.List.Width, 0) end else begin if PtInAutoScrollLeftRegion(Pt) then DoAutoScroll(-(ScrollDeltaLeft(Pt) * AutoScrollAccelerator), 0) else if PtInAutoScrollRightRegion(Pt) then DoAutoScroll(ScrollDeltaRight(Pt) * AutoScrollAccelerator, 0) end end end; end; procedure TCustomEasyDragManagerBase.BeginDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates); begin DoDragBegin(WindowPoint, KeyState); end; constructor TCustomEasyDragManagerBase.Create(AnOwner: TCustomEasyListview); begin inherited; FAutoScrollDelay := _AUTOSCROLLDELAY; FAutoScrollTime := _AUTOSCROLLTIME; FAutoScroll := True; FAutoScrollAccelerator := 2; FAutoScrollMargin := 15; FMouseButton := [cmbLeft]; end; destructor TCustomEasyDragManagerBase.Destroy; begin inherited; end; procedure TCustomEasyDragManagerBase.DoAfterAutoScroll; begin end; procedure TCustomEasyDragManagerBase.DoAutoScroll(DeltaX, DeltaY: Integer); var Msg: TWMMouse; // Usually called from AutoScrollWindow which calcualate how to do the scroll. begin // Need to flag the controls paint method to not worry about the selection // rect as we take care of it in the auto scroll DoBeforeAutoScroll; Include(FDragState, edmsAutoScrolling); OwnerListview.Scrollbars.Scroll(DeltaX, DeltaY); UpdateAfterAutoScroll; // Need to fake a mouse move to update any drag selection after a scroll Msg.Pos := PointToSmallPoint( OwnerListview.ScreenToClient(Mouse.CursorPos)); Msg.Keys := 0; Msg.Msg := WM_MOUSEMOVE; OwnerListview.WMMouseMove(Msg); Exclude(FDragState, edmsAutoScrolling); DoAfterAutoScroll; end; procedure TCustomEasyDragManagerBase.DoBeforeAutoScroll; begin end; procedure TCustomEasyDragManagerBase.DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin end; procedure TCustomEasyDragManagerBase.DoDragBegin(WindowPoint: TPoint; KeyState: TCommonKeyStates); begin end; procedure TCustomEasyDragManagerBase.DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin end; procedure TCustomEasyDragManagerBase.DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); begin end; procedure TCustomEasyDragManagerBase.DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin end; procedure TCustomEasyDragManagerBase.DoEnable(Enable: Boolean); begin end; procedure TCustomEasyDragManagerBase.DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); begin end; procedure TCustomEasyDragManagerBase.DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); begin end; procedure TCustomEasyDragManagerBase.DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); begin end; function TCustomEasyDragManagerBase.DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; begin Result := False end; function TCustomEasyDragManagerBase.DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; begin Result := False end; procedure TCustomEasyDragManagerBase.Drag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin // Watch for an auto scroll if AutoScroll then begin // If the mouse is not in the window start the timer and prepare for autoscroll // If is then reset the flags and wait for the next time the mouse leaves the window if PtInAutoScrollRegion(WindowPoint) then Timer.Enabled := True else begin FAutoScrollDelayMet := False; Timer.Enabled := False end; end; LastKeyState := KeyState; DoDrag(Canvas, WindowPoint, KeyState, Effects) end; procedure TCustomEasyDragManagerBase.DragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin FreeAndNil(FTimer); LastKeyState := []; Exclude(FDragState, edmsDragging); DoDragDrop(WindowPoint, KeyState, Effects); DataObject := nil; end; procedure TCustomEasyDragManagerBase.DragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); begin FreeAndNil(FTimer); LastKeyState := []; Exclude(FDragState, edmsDragging); DoDragEnd(Canvas, WindowPoint, KeyState); DataObject := nil; end; procedure TCustomEasyDragManagerBase.DragEnter(const ADataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin Include(FDragState, edmsDragging); DataObject := ADataObject; Timer.Enabled := False; Timer.OnTimer := HandleTimer; Timer.Interval := AutoScrollDelay; FAutoScrollDelayMet := False; DoDragEnter(ADataObject, Canvas, WindowPoint, KeyState, Effects) end; function TCustomEasyDragManagerBase.GetAutoScrolling: Boolean; begin Result := edmsAutoScrolling in DragState end; function TCustomEasyDragManagerBase.GetDragging: Boolean; begin Result := edmsDragging in DragState end; function TCustomEasyDragManagerBase.GetTimer: TTimer; begin if not Assigned(FTimer) then FTimer := TTimer.Create(nil); Result := FTimer; end; procedure TCustomEasyDragManagerBase.HandleTimer(Sender: TObject); begin if AutoScrollDelayMet then AutoScrollWindow else begin FAutoScrollDelayMet := True; Timer.Interval := AutoScrollTime; end end; function TCustomEasyDragManagerBase.PtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; begin Result := DoPtInAutoScrollDownRegion(WindowPoint) end; function TCustomEasyDragManagerBase.PtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; begin Result := DoPtInAutoScrollLeftRegion(WindowPoint) end; function TCustomEasyDragManagerBase.PtInAutoScrollRegion(WindowPoint: TPoint): Boolean; begin Result := PtInAutoScrollDownRegion(WindowPoint) or PtInAutoScrollLeftRegion(WindowPoint) or PtInAutoScrollRightRegion(WindowPoint) or PtInAutoScrollUpRegion(WindowPoint) end; function TCustomEasyDragManagerBase.PtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; begin Result := DoPtInAutoScrollRightRegion(WindowPoint) end; function TCustomEasyDragManagerBase.PtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; begin Result := DoPtInAutoScrollUpRegion(WindowPoint) end; function TCustomEasyDragManagerBase.ScrollDeltaDown(WindowPoint: TPoint): Integer; begin Result := Abs(OwnerListview.ClientHeight - WindowPoint.Y - AutoScrollMargin) end; function TCustomEasyDragManagerBase.ScrollDeltaLeft(WindowPoint: TPoint): Integer; begin Result := Abs(WindowPoint.X - AutoScrollMargin) end; function TCustomEasyDragManagerBase.ScrollDeltaRight(WindowPoint: TPoint): Integer; begin Result := Abs(OwnerListview.ClientWidth - WindowPoint.X - AutoScrollMargin ) end; function TCustomEasyDragManagerBase.ScrollDeltaUp(WindowPoint: TPoint): Integer; begin Result := Abs(WindowPoint.Y - OwnerListview.Header.RuntimeHeight - AutoScrollMargin) end; procedure TCustomEasyDragManagerBase.RegisterOLEDragDrop(DoRegister: Boolean); begin if OwnerListview.HandleAllocated then begin if DoRegister then begin if not (ebcsOLERegistered in OwnerListview.States) then begin RegisterDragDrop(OwnerListview.Handle, OwnerListview.DropTarget); Include(OwnerListview.FStates, ebcsOLERegistered) end end else begin if ebcsOLERegistered in OwnerListview.States then begin RevokeDragDrop(OwnerListview.Handle); Exclude(OwnerListview.FStates, ebcsOLERegistered) end end; end end; procedure TCustomEasyDragManagerBase.SetEnabled(const Value: Boolean); begin if FEnabled <> Value then begin DoEnable(Value); FEnabled := Value; end end; procedure TCustomEasyDragManagerBase.SetRegistered(Value: Boolean); begin if Value <> FRegistered then begin RegisterOLEDragDrop(Value); FRegistered := Value; end end; procedure TCustomEasyDragManagerBase.UpdateAfterAutoScroll; begin end; procedure TCustomEasyDragManagerBase.VCLDragStart; begin end; procedure TCustomEasyDragManagerBase.WMKeyDown(var Msg: TWMKeyDown); begin case Msg.CharCode of VK_HOME: DoAutoScroll(-OwnerListview.Scrollbars.OffsetX, -OwnerListview.Scrollbars.OffsetY); VK_END: DoAutoScroll(OwnerListview.Scrollbars.ViewWidth-OwnerListview.ClientWidth, OwnerListview.Scrollbars.ViewHeight-OwnerListview.ClientHeight); VK_NEXT: DoAutoScroll(0, OwnerListview.ClientHeight); VK_PRIOR: DoAutoScroll(0, -OwnerListview.ClientHeight); VK_UP: DoAutoScroll(0, -OwnerListview.Scrollbars.Line); VK_DOWN: DoAutoScroll(0, OwnerListview.Scrollbars.Line); VK_LEFT: DoAutoScroll(-OwnerListview.Scrollbars.Line, 0); VK_RIGHT: DoAutoScroll(OwnerListview.Scrollbars.Line, 0); end; end; constructor TEasyDragRectManager.Create(AnOwner: TCustomEasyListview); begin inherited; FMouseButton := [cmbLeft, cmbRight]; FEnabled := False; end; destructor TEasyDragRectManager.Destroy; begin inherited; end; function TEasyDragRectManager.DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.Y > OwnerListview.ClientHeight - AutoScrollMargin) and (OwnerListview.Scrollbars.OffsetY < OwnerListview.Scrollbars.MaxOffsetY) end; function TEasyDragRectManager.DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.X < AutoScrollMargin) and (OwnerListview.Scrollbars.OffsetX > 0) end; function TEasyDragRectManager.DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.X > (OwnerListview.ClientWidth - AutoScrollMargin)) and (OwnerListview.Scrollbars.OffsetX < OwnerListview.Scrollbars.MaxOffsetX) end; function TEasyDragRectManager.DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.Y - OwnerListview.Header.RuntimeHeight < AutoScrollMargin) and (OwnerListview.Scrollbars.OffsetY > 0) end; procedure TEasyDragRectManager.DoAfterAutoScroll; begin inherited; end; procedure TEasyDragRectManager.DoAutoScroll(DeltaX, DeltaY: Integer); // Usually called from AutoScrollWindow which calcualate how to do the scroll. // This method is usually overridden to perform the scroll in the passed direction begin inherited; end; procedure TEasyDragRectManager.DoBeforeAutoScroll; begin inherited; // Keep the Dragpoint in sync with the current view // Need to map the dragged point to a new point after a scroll FOldOffsets.X := OwnerListview.Scrollbars.OffsetX; FOldOffsets.Y := OwnerListview.Scrollbars.OffsetY; end; procedure TEasyDragRectManager.DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); var ARect: TRect; begin // Update the Selection due to this drag OwnerListview.Selection.DragSelect(KeyState); // Get the last rectangle FPrevRect := SelectionRect; inherited; // Update the drag point DragPoint := OwnerListview.Scrollbars.MapWindowToView(WindowPoint); // Map it to the Client window coordinates ARect := SelRectInWindowCoords; // Make sure it is confined in the visible window IntersectRect(ARect, ARect, OwnerListview.ClientRect); // May need to update the last rectangle to if the drag rect is getting smaller UnionRect(ARect, ARect, OwnerListview.Scrollbars.MapViewRectToWindowRect(PrevRect)); // Reentrant possibility if not(edmsAutoScrolling in DragState) then AutoScrollWindow; // Always have to update if the selection rectangle if it gets smaller or full // update if full row select (leaves white bands at the column interfaces) if OwnerListview.Selection.FullRowSelect then OwnerListview.SafeInvalidateRect(nil, True) else OwnerListview.SafeInvalidateRect(@ARect, True); end; procedure TEasyDragRectManager.DoDragBegin(WindowPoint: TPoint; KeyState: TCommonKeyStates); begin inherited; FPrevRect := SelectionRect; end; procedure TEasyDragRectManager.DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); var ARect: TRect; begin // Erase the selection rectangle, mainly for the XOR FocusRect when not DoubleBuffered inherited; // Get the last rectangle ARect := SelRectInWindowCoords; // Make sure it is confined in the visible window IntersectRect(ARect, ARect, OwnerListview.ClientRect); // Redraw the window if OwnerListview.Selection.FullRowSelect then OwnerListview.SafeInvalidateRect(nil, True) else OwnerListview.SafeInvalidateRect(@ARect, True); AnchorPoint := Point(0, 0); DragPoint := Point(0, 0); FPrevRect := Rect(0, 0, 0, 0); end; procedure TEasyDragRectManager.DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin inherited DoDragEnter(DataObject, Canvas, WindowPoint, KeyState, Effects); FDragPoint := WindowPoint end; procedure TEasyDragRectManager.FinalizeDrag(KeyState: TCommonKeyStates); // Does not mean the action actually occured it means that InitializeDrag was // called and this is it matching call. EndDrag means that the drag actually // occured begin end; function TEasyDragRectManager.GetSelectionRect: TRect; begin Result := ProperRect(Rect(AnchorPoint.X, AnchorPoint.Y, DragPoint.X, DragPoint.Y)); if Result.Top = Result.Bottom then // added Inc(Result.Bottom); if Result.Left = Result.Right then // added Inc(Result.Right); end; function TEasyDragRectManager.InitializeDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates): Boolean; // Does not mean that the action will be a Selection Drag, it just means get // ready for one just in case. begin Result := False; if Enabled then begin if ((cksLButton in KeyState) and (cmbLeft in MouseButton)) or ((cksMButton in KeyState) and (cmbMiddle in MouseButton)) or ((cksRButton in KeyState) and (cmbRight in MouseButton)) then begin AnchorPoint := OwnerListview.Scrollbars.MapWindowToView(WindowPoint); DragPoint := AnchorPoint; Result := True end end end; procedure TEasyDragRectManager.PaintRect(Canvas: TCanvas); // Paints the selection rectangle to the canvas: // NOTE: DO NOT USE THIS METHOD DIRECTLY use the PaintSelectionRect to draw // the rectangle // If not DoubleBuffered it is assumed that the Canvas is a Screen DC else it is // assumed to be a Bitmap Compatiable Memory DC var SelectRect: TRect; begin SelectRect.TopLeft := OwnerListview.Scrollbars.MapViewToWindow(AnchorPoint); SelectRect.BottomRight := OwnerListview.Scrollbars.MapViewToWindow(DragPoint); SelectRect := ProperRect(SelectRect); IntersectRect(SelectRect, SelectRect, OwnerListview.ClientRect); if (OwnerListview.ViewSupportsHeader) and (OwnerListview.Header.Visible) then begin if SelectRect.Top < OwnerListview.Header.Height then SelectRect.Top := OwnerListview.Header.Height; end; if OwnerListview.Selection.AlphaBlendSelRect and HasMMX then begin Canvas.Brush.Color := OwnerListview.Selection.BorderColorSelRect; MPCommonUtilities.AlphaBlend(0, Canvas.Handle, SelectRect, Point(0, 0), cbmConstantAlphaAndColor, OwnerListview.Selection.BlendAlphaSelRect, ColorToRGB(OwnerListview.Selection.BlendColorSelRect)); Canvas.FrameRect(SelectRect); end else begin Canvas.Font.Assign(OwnerListview.Font); Canvas.Brush.Color := OwnerListview.Color; Canvas.Font.Color := clBlack; DrawFocusRect(Canvas.Handle, SelectRect); end end; procedure TEasyDragRectManager.PaintSelectionRect(Canvas: TCanvas); // Causes the Selection Rectangle to be drawn or "erased" (erased is just redrawn // again in the same place so the XOR mode will clear the rectangle) // NOTE: Use this method and not the PaintRect method directly begin PaintRect(Canvas); end; function TEasyDragRectManager.SelRectInWindowCoords: TRect; // Gets the selection rectangle in the current Window coordinates then trims off // the pieces that do not lie in the current window rectangle begin Result.TopLeft := OwnerListview.Scrollbars.MapViewToWindow(AnchorPoint); Result.BottomRight := OwnerListview.Scrollbars.MapViewToWindow(DragPoint); Result := ProperRect(Result); end; procedure TEasyDragRectManager.SetAnchorPoint(ViewportAnchor: TPoint); begin FAnchorPoint := ViewportAnchor end; procedure TEasyDragRectManager.SetDragPoint(const Value: TPoint); begin FDragPoint := Value end; procedure TEasyDragRectManager.UpdateAfterAutoScroll; begin inherited UpdateAfterAutoScroll; // Keep the Dragpoint in sync with the current view // Need to map the dragged point to a new point after a scroll FDragPoint.X := DragPoint.X + (OwnerListview.Scrollbars.OffsetX - OldOffsets.X); FDragPoint.Y := DragPoint.Y + (OwnerListview.Scrollbars.OffsetY - OldOffsets.Y); end; procedure TEasyDragRectManager.WMKeyDown(var Msg: TWMKeyDown); begin inherited; end; { TCustomEasyListview } constructor TCustomEasyListview.Create(AOwner: TComponent); begin inherited Create(AOwner); FGesture := TEasyGestureManager.Create(Self); NCCanvas := TCanvas.Create; FGroupFont := TFont.Create; FPaintInfoGroup := CreateGroupPaintInfo; FPaintInfoItem := CreateItemPaintInfo; FPaintInfoColumn := CreateColumnPaintInfo; PaintInfoGroup.FMarginBottom.FPaintInfo := TEasyPaintInfoGroup.Create(Self); FHotTrack := TEasyHotTrackManager.Create(Self); Canvas.Control := Self; ParentColor := False; Brush.Color := clWindow; Color := clWindow; BevelInner := bvLowered; BevelKind := bkTile; ControlStyle := ControlStyle - [csCaptureMouse, csOpaque, csAcceptsControls]; // We will do this ourselves FBackGround := TEasyBackgroundManager.Create(Self); FScrollbars := TEasyScrollbarManager.Create(Self); FDropTarget := TEasyDropTargetManager.Create(Self); FDragRect := TEasyDragRectManager.Create(Self); FDragManager := TEasyOLEDragManager.Create(Self); FCheckManager := TEasyCheckManager.Create(Self); FSelection := TEasySelectionManager.Create(Self); FGroups := CreateGroups; FHeader := TEasyHeader.Create(Self); FEditManager := TEasyEditManager.Create(Self); FGlobalImages := TEasyGlobalImageManager.Create(Self); HintInfo := TEasyHintInfo.Create(Self); FCellSizes := TEasyCellSizes.Create(Self); FSort := TEasySortManager.Create(Self); TabStop := True; FWheelMouseDefaultScroll := edwsVert; FWheelMouseScrollModifierEnabled := True; FGroupCollapseButton := TBitmap.Create; FGroupExpandButton := TBitmap.Create; FItems := TEasyGlobalItems.Create(Self); FShowGroupMargins := False; FShowThemedBorder := True; DisabledBlendAlpha := 128; DisabledBlendColor := clWindow; FIncrementalSearch := TEasyIncrementalSearchManager.Create(Self); FScratchCanvas := TControlCanvas.Create; FScratchCanvas.Control := Self; {$IFNDEF COMPILER_6_UP} Width := 100; Height := 200; {$ENDIF COMPILER_6_UP} if IsUnicode then begin // GroupFont.Name := 'MS Shell Dlg 2'; // Font.Name := 'MS Shell Dlg 2'; // Header.Font.Name := 'MS Shell Dlg 2'; end end; destructor TCustomEasyListview.Destroy; begin Groups.Clear; // Clear the items first so there is no chance of trying to draw them after the window is destroyed Header.Columns.Clear; // Clear the columns first so there is no chance of trying to draw them after the window is destroyed inherited Destroy; DropTarget := nil; // Don't destroy these objects until the Window is destroyed GroupExpandButton.Canvas.Unlock; GroupCollapseButton.Canvas.Unlock; FreeAndNil(FGesture); FreeAndNil(FItems); FreeAndNil(FNCCanvas); FreeAndNil(FGroupExpandButton); FreeAndNil(FGroupCollapseButton); FreeAndNil(FBackGround); FreeAndNil(FBackBits); FreeAndNil(FScrollbars); FreeAndNil(FDragRect); FreeAndNil(FDragManager); FreeAndNil(FCheckManager); FreeAndNil(FSelection); FreeAndNil(FHeader); FreeAndNil(FEditManager); FreeAndNil(FGlobalImages); FreeAndNil(FCellSizes); {$IFDEF COMPILER_5_UP} FreeAndNil(FGroupFont); // Bug in D4 {$ENDIF COMPILER_5_UP} FreeAndNil(FPaintInfoGroup); FreeAndNil(FPaintInfoItem); FreeAndNil(FPaintInfoColumn); FreeAndNil(FHotTrack); FreeAndNil(FHintInfo); FreeAndNil(FSort); FreeAndNil(FIncrementalSearch); FreeAndNil(FScratchCanvas); FreeAndNil(FGroups); // Always make Last end; function TCustomEasyListview.ClickTestGroup(ViewportPoint: TPoint; KeyStates: TCommonKeyStates; var HitInfo: TEasyGroupHitTestInfoSet): TEasyGroup; // // Handles any default behavior of clicking on a group and returns true if the // click was on a group object // begin HitInfo := []; Result := Groups.GroupByPoint(ViewportPoint); if Assigned(Result) then Result.HitTestAt(ViewportPoint, HitInfo); end; function TCustomEasyListview.ClickTestItem(ViewportPoint: TPoint; Group: TEasyGroup; KeyStates: TCommonKeyStates; var HitInfo: TEasyItemHitTestInfoSet): TEasyItem; begin Result := nil; HitInfo := []; if not Assigned(Group) then Group := Groups.GroupByPoint(ViewportPoint); if Assigned(Group) then Result := Group.ItembyPoint(ViewportPoint); // Result := Groups.ItcmbyPoint(ViewportPoint); if Assigned(Result) then Result.HitTestAt(ViewportPoint, HitInfo); end; function TCustomEasyListview.ClientInViewportCoords: TRect; begin Result := ClientRect; Result.Top := Result.Top + Header.RuntimeHeight; Result := Scrollbars.MapWindowRectToViewRect(Result) end; function TCustomEasyListview.CreateColumnPaintInfo: TEasyPaintInfoBaseColumn; begin Result := TEasyPaintInfoColumn.Create(Self) end; function TCustomEasyListview.CreateGroupPaintInfo: TEasyPaintInfoBaseGroup; begin Result := TEasyPaintInfoGroup.Create(Self) end; function TCustomEasyListview.CreateGroups: TEasyGroups; begin Result := TEasyGroups.Create(Self); end; function TCustomEasyListview.CreateItemPaintInfo: TEasyPaintInfoBaseItem; begin Result := TEasyPaintInfoItem.Create(Self); end; function TCustomEasyListview.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; var LocalMouseScroll: TEasyDefaultWheelScroll; uiParam, pvParam: UINT; IsNeg: Boolean; begin IsNeg := WheelDelta < 0; uiParam := 0; pvParam := 3; if IsWinNT then SystemParametersInfo(SPI_GETWHEELSCROLLLINES, uiParam, @pvParam, 0); if WheelMouseDefaultScroll = edwsVert then WheelDelta := Groups.CellHeight * Integer(pvParam) // Sroll down n Cells else WheelDelta := Groups.CellWidth {* Integer(pvParam)}; // Scroll sideways is different only one cell if IsNeg then WheelDelta := -WheelDelta; Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos); LocalMouseScroll := WheelMouseDefaultScroll; if WheelMouseScrollModifierEnabled then begin if (ssShift in Shift) then begin if WheelMouseDefaultScroll = edwsVert then LocalMouseScroll := edwsHorz else LocalMouseScroll := edwsVert end; if ssCtrl in Shift then begin if LocalMouseScroll = edwsVert then WheelDelta := ClientHeight - Header.RuntimeHeight else WheelDelta := ClientWidth; if IsNeg then WheelDelta := -WheelDelta; end end; if LocalMouseScroll = edwsVert then Scrollbars.Scroll(0, -WheelDelta) else if LocalMouseScroll = edwsHorz then Scrollbars.Scroll(-WheelDelta, 0); if not Result then Result := True; end; function TCustomEasyListview.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; begin Result := inherited DoMouseWheelDown(Shift, MousePos); end; function TCustomEasyListview.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; begin Result := inherited DoMouseWheelUp(Shift, MousePos); end; function TCustomEasyListview.DragInitiated: Boolean; begin Result := [ebcsDragSelecting, ebcsDragging, ebcsDragSelectPending, ebcsDragPending] * States <> [] end; function TCustomEasyListview.ExecuteDragDrop(AvailableEffects: TCommonDropEffects; DataObjectInf: IDataObject; DropSource: IDropSource; var dwEffect: Integer): HRESULT; begin Result := ActiveX.DoDragDrop(DataObjectInf, DropSource, DropEffectStatesToDropEffect(AvailableEffects), dwEffect); end; function TCustomEasyListview.GetGroupCollapseImage: TBitmap; begin Result := FGroupCollapseButton end; function TCustomEasyListview.GetGroupExpandImage: TBitmap; begin Result := FGroupExpandButton end; function TCustomEasyListview.GetHintType: TEasyHintType; begin Result := HintInfo.HintType end; function TCustomEasyListview.GetPaintInfoColumn: TEasyPaintInfoBaseColumn; begin Result := FPaintInfoColumn; end; function TCustomEasyListview.GetPaintInfoGroup: TEasyPaintInfoBaseGroup; begin Result := FPaintInfoGroup; end; function TCustomEasyListview.GetPaintInfoItem: TEasyPaintInfoBaseItem; begin Result := FPaintInfoItem; end; function TCustomEasyListview.GetScratchCanvas: TControlCanvas; begin if HandleAllocated then Result := FScratchCanvas else Result := nil end; function TCustomEasyListview.GetSortColumn: TEasyColumn; begin Result := Selection.FocusedColumn end; function TCustomEasyListview.GetTopItem: TEasyItem; begin Result := Groups.FirstItemInRect( Scrollbars.MapWindowRectToViewRect(ClientRect, False)) end; function TCustomEasyListview.GroupTestExpand(HitInfo: TEasyGroupHitTestInfoSet): Boolean; begin Result := egtOnExpandButton in HitInfo end; function TCustomEasyListview.IsFontStored: Boolean; begin Result := not ParentFont and not DesktopFont; end; function TCustomEasyListview.IsHeaderMouseMsg(MousePos: TSmallPoint; ForceTest: Boolean = False): Boolean; var R: TRect; begin Result := False; if not (DragRect.Dragging or DragManager.Dragging or Header.DragManager.Dragging) or ForceTest then begin R := Header.DisplayRect; R.Bottom := Header.RuntimeHeight; Result := (ViewSupportsHeader and PtInRect(R, SmallPointToPoint(MousePos))) or (ebcsHeaderCapture in States) or Assigned(Header.HotTrackedColumn) end end; function TCustomEasyListview.IsThumbnailView: Boolean; begin Result := View in THUMBNAILVIEWS end; function TCustomEasyListview.IsVertView: Boolean; begin Result := View in VERTICALVIEWS end; function TCustomEasyListview.ScrollHeaderHorz: Boolean; begin Result := not (Header.ShowInAllViews and (View = elsList)) end; function TCustomEasyListview.ToolTipNeeded(TargetObj: TEasyCollectionItem; var TipCaption: WideString): Boolean; // Calcuates if the text is being truncated in the current view of the object // If so the result is true. var TextFlags: TCommonDrawTextWFlags; RectArray: TEasyRectArrayObject; R: TRect; LineCount: Integer; Item: TEasyItem; begin Result := False; TipCaption := ''; if TargetObj is TEasyItem then begin Item := TEasyItem( TargetObj); if not Item.Focused then begin Item.ItemRectArray(nil, Canvas, RectArray); TextFlags := [dtLeft, dtCalcRect, dtCalcRectAdjR]; R := RectArray.LabelRect; LineCount := Item.View.PaintTextLineCount(Item, nil); Item.View.LoadTextFont(Item, 0, Canvas, False); DrawTextWEx(Canvas.Handle, Item.Caption, R, TextFlags, LineCount); if (RectWidth(RectArray.TextRect) < RectWidth(R)) or (RectHeight(RectArray.TextRect) < RectHeight(R)) then begin TipCaption := Item.Caption; Result := True; end end end end; function TCustomEasyListview.UseInternalDragImage: Boolean; begin Result := True end; function TCustomEasyListview.ViewSupportsHeader: Boolean; begin Result := (View in HEADERSUPPORTEDVIEWS) or Header.ShowInAllViews end; procedure TCustomEasyListview.AutoFitAllCells(VisibleOnly: Boolean); var i: Integer; begin case View of elsReport: begin BeginUpdate; try for i := 0 to Header.Columns.Count - 1 do begin if VisibleOnly then begin if Header.Columns[i].Visible then Header.Columns[i].AutoSizeToFit end else Header.Columns[i].AutoSizeToFit end finally EndUpdate end end; elsSmallIcon: begin BeginUpdate; try CellSizes.SmallIcon.AutoSize := True; finally EndUpdate end end; elsList: begin BeginUpdate; try CellSizes.List.AutoSize := True; finally EndUpdate end end; elsGrid: begin BeginUpdate; try CellSizes.Grid.AutoSize := True; finally EndUpdate end end; end end; procedure TCustomEasyListview.BeginUpdate; begin inherited BeginUpdate; // Sort.BeginUpdate; end; procedure TCustomEasyListview.CancelCut; var Item: TEasyItem; begin Item := Groups.FirstItem; while Assigned(Item) do begin Item.Cut := False; Item := Groups.NextItem(Item) end end; procedure TCustomEasyListview.CheckFocus; begin if not Focused then begin if CanFocus and not (csDesigning in ComponentState) and HandleAllocated then SetFocus; end; end; procedure TCustomEasyListview.ClearPendingDrags; begin States := States - [ebcsDragPending, ebcsDragSelectPending]; DragManager.ClearDragItem; end; procedure TCustomEasyListview.ClearStates; begin Exclude(FStates, ebcsLButtonDown); Exclude(FStates, ebcsMButtonDown); Exclude(FStates, ebcsRButtonDown); Exclude(FStates, ebcsDragSelecting); Exclude(FStates, ebcsDragSelectPending); Exclude(FStates, ebcsDragSelecting); Exclude(FStates, ebcsDragPending); Exclude(FStates, ebcsDragging); Exclude(FStates, ebcsScrollButtonDown); Exclude(FStates, ebcsVCLDrag); Exclude(FStates, ebcsCheckboxClickPending); Exclude(FStates, ebcsHeaderCapture); Exclude(FStates, ebcsGroupExpandPending); if not Themed then CheckManager.PendingObject := nil; end; procedure TCustomEasyListview.ClipHeader(ACanvas: TCanvas; ResetClipRgn: Boolean); var OldOrg: TPoint; begin if ResetClipRgn then SelectClipRgn(ACanvas.Handle, 0); if Header.RuntimeHeight > 0 then begin SetWindowOrgEx(ACanvas.Handle, 0, 0, @OldOrg); if ViewSupportsHeader and (Header.Visible) then ExcludeClipRect(ACanvas.Handle, 0, 0, ClientWidth, Header.RuntimeHeight); SetWindowOrgEx(ACanvas.Handle, OldOrg.X, OldOrg.Y, nil); end end; procedure TCustomEasyListview.CMDrag(var Msg: TCMDrag); // Called during a VCL drag and drop operation var Keys: TCommonKeyStates; P: TPoint; Effects: TCommonDropEffect; {$IFDEF LOG_VCL_CMDRAG} F: TFileStream; S: string; Buffer: array[0..MAX_PATH] of char; {$ENDIF} begin {$IFDEF LOG_VCL_CMDRAG} FillChar(Buffer, SizeOf(Buffer), #0); GetModuleFileName(hInstance, Buffer, MAX_PATH); S := ExtractFilePath(Buffer) + 'VCL Drag.log'; try F := TFileStream.Create(S, fmOpenReadWrite or fmShareExclusive); except F := TFileStream.Create(S, fmCreate or fmShareExclusive); end; F.Seek(0, soFromEnd); case Msg.DragMessage of dmDragEnter: S := 'dmDragEnter'; dmDragLeave: S := 'dmDragLeave'; dmDragMove: S := 'dmDragMove'; dmDragDrop: S := 'dmDragDrop'; dmDragCancel: S := 'dmDragCancel'; dmFindTarget: S := 'dmFindTarget'; end; S := S + #13+#10; F.Write(PChar(S)^, Length(S)); F.Free; {$ENDIF} Keys := []; Effects := cdeNone; case Msg.DragMessage of dmDragEnter: begin DragManager.DragEnter(nil, nil, ScreenToClient(Msg.DragRec^.Pos), Keys, Effects); inherited; end; dmDragLeave: begin // The VCL DD stupidly sends a Drag Leave before the Drag Drop. This // causes problems since I use DragEnd to reset a lot of the DragManagers // flags. Check if the drop was on this window. If it was skip the // Drag end and wait for the Drag Drop GetCursorPos(P); if WindowFromPoint(P) <> Handle then begin DragManager.DragEnd(nil, ScreenToClient(Msg.DragRec^.Pos), Keys); ClearStates; end; inherited; end; dmDragMove: begin DragManager.Drag(nil, ScreenToClient(Msg.DragRec^.Pos), Keys, Effects); inherited; end; dmDragDrop: begin inherited; DragManager.DragDrop(ScreenToClient(Msg.DragRec^.Pos), Keys, Effects); ClearStates; end; dmDragCancel: begin DragManager.DragEnd(nil, ScreenToClient(Msg.DragRec^.Pos), Keys); inherited; ClearStates; end; else inherited; end; end; procedure TCustomEasyListview.CMHintShow(var Message: TCMHintShow); var Allow: Boolean; TargetObj: TEasyCollectionItem; ItemHitInfo: TEasyItemHitTestInfoSet; GroupHitInfo: TEasyGroupHitTestInfoSet; ViewPt: TPoint; begin {$IFDEF GXDEBUG_HINT} SendDebug('CMHintShow'); {$ENDIF GXDEBUG_HINT} ViewPt := Scrollbars.MapWindowToView(Message.HintInfo^.CursorPos); // See if we have hit any objects of interest TargetObj := Groups.ItembyPoint(ViewPt); if Assigned(TargetObj) then begin TEasyItem( TargetObj).HitTestAt(ViewPt, ItemHitInfo); if not(ehtOnClickselectBounds in ItemHitInfo) then TargetObj := nil end; if not Assigned(TargetObj) then begin TargetObj := Groups.GroupByPoint(ViewPt); if Assigned(TargetObj) then TEasyGroup( TargetObj).HitTestAt(ViewPt, GroupHitInfo); end; // Default hint type is Text FHintData.HintType := HintInfo.HintType; FHintData.HintStr := Hint; FHintData.ReshowTimeout := Message.HintInfo^.ReshowTimeout; FHintData.HideTimeout := Message.HintInfo^.HideTimeout; // Allow the application to modify the HintData Allow := False; DoHintPopup(TargetObj, FHintData.HintType, Message.HintInfo^.CursorPos, FHintData.HintStr, FHintData.HideTimeout, FHintData.ReshowTimeout, Allow); if FHintData.HintStr = '' then Allow := False; Message.HintInfo^.ReshowTimeout := FHintData.ReshowTimeout; Message.HintInfo^.HideTimeout := FHintData.HideTimeout; SetRect(FHintData.ToolTipRect, 0, 0, Screen.Width, 0); // If the type is ToolTip then calculate if it is necessary if (FHintData.HintType = ehtToolTip) then begin if TargetObj is TEasyItem then Allow := ToolTipNeeded(TargetObj, FHintData.HintStr) else Allow := False; end; if Allow then begin Message.HintInfo.HintWindowClass := TEasyHintWindow; // Send our HintData to the Hint Window through the supplied Data parameter Message.HintInfo.HintData := @FHintData; if Message.HintInfo.HintStr = '' then Message.HintInfo.HintStr := 'Dummy'; // Area where the tip is defined, once outside the Hint testing will resume if TargetObj is TEasyItem then Message.HintInfo^.CursorRect := TargetObj.DisplayRect; if TargetObj is TEasyGroup then begin if egtOnRightMargin in GroupHitInfo then Message.HintInfo^.CursorRect := TEasyGroup( TargetObj).BoundsRectRightMargin else if egtOnLeftMargin in GroupHitInfo then Message.HintInfo^.CursorRect := TEasyGroup( TargetObj).BoundsRectLeftMargin else if egtOnHeader in GroupHitInfo then Message.HintInfo^.CursorRect := TEasyGroup( TargetObj).BoundsRectTopMargin else if egtOnFooter in GroupHitInfo then Message.HintInfo^.CursorRect := TEasyGroup( TargetObj).BoundsRectBottomMargin; end; Message.HintInfo^.CursorRect := Scrollbars.MapViewRectToWindowRect(Message.HintInfo^.CursorRect); FHintData.Listview := Self; FHintData.HintControl := Message.HintInfo^.HintControl; FHintData.HintWindowClass := Message.HintInfo^.HintWindowClass; FHintData.HintPos := Message.HintInfo^.HintPos; FHintData.HintMaxWidth := Message.HintInfo^.HintMaxWidth; FHintData.HintColor := Message.HintInfo^.HintColor; FHintData.CursorRect := Message.HintInfo^.CursorRect; FHintData.CursorPos := Message.HintInfo^.CursorPos; FHintData.HintData := nil; FHintData.TargetObj := TargetObj; inherited; end else Message.Result := 1; // Message is handled, don't show the hint end; procedure TCustomEasyListview.CMHintShowPause(var Message: TCMHintShow); var HintShowing: Boolean; PauseTime: PInteger; begin {$IFDEF GXDEBUG_HINT} SendDebug('CMHintShowPause'); {$ENDIF GXDEBUG_HINT} PauseTime := PInteger(TMessage(Message).LParam); HintShowing := Boolean( TMessage(Message).wParam); DoHintShowPause(HintShowing, PauseTime^); inherited end; procedure TCustomEasyListview.CMMouseWheel(var Msg: TWMMouseWheel); begin inherited end; procedure TCustomEasyListview.CMParentFontChanged(var Msg: TMessage); begin inherited; if ParentFont then begin if Msg.wParam <> 0 then begin GroupFont.Assign(TFont(Msg.lParam)); Header.Font.Assign(TFont(Msg.lParam)); end else begin GroupFont.Assign(TWinControlCracker(Parent).Font); Header.Font.Assign(TWinControlCracker(Parent).Font); end end end; procedure TCustomEasyListview.CopyToClipboard; begin end; procedure TCustomEasyListview.CreateParams(var Params: TCreateParams); begin inherited; Params.WindowClass.Style := Params.WindowClass.Style or CS_DBLCLKS and not (CS_HREDRAW or CS_VREDRAW); Params.Style := Params.Style or WS_CLIPCHILDREN or WS_CLIPSIBLINGS; AddBiDiModeExStyle(Params.ExStyle); end; procedure TCustomEasyListview.CreateWnd; begin inherited; DoUpdate; // The Window Handle is now valid DragManager.Registered := DragManager.Enabled; Header.DragManager.Registered := Header.DragManager.Enabled; ResizeBackBits(ClientWidth, ClientHeight); end; procedure TCustomEasyListview.CutToClipboard; var Handled, Mark: Boolean; begin Handled := False; Mark := True; DoClipboardCut(Handled, Mark); if Handled and Mark then MarkSelectedCut end; procedure TCustomEasyListview.DestroyWnd; begin inherited; end; procedure TCustomEasyListview.DoAfterPaint(ACanvas: TCanvas; ClipRect: TRect); begin if Assigned(OnAfterPaint) then OnAfterPaint(Self, ACanvas, ClipRect) end; procedure TCustomEasyListview.DoAutoGroupGetKey(Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Key: LongWord); begin if Assigned(OnAutoGroupGetKey) then OnAutoGroupGetKey(Self, Item, ColumnIndex, Groups, Key) end; procedure TCustomEasyListview.DoAutoSortGroupCreate(Item: TEasyItem; ColumnIndex: Integer; Groups: TEasyGroups; var Group: TEasyGroup; var DoDefaultAction: Boolean); begin if Assigned(OnAutoSortGroupCreate) then OnAutoSortGroupCreate(Self, Item, ColumnIndex, Groups, Group, DoDefaultAction); if not Assigned(Group) then Group := Groups.Add end; procedure TCustomEasyListview.DoClipboardCopy(var Handled: Boolean); begin if Assigned(OnClipboardCopy) then OnClipboardCopy(Self, Handled); end; procedure TCustomEasyListview.DoClipboardCut(var MarkAsCut, Handled: Boolean); begin if Assigned(OnClipboardCut) then OnClipboardCut(Self, MarkAsCut, Handled); end; procedure TCustomEasyListview.DoClipboardPaste(var Handled: Boolean); begin if Assigned(OnClipboardPaste) then OnClipboardPaste(Self, Handled); end; procedure TCustomEasyListview.DoColumnCheckChanged(Column: TEasyColumn); begin if Assigned(OnColumnCheckChanged) and not (csDestroying in ComponentState) then OnColumnCheckChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnCheckChanging(Column: TEasyColumn; var Allow: Boolean); begin if Assigned(OnColumnCheckChanging) and not (csDestroying in ComponentState) then OnColumnCheckChanging(Self, Column, Allow) end; procedure TCustomEasyListview.DoColumnClick(Button: TCommonMouseButton; const Column: TEasyColumn); begin if Assigned(OnColumnClick) then OnColumnClick(Self, Button, Column) end; procedure TCustomEasyListview.DoColumnContextMenu(HitInfo: TEasyHitInfoColumn; WindowPoint: TPoint; var Menu: TPopupMenu); begin if Assigned(OnColumnContextMenu) then OnColumnContextMenu(Self, HitInfo, WindowPoint, Menu); end; procedure TCustomEasyListview.DoColumnDblClick(Button: TCommonMouseButton; ShiftState: TShiftState; MousePos: TPoint; Column: TEasyColumn); begin if Assigned(OnColumnDblClick) then OnColumnDblClick(Self, Button, MousePos, Column) end; procedure TCustomEasyListview.DoColumnDropDownButtonClick(Column: TEasyColumn; Button: TCommonMouseButton; ShiftState: TShiftState; MousePos: TPoint; var DoDefault: Boolean); begin if Assigned(OnColumnDropDownButtonClick) then OnColumnDropDownButtonClick(Self, Column, Button, ShiftState, MousePos, DoDefault) end; procedure TCustomEasyListview.DoColumnEnableChanged(Column: TEasyColumn); begin if Assigned(OnColumnEnableChanged) and not (csDestroying in ComponentState) then OnColumnEnableChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnEnableChanging(Column: TEasyColumn; var Allow: Boolean); begin if Assigned(OnColumnEnableChanging) and not (csDestroying in ComponentState) then OnColumnEnableChanging(Self, Column, Allow) end; procedure TCustomEasyListview.DoColumnFocusChanged(Column: TEasyColumn); begin if Assigned(OnColumnFocusChanged) and not (csDestroying in ComponentState) then OnColumnFocusChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnFocusChanging(Column: TEasyColumn; var Allow: Boolean); begin if Assigned(OnColumnFocusChanging) and not (csDestroying in ComponentState) then OnColumnFocusChanging(Self, Column, Allow) end; procedure TCustomEasyListview.DoColumnFreeing(Column: TEasyColumn); begin if Assigned(OnColumnFreeing) then OnColumnFreeing(Self, Column) end; procedure TCustomEasyListview.DoColumnGetCaption(Column: TEasyColumn; Line: Integer; var Caption: WideString); begin if Assigned(OnColumnGetCaption) then OnColumnGetCaption(Self, Column, Line, Caption) end; procedure TCustomEasyListview.DoColumnGetDetail(Column: TEasyColumn; Line: Integer; var Detail: Integer); begin if Assigned(OnColumnGetDetail) then OnColumnGetDetail(Self, Column, Line, Detail) end; procedure TCustomEasyListview.DoColumnGetDetailCount(Column: TEasyColumn; var Count: Integer); begin if Assigned(OnColumnGetDetailCount) then OnColumnGetDetailCount(Self, Column, Count) end; procedure TCustomEasyListview.DoColumnGetImageIndex(Column: TEasyColumn; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); begin if Assigned(OnColumnGetImageIndex) then OnColumnGetImageIndex(Self, Column, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoColumnGetImageList(Column: TEasyColumn; var ImageList: TCustomImageList); begin if Assigned(OnColumnGetImageList) then OnColumnGetImageList(Self, Column, ImageList) end; procedure TCustomEasyListview.DoColumnImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin if Assigned(OnColumnImageDraw) then OnColumnImageDraw(Self, Column, ACanvas, RectArray, AlphaBlender) end; procedure TCustomEasyListview.DoColumnImageGetSize(Column: TEasyColumn; var ImageWidth, ImageHeight: Integer); begin if Assigned(OnColumnImageGetSize) then OnColumnImageGetSize(Self, Column, ImageWidth, ImageHeight) end; procedure TCustomEasyListview.DoColumnImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin if Assigned(OnColumnImageDrawIsCustom) then OnColumnImageDrawIsCustom(Self, Column, IsCustom) end; procedure TCustomEasyListview.DoColumnInitialize(Column: TEasyColumn); begin if Assigned(OnColumnInitialize) then OnColumnInitialize(Self, Column) end; procedure TCustomEasyListview.DoColumnLoadFromStream(Column: TEasyColumn; S: TStream; Version: Integer); begin if Assigned(OnColumnLoadFromStream) then OnColumnLoadFromStream(Self, Column, S, Version); end; procedure TCustomEasyListview.DoColumnPaintText(Column: TEasyColumn; ACanvas: TCanvas); begin if Assigned(OnColumnPaintText) then OnColumnPaintText(Self, Column, ACanvas) end; procedure TCustomEasyListview.DoColumnSaveToStream(Column: TEasyColumn; S: TStream; Version: Integer); begin if Assigned(OnColumnSaveToStream) then OnColumnSaveToStream(Self, Column, S, Version); end; procedure TCustomEasyListview.DoColumnSelectionChanged(Column: TEasyColumn); begin if Assigned(OnColumnSelectionChanged) and not (csDestroying in ComponentState) then OnColumnSelectionChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnSelectionChanging(Column: TEasyColumn; var Allow: Boolean); begin if Assigned(OnColumnSelectionChanging) and not (csDestroying in ComponentState) then OnColumnSelectionChanging(Self, Column, Allow) end; procedure TCustomEasyListview.DoColumnSetCaption(Column: TEasyColumn; const Caption: WideString); begin if Assigned(OnColumnSetCaption) then OnColumnSetCaption(Self, Column, Caption) end; procedure TCustomEasyListview.DoColumnSetDetail(Column: TEasyColumn; Line: Integer; Detail: Integer); begin if Assigned(OnColumnSetDetail) then OnColumnSetDetail(Self, Column, Line, Detail) end; procedure TCustomEasyListview.DoColumnSetDetailCount(Column: TEasyColumn; DetailCount: Integer); begin /// end; procedure TCustomEasyListview.DoColumnSetImageIndex(Column: TEasyColumn; ImageKind: TEasyImageKind; ImageIndex: Integer); begin if Assigned(OnColumnSetImageIndex) then OnColumnSetImageIndex(Self, Column, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoColumnSizeChanged(Column: TEasyColumn); begin if Assigned(OnColumnSizeChanged) and not (csDestroying in ComponentState) then OnColumnSizeChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnSizeChanging(Column: TEasyColumn; Size, NewSize: Integer; var Allow: Boolean); begin if Assigned(OnColumnSizeChanging) and not (csDestroying in ComponentState) then OnColumnSizeChanging(Self, Column, Size, NewSize, Allow) end; procedure TCustomEasyListview.DoColumnStructureChange; begin if Assigned(OnColumnStructureChange) then OnColumnStructureChange(Self) end; procedure TCustomEasyListview.DoColumnThumbnailDraw(Column: TEasyColumn; ACanvas: TCanvas; ARect: TRect; var DoDefault: Boolean); begin end; procedure TCustomEasyListview.DoColumnVisibilityChanged(Column: TEasyColumn); begin if Assigned(OnColumnVisibilityChanged) then OnColumnVisibilityChanged(Self, Column) end; procedure TCustomEasyListview.DoColumnVisibilityChanging(Column: TEasyColumn; var Allow: Boolean); begin if Assigned(OnColumnVisibilityChanging) then OnColumnVisibilityChanging(Self, Column, Allow) end; procedure TCustomEasyListview.DoContextMenu(MousePt: TPoint; var Handled: Boolean); begin if Assigned(OnContextMenu) then OnContextMenu(Self, MousePt, Handled) end; procedure TCustomEasyListview.DoColumnCustomView(Column: TEasyColumn; var ViewClass: TEasyViewColumnClass); begin if Assigned(OnColumnCustomView) then OnColumnCustomView(Self, Column, ViewClass); end; procedure TCustomEasyListview.DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); begin if Assigned(OnCustomGrid) then OnCustomGrid(Self, Group, ViewStyle, Grid) end; procedure TCustomEasyListview.DoGesture(Gesture: WideString; var Handled: Boolean); begin if Assigned(OnMouseGesture) then OnMouseGesture(Self, Gesture, Handled) end; procedure TCustomEasyListview.DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); begin if Assigned(OnGroupCustomView) then OnGroupCustomView(Self, Group, ViewStyle, View) end; procedure TCustomEasyListview.DoGroupStructureChange; begin if Assigned(OnGroupStructureChange) then OnGroupStructureChange(Self) end; procedure TCustomEasyListview.DoItemCustomView(Item: TEasyItem; ViewStyle: TEasyListStyle; var View: TEasyViewItemClass); begin if Assigned(OnItemCustomView) then OnItemCustomView(Self, Item, ViewStyle, View) end; procedure TCustomEasyListview.DoDblClick(Button: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState); begin if Assigned(OnDblClick) then OnDblClick(Self, Button, MousePos, ShiftState) end; procedure TCustomEasyListview.DoGetDragImage(Bitmap: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); begin if Assigned(OnGetDragImage) then OnGetDragImage(Self, Bitmap, DragStartPt, HotSpot, TransparentColor, Handled); end; procedure TCustomEasyListview.DoGroupClick(Group: TEasyGroup; KeyStates: TCommonKeyStates; HitTest: TEasyGroupHitTestInfoSet); begin if Assigned(OnGroupClick) then OnGroupClick(Self, Group, KeyStates, HitTest) end; procedure TCustomEasyListview.DoGroupCollapse(Group: TEasyGroup); begin if Assigned(OnGroupCollapse) and not (csDestroying in ComponentState) then OnGroupCollapse(Self, Group); end; procedure TCustomEasyListview.DoGroupCollapsing(Group: TEasyGroup; var Allow: Boolean); begin if Assigned(OnGroupCollapsing) and not (csDestroying in ComponentState) then OnGroupCollapsing(Self, Group, Allow); end; function TCustomEasyListview.DoGroupCompare(Column: TEasyColumn; Group1, Group2: TEasyGroup): Integer; begin if Assigned(OnGroupCompare) then Result := OnGroupCompare(Self, Group1, Group2) else Result := DefaultSort(Column, Group1, Group2) end; procedure TCustomEasyListview.DoGroupContextMenu(HitInfo: TEasyHitInfoGroup; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean); begin if Assigned(OnGroupContextMenu) then OnGroupContextMenu(Self, HitInfo, WindowPoint, Menu, Handled); end; procedure TCustomEasyListview.DoGroupDblClick(Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoGroup); begin if Assigned(OnGroupDblClick) then OnGroupDblClick(Self, Button, MousePos, HitInfo) end; procedure TCustomEasyListview.DoGroupExpand(Group: TEasyGroup); begin Groups.Rebuild; if Assigned(OnGroupExpand) then OnGroupExpand(Self, Group) end; procedure TCustomEasyListview.DoGroupExpanding(Group: TEasyGroup; var Allow: Boolean); begin if Assigned(OnGroupExpanding) then OnGroupExpanding(Self, Group, Allow) end; procedure TCustomEasyListview.DoGroupHotTrack(Group: TEasyGroup; State: TEasyHotTrackstate; MousePos: TPoint); begin if Assigned(OnGroupHotTrack) then OnGroupHotTrack(Self, Group, State, MousePos) end; procedure TCustomEasyListview.DoGroupFreeing(Group: TEasyGroup); begin if Assigned(OnGroupFreeing) then OnGroupFreeing(Self, Group) end; procedure TCustomEasyListview.DoGroupGetCaption(Group: TEasyGroup; var Caption: WideString); begin if Assigned(OnGroupGetCaption) then OnGroupGetCaption(Self, Group, Caption) end; procedure TCustomEasyListview.DoGroupGetDetail(Group: TEasyGroup; Line: Integer; var Detail: Integer); begin if Assigned(OnGroupGetDetail) then OnGroupGetDetail(Self, Group, Line, Detail) end; procedure TCustomEasyListview.DoGroupGetDetailCount(Group: TEasyGroup; var Count: Integer); begin if Assigned(OnGroupGetDetailCount) then OnGroupGetDetailCount(Self, Group, Count) end; procedure TCustomEasyListview.DoGroupGetImageIndex(Group: TEasyGroup; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); begin if Assigned(OnGroupGetImageIndex) then OnGroupGetImageIndex(Self, Group, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoGroupGetImageList(Group: TEasyGroup; var ImageList: TCustomImageList); begin if Assigned(OnGroupGetImageList) then OnGroupGetImageList(Self, Group, ImageList) end; procedure TCustomEasyListview.DoGroupImageDraw(Group: TEasyGroup; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin if Assigned(OnGroupImageDraw) then OnGroupImageDraw(Self, Group, ACanvas, RectArray, AlphaBlender) end; procedure TCustomEasyListview.DoGroupImageGetSize(Group: TEasyGroup; var ImageWidth, ImageHeight: Integer); begin if Assigned(OnGroupImageGetSize) then OnGroupImageGetSize(Self, Group, ImageWidth, ImageHeight) end; procedure TCustomEasyListview.DoGroupImageDrawIsCustom(Group: TEasyGroup; var IsCustom: Boolean); begin if Assigned(OnGroupImageDrawIsCustom) then OnGroupImageDrawIsCustom(Self, Group, IsCustom) end; procedure TCustomEasyListview.DoGroupInitialize(Group: TEasyGroup); begin if Assigned(OnGroupInitialize) then OnGroupInitialize(Self, Group) end; procedure TCustomEasyListview.DoGroupLoadFromStream(Group: TEasyGroup; S: TStream; Version: Integer); begin if Assigned(OnGroupLoadFromStream) then OnGroupLoadFromStream(Self, Group, S, Version) end; procedure TCustomEasyListview.DoGroupPaintText(Group: TEasyGroup; ACanvas: TCanvas); begin if Assigned(OnGroupPaintText) then OnGroupPaintText(Self, Group, ACanvas) end; procedure TCustomEasyListview.DoGroupSaveToStream(Group: TEasyGroup; S: TStream; Version: Integer); begin if Assigned(OnGroupSaveToStream) then OnGroupSaveToStream(Self, Group, S, Version) end; procedure TCustomEasyListview.DoGroupSelectionChanged(Group: TEasyGroup); begin if Assigned(OnGroupSelectionChanged) then OnGroupSelectionChanged(Self, Group) end; procedure TCustomEasyListview.DoGroupSelectionChanging(Group: TEasyGroup; var Allow: Boolean); begin if Assigned(OnGroupSelectionChanging) then OnGroupSelectionChanging(Self, Group, Allow) end; procedure TCustomEasyListview.DoGroupSetCaption(Group: TEasyGroup; const Caption: WideString); begin if Assigned(OnGroupSetCaption) then OnGroupSetCaption(Self, Group, Caption) end; procedure TCustomEasyListview.DoGroupSetDetailCount(Group: TEasyGroup; DetailCount: Integer); begin /// end; procedure TCustomEasyListview.DoGroupSetImageIndex(Group: TEasyGroup; ImageKind: TEasyImageKind; ImageIndex: Integer); begin if Assigned(OnGroupSetImageIndex) then OnGroupSetImageIndex(Self, Group, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoGroupSetDetail(Group: TEasyGroup; Line: Integer; Detail: Integer); begin if Assigned(OnGroupSetDetail) then OnGroupSetDetail(Self, Group, Line, Detail) end; procedure TCustomEasyListview.DoGroupThumbnailDraw(Group: TEasyGroup; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not implemented end; procedure TCustomEasyListview.DoGroupVisibilityChanged(Group: TEasyGroup); begin if Assigned(OnGroupVisibilityChanged) and not (csDestroying in ComponentState) then OnGroupVisibilityChanged(Self, Group) end; procedure TCustomEasyListview.DoGroupVisibilityChanging(Group: TEasyGroup; var Allow: Boolean); begin if Assigned(OnGroupVisibilityChanging) and not (csDestroying in ComponentState) then OnGroupVisibilityChanging(Self, Group, Allow) end; procedure TCustomEasyListview.DoHeaderDblClick(Button: TCommonMouseButton; MousePos: TPoint; ShiftState: TShiftState); begin if Assigned(OnHeaderDblClick) then OnHeaderDblClick(Self, Button, MousePos, ShiftState) end; procedure TCustomEasyListview.DoHintCustomInfo(TargetObj: TEasyCollectionItem; const Info: TEasyHintInfo); begin if Assigned(OnHintCustomInfo) then OnHintCustomInfo(Self, TargetObj, Info); end; procedure TCustomEasyListview.DoHintCustomDraw(TargetObj: TEasyCollectionItem; const Info: TEasyHintInfo); begin if Assigned(OnHintCustomDraw) then OnHintCustomDraw(Self, TargetObj, Info); end; procedure TCustomEasyListview.DoHintPopup(TargetObj: TEasyCollectionItem; HintType: TEasyHintType; MousePos: TPoint; var AText: WideString; var HideTimeout, ReshowTimeout: Integer; var Allow: Boolean); begin if Assigned(OnHintPopup) then OnHintPopup(Self, TargetObj, HintType, MousePos, AText, HideTimeout, ReshowTimeout, Allow) end; procedure TCustomEasyListview.DoHintShowPause(HintShowingNow: Boolean; var PauseTime: Integer); begin if Assigned(OnHintPauseTime) then OnHintPauseTime(Self, HintShowingNow, PauseTime) end; procedure TCustomEasyListview.DoIncrementalSearch(Item: TEasyItem; const SearchBuffer: WideString; var CompareResult: Integer); var Handled: Boolean; begin CompareResult := 0; Handled := False; if Assigned(OnIncrementalSearch) then OnIncrementalSearch(Item, SearchBuffer, Handled, CompareResult); if not Handled then CompareResult := WideIncrementalSearch(Item.Caption, SearchBuffer) end; procedure TCustomEasyListview.DoItemCheckChanged(Item: TEasyItem); begin if Assigned(OnItemCheckChange) and not (csDestroying in ComponentState) then OnItemCheckChange(Self, Item) end; procedure TCustomEasyListview.DoItemCheckChanging(Item: TEasyItem; var Allow: Boolean); begin if Assigned(OnItemCheckChanging) and not (csDestroying in ComponentState) then OnItemCheckChanging(Self, Item, Allow); end; procedure TCustomEasyListview.DoItemClick(Item: TEasyItem; KeyStates: TCommonKeyStates; HitInfo: TEasyItemHitTestInfoSet); begin if Assigned(OnItemClick) then OnItemClick(Self, Item, KeyStates, HitInfo) end; function TCustomEasyListview.DoItemCompare(Column: TEasyColumn; Group: TEasyGroup; Item1, Item2: TEasyItem): Integer; var DoDefault: Boolean; begin Result := 0; DoDefault := True; if Assigned(OnItemCompare) then Result := OnItemCompare(Self, Column, Group, Item1, Item2, DoDefault); if DoDefault then Result := DefaultSort(Column, Item1, Item2) end; procedure TCustomEasyListview.DoItemContextMenu(HitInfo: TEasyHitInfoItem; WindowPoint: TPoint; var Menu: TPopupMenu; var Handled: Boolean); begin Menu := nil; if Assigned(OnItemContextMenu) then OnItemContextMenu(Self, HitInfo, WindowPoint, Menu, Handled); end; procedure TCustomEasyListview.DoItemCreateEditor(Item: TEasyItem; var Editor: IEasyCellEditor); begin if Assigned(OnItemCreateEditor) then OnItemCreateEditor(Self, Item, Editor); if not Assigned(Editor) then begin if View in MULTILINEVIEWS then Editor := TEasyMemoEditor.Create else Editor := TEasyStringEditor.Create; end end; procedure TCustomEasyListview.DoItemDblClick(Button: TCommonMouseButton; MousePos: TPoint; HitInfo: TEasyHitInfoItem); begin if Assigned(OnItemDblClick) then OnItemDblClick(Self, Button, MousePos, HitInfo) end; procedure TCustomEasyListview.DoItemEditBegin(Item: TEasyItem; var Column: Integer; var Allow: Boolean); begin if Assigned(OnItemEditBegin) then OnItemEditBegin(Self, Item, Column, Allow) end; procedure TCustomEasyListview.DoItemEdited(Item: TEasyItem; var NewValue: Variant; var Accept: Boolean); begin if Assigned(OnItemEdited) then OnItemEdited(Self, Item, NewValue, Accept); end; procedure TCustomEasyListview.DoItemEditEnd(Item: TEasyItem); begin if Assigned(OnItemEditEnd) then OnItemEditEnd(Self, Item); end; procedure TCustomEasyListview.DoItemEnableChanged(Item: TEasyItem); begin if Assigned(OnItemEnableChange) then OnItemEnableChange(Self, Item) end; procedure TCustomEasyListview.DoItemEnableChanging(Item: TEasyItem; var Allow: Boolean); begin if Assigned(OnItemEnableChanging) then OnItemEnableChanging(Self, Item, Allow) end; procedure TCustomEasyListview.DoItemFocusChanged(Item: TEasyItem); begin if Assigned(OnItemFocusChanged) then OnItemFocusChanged(Self, Item) end; procedure TCustomEasyListview.DoItemFocusChanging(Item: TEasyItem; var Allow: Boolean); begin if Assigned(OnItemFocusChanging) then OnItemFocusChanging(Self, Item, Allow) end; procedure TCustomEasyListview.DoItemFreeing(Item: TEasyItem); begin if Assigned(OnItemFreeing) then OnItemFreeing(Self, Item) end; procedure TCustomEasyListview.DoItemGetCaption(Item: TEasyItem; Column: Integer; var ACaption: WideString); begin if Assigned(OnItemGetCaption) then OnItemGetCaption(Self, Item, Column, ACaption) end; procedure TCustomEasyListview.DoItemGetEditCaption(Item: TEasyItem; Column: TEasyColumn; var Caption: WideString); begin if Assigned(OnItemGetEditCaption) then OnItemGetEditCaption(Self, Item, Column, Caption) end; procedure TCustomEasyListview.DoItemGetEditMenu(Editor: TEasyBaseEditor; var Menu: TPopupMenu); begin if Assigned(OnItemGetEditMenu) then OnItemGetEditMenu(Self, Editor, Menu) end; procedure TCustomEasyListview.DoItemGetGroupKey(Item: TEasyItem; FocusedColumn: Integer; var Key: LongWord); begin if Assigned(OnItemGetGroupKey) then OnItemGetGroupKey(Self, Item, FocusedColumn, Key) end; procedure TCustomEasyListview.DoItemGetImageIndex(Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; var ImageIndex: TCommonImageIndexInteger); begin if Assigned(OnItemGetImageIndex) then OnItemGetImageIndex(Self, Item, Column, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoItemGetImageList(Item: TEasyItem; Column: Integer; var ImageList: TCustomImageList); begin if Assigned(OnItemGetImageList) then OnItemGetImageList(Self, Item, Column, ImageList) end; procedure TCustomEasyListview.DoItemGetStateImageList(Item: TEasyItem; Column: Integer; var ImageList: TCustomImageList); begin if Assigned(OnItemGetStateImageList) then OnItemGetStateImageList(Self, Item, Column, ImageList) end; procedure TCustomEasyListview.DoItemGetTileDetail(Item: TEasyItem; Line: Integer; var Detail: Integer); begin if Assigned(OnItemGetTileDetail) then OnItemGetTileDetail(Self, Item, Line, Detail) end; procedure TCustomEasyListview.DoItemGetTileDetailCount(Item: TEasyItem; var Count: Integer); begin if Assigned(OnItemGetTileDetailCount) then OnItemGetTileDetailCount(Self, Item, Count) end; procedure TCustomEasyListview.DoItemImageDraw(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin if Assigned(OnItemImageDraw) then OnItemImageDraw(Self, Item, Column, ACanvas, RectArray, AlphaBlender) end; procedure TCustomEasyListview.DoItemImageGetSize(Item: TEasyItem; Column: TEasyColumn; var ImageWidth, ImageHeight: Integer); begin if Assigned(OnItemImageGetSize) then OnItemImageGetSize(Self, Item, Column, ImageWidth, ImageHeight) end; procedure TCustomEasyListview.DoItemImageDrawIsCustom(Column: TEasyColumn; Item: TEasyItem; var IsCustom: Boolean); begin if Assigned(OnItemImageDrawIsCustom) then OnItemImageDrawIsCustom(Self, Item, Column, IsCustom) end; procedure TCustomEasyListview.DoItemHotTrack(Item: TEasyItem; State: TEasyHotTrackstate; MousePos: TPoint); begin if HotTrack.Enabled then if Assigned(OnItemHotTrack) then OnItemHotTrack(Self, Item, State, MousePos) end; procedure TCustomEasyListview.DoItemInitialize(Item: TEasyItem); begin if Assigned(OnItemInitialize) then OnItemInitialize(Self, Item) end; procedure TCustomEasyListview.DoItemLoadFromStream(Item: TEasyItem; S: TStream; Version: Integer); begin if Assigned(OnItemLoadFromStream) then OnItemLoadFromStream(Self, Item, S, Version) end; procedure TCustomEasyListview.DoItemMouseDown(Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean); begin if Assigned(OnItemMouseDown) then OnItemMouseDown(Self, Item, Button, DoDefault) end; procedure TCustomEasyListview.DoItemMouseUp(Item: TEasyItem; Button: TCommonMouseButton; var DoDefault: Boolean); begin if Assigned(OnItemMouseUp) then OnItemMouseUp(Self, Item, Button, DoDefault) end; procedure TCustomEasyListview.DoItemPaintText(Item: TEasyItem; Position: Integer; ACanvas: TCanvas); begin if Assigned(OnItemPaintText) then OnItemPaintText(Self, Item, Position, ACanvas) end; procedure TCustomEasyListview.DoItemSaveToStream(Item: TEasyItem; S: TStream; Version: Integer); begin if Assigned(OnItemSaveToStream) then OnItemSaveToStream(Self, Item, S, Version) end; procedure TCustomEasyListview.DoItemSelectionChanged(Item: TEasyItem); begin if Assigned(OnItemSelectionChanged) and not (csDestroying in ComponentState) then OnItemSelectionChanged(Self, Item) end; procedure TCustomEasyListview.DoItemSelectionChanging(Item: TEasyItem; var Allow: Boolean); begin if Assigned(OnItemSelectionChanging) and not (csDestroying in ComponentState) then OnItemSelectionChanging(Self, Item, Allow) end; procedure TCustomEasyListview.DoItemSelectionsChanged; begin if Assigned(OnItemSelectionsChanged) and not (csDestroying in ComponentState) then OnItemSelectionsChanged(Self) end; procedure TCustomEasyListview.DoItemSetCaption(Item: TEasyItem; Column: Integer; const Caption: WideString); begin if Assigned(OnItemSetCaption) then OnItemSetCaption(Self, Item, Column, Caption) end; procedure TCustomEasyListview.DoItemSetGroupKey(Item: TEasyItem; FocusedColumn: Integer; Key: LongWord); begin if Assigned(OnItemSetGroupKey) then OnItemSetGroupKey(Self, Item, FocusedColumn, Key) end; procedure TCustomEasyListview.DoItemSetImageIndex(Item: TEasyItem; Column: Integer; ImageKind: TEasyImageKind; ImageIndex: Integer); begin if Assigned(OnItemSetImageIndex) then OnItemSetImageIndex(Self, Item, Column, ImageKind, ImageIndex) end; procedure TCustomEasyListview.DoItemSetTileDetail(Item: TEasyItem; Line: Integer; Detail: Integer); begin if Assigned(OnItemSetTileDetail) then OnItemSetTileDetail(Self, Item, Line, Detail) end; procedure TCustomEasyListview.DoItemSetTileDetailCount(Item: TEasyItem; Detail: Integer); begin // end; procedure TCustomEasyListview.DoItemStructureChange; begin if Assigned(OnItemStructureChange) then OnItemStructureChange(Self) end; procedure TCustomEasyListview.DoItemThumbnailDraw(Item: TEasyItem; ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin if Assigned(OnItemThumbnailDraw) then OnItemThumbnailDraw(Self, Item, ACanvas, ARect, AlphaBlender, DoDefault) end; procedure TCustomEasyListview.DoItemVisibilityChanged(Item: TEasyItem); begin if Assigned(OnItemVisibilityChanged) and not (csDestroying in ComponentState) then OnItemVisibilityChanged(Self, Item) end; procedure TCustomEasyListview.DoItemVisibilityChanging(Item: TEasyItem; var Allow: Boolean); begin if Assigned(OnItemVisibilityChanging) and not (csDestroying in ComponentState)then OnItemVisibilityChanging(Self, Item, Allow) end; procedure TCustomEasyListview.DoKeyAction(var CharCode: Word; var Shift: TShiftState; var DoDefault: Boolean); begin if Assigned(OnKeyAction) then OnKeyAction(Self, CharCode, Shift, DoDefault) end; procedure TCustomEasyListview.DoOLEDragEnd(ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); begin if Assigned(OnOLEDragEnd) then OnOLEDragEnd(Self, ADataObject, DragResult, ResultEffect, KeyStates); end; procedure TCustomEasyListview.DoOLEDragStart(ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); begin if Assigned(OnOLEDragStart) then OnOLEDragStart(Self, ADataObject, AvailableEffects, AllowDrag); end; procedure TCustomEasyListview.DoOLEDropSourceGiveFeedback( Effect: TCommonDropEffects; var UseDefaultCursors: Boolean); // When the control is the OLE Drag source, this is called when OLE subsystem // wants to display a different drag cursor (different than the drag image). By // default the built in cursors are used but the application may set the cursors // itself in this event begin if Assigned(OnOLEGiveFeedback) then OnOLEGiveFeedback(Self, Effect, UseDefaultCursors) end; procedure TCustomEasyListview.DoOLEDropSourceQueryContineDrag( EscapeKeyPressed: Boolean; KeyStates: TCommonKeyStates; var QueryResult: TEasyQueryDragResult); // When the control is the OLE Drag source the OLE subsystem calls back to the // source to query if the source would like to contine the drag, quit the drag, // or drop the object where it is. begin if Assigned(OnOLEQueryContineDrag) then OnOLEQueryContineDrag(Self, EscapeKeyPressed, KeyStates, QueryResult) end; procedure TCustomEasyListview.DoOLEDropTargetDragDrop(DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect; var Handled: Boolean); // When the control is the OLE Drag target this is called when the data object is // dropped on the control begin if Assigned(OnOLEDragDrop) then OnOLEDragDrop(Self, DataObject, KeyState, WindowPt, AvailableEffects, DesiredEffect, Handled) end; procedure TCustomEasyListview.DoOLEDropTargetDragEnter(DataObject: IDataObject; KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect); // When the control is the OLE Drag target this is called when the drag object // first enters the controls client window begin if Assigned(OnOLEDragEnter) then OnOLEDragEnter(Self, DataObject, KeyState, WindowPt, AvailableEffects, DesiredEffect) end; procedure TCustomEasyListview.DoOLEDropTargetDragLeave; // When the control is the OLE Drag target this is called when the data object // leaves the controls client window begin if Assigned(OnOLEDragLeave) then OnOLEDragLeave(Self) end; procedure TCustomEasyListview.DoOLEDropTargetDragOver(KeyState: TCommonKeyStates; WindowPt: TPoint; AvailableEffects: TCommonDropEffects; var DesiredEffect: TCommonDropEffect); // When the control is the OLE Drag target this is called when the data object is // moving over the controls client window begin if Assigned(OnOLEDragOver) then OnOLEDragOver(Self, KeyState, WindowPt, AvailableEffects, DesiredEffect) end; procedure TCustomEasyListview.DoOLEGetCustomFormats(var Formats: TFormatEtcArray); begin if Assigned(OnOLEGetCustomFormats) then OnOLEGetCustomFormats(Self, Formats) end; procedure TCustomEasyListview.DoOLEGetData(const FormatEtcIn: TFormatEtc; var Medium: TStgMedium; var Handled: Boolean); // Called from the IDataObject when a target wants the source (us) to give it the // OLE data begin FillChar(Medium, SizeOf(Medium), #0); Handled := False; if Assigned(OnOLEGetData) then OnOLEGetData(Self, FormatEtcIn, Medium, Handled); end; procedure TCustomEasyListview.DoOLEGetDataObject(var DataObject: IDataObject); begin DataObject := nil; if Assigned(OnOLEGetDataObject) then OnOLEGetDataObject(Self, DataObject) end; procedure TCustomEasyListview.DoPaintBkGnd(ACanvas: TCanvas; AWindowRect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin if Assigned(OnPaintBkGnd) then OnPaintBkGnd(Self, ACanvas, AWindowRect, AlphaBlender, DoDefault) end; procedure TCustomEasyListview.DoPaintHeaderBkGnd(ACanvas: TCanvas; ARect: TRect; var Handled: Boolean); begin if Assigned(OnPaintHeaderBkGnd) then OnPaintHeaderBkGnd(Self, ACanvas, ARect, Handled) end; procedure TCustomEasyListview.DoPaintRect(ACanvas: TCanvas; WindowClipRect: TRect; SelectedOnly: Boolean); // Paints the control defined by Rect to the passed canvas. Called from the // WM_PAINT message or can be called to make a snapshot of the control // ARect is in Window coordinates. procedure PaintAndGetNextColumn(var Column: TEasyColumn; Item: TEasyItem; ItemRect, ViewClipRect: TRect; OrgPt: TPoint; Clip, ForceSelectionRectDraw: Boolean); begin ClipHeader(ACanvas, True); SetWindowOrgEx(ACanvas.Handle, Scrollbars.OffsetX, Scrollbars.OffsetY - Header.RuntimeHeight, nil); if Clip then begin IntersectRect(ItemRect, ItemRect, ViewClipRect); IntersectClipRect(ACanvas.Handle, ItemRect.Left, ItemRect.Top, ItemRect.Right, ItemRect.Bottom); end; Item.Paint(ACanvas, ViewClipRect, Column, ForceSelectionRectDraw); Column := Header.NextColumnInRect(Column, ViewClipRect); end; procedure PaintReportView(Item: TEasyItem; ViewClipRect: TRect; OrgPt: TPoint); var R: TRect; Column: TEasyColumn; RectArray: TEasyRectArrayObject; begin Column := Header.FirstColumnInRect(ViewClipRect); if Item.Selected or Item.Hilighted then begin if Selection.GroupSelections then PaintAndGetNextColumn(Column, Item, Item.DisplayRect, ViewClipRect, OrgPt, False, True) else if Selection.FullRowSelect then PaintAndGetNextColumn(Column, Item, Item.DisplayRect, ViewClipRect, OrgPt, True, True); end; while Assigned(Column) do PaintAndGetNextColumn(Column, Item, Item.DisplayRect, ViewClipRect, OrgPt, False, False); // Special processing for Full Row Select if Selection.FullRowSelect and Focused and Selection.UseFocusRect and Item.Focused and not SelectedOnly then begin // Draw a Focus Rectangle around focused item ClipHeader(ACanvas, True); ACanvas.Brush.Color := Color; ACanvas.Font.Color := clBlack; Item.ItemRectArray(Header.FirstColumnByPosition, ACanvas, RectArray); R := Selection.FocusedItem.DisplayRect; if not Selection.FullCellPaint then if not Selection.FullItemPaint then R.Left := RectArray.SelectionRect.Left; DrawFocusRect(ACanvas.Handle, R); end end; var Group, FirstVisibleGroup: TEasyGroup; Item: TEasyItem; Column: TEasyColumn; OrgPt: TPoint; ViewClipRect, R: TRect; begin GroupCollapseButton.Canvas.Lock; GroupExpandButton.Canvas.Lock; GetWindowOrgEx(Canvas.Handle, OrgPt); try // Header accounted for in the DC Offset ViewClipRect := Scrollbars.MapWindowRectToViewRect(WindowClipRect, True); if not SelectedOnly then begin if Assigned(Background) and not SelectedOnly then BackGround.PaintTo(ACanvas, WindowClipRect, False); SelectClipRgn(Canvas.Handle, 0); if ScrollHeaderHorz then begin SetWindowOrgEx(ACanvas.Handle, Scrollbars.OffsetX, 0, nil); if ViewSupportsHeader and Header.Visible then Header.PaintTo(ACanvas, ViewClipRect); end else begin if ViewSupportsHeader and Header.Visible then Header.PaintTo(ACanvas, Rect(0, 0, ClientWidth, Header.RuntimeHeight)); end; ClipHeader(ACanvas, True); SetWindowOrgEx(ACanvas.Handle, Scrollbars.OffsetX, Scrollbars.OffsetY - Header.RuntimeHeight, nil); Group := Groups.FirstGroupInRect(ViewClipRect); while Assigned(Group) do begin Group.Paint(egmeBackground, Group.DisplayRect, ACanvas); Group.Paint(egmeTop, Group.BoundsRectTopMargin, ACanvas); Group.Paint(egmeBottom, Group.BoundsRectBottomMargin, ACanvas); Group.Paint(egmeLeft, Group.BoundsRectLeftMargin, ACanvas); Group.Paint(egmeRight, Group.BoundsRectRightMargin, ACanvas); Group.Paint(egmeForeground, Group.DisplayRect, ACanvas); Group := Groups.NextGroupInRect(Group, ViewClipRect) end; end; SetWindowOrgEx(ACanvas.Handle, Scrollbars.OffsetX, Scrollbars.OffsetY - Header.RuntimeHeight, nil); SelectClipRgn(ACanvas.Handle, 0); // Paint the colored column background for the focused node if not SelectedOnly and ((View = elsReport) or (View = elsGrid)) then begin if PaintInfoColumn.HilightFocused and Assigned(Selection.FocusedColumn) then begin if Selection.FocusedColumn.SortDirection <> esdNone then begin ACanvas.Brush.Color := PaintInfoColumn.HilightFocusedColor; Group := Groups.FirstVisibleGroup; while Assigned(Group) do begin R := Selection.FocusedColumn.DisplayRect; R.Top := Scrollbars.OffsetY; R.Bottom := Scrollbars.OffsetY + (ClientHeight - Header.RuntimeHeight); if IntersectRect(R, ViewClipRect, R) then if IntersectRect(R, R, Group.BoundsRectBkGnd) then ACanvas.FillRect(R); Group := Groups.NextVisibleGroup(Group) end end end end; Item := Groups.FirstItemInRect(ViewClipRect); // If GroupSelection we always need to paint the first item if Assigned(Item) and (View = elsReport) and Selection.GroupSelections then begin // Need to paint the first item in a selection group if Assigned(Item.SelectionGroup) then begin if not SelectedOnly or (SelectedOnly and Item.Selected) then begin PaintReportView(Item.SelectionGroup.FirstItem, ViewClipRect, OrgPt); // Don't Repaint it if Item.SelectionGroup.FirstItem = Item then Item := Groups.NextItemInRect(Item, ViewClipRect); end end end; while Assigned(Item) do begin ClipHeader(ACanvas, True); // Need to paint the focused item last if its text may overlap another cell when focused if not Item.Focused or not Item.View.OverlappedFocus then begin if not SelectedOnly or (SelectedOnly and Item.Selected) then begin if View = elsReport then PaintReportView(Item, ViewClipRect, OrgPt) else Item.Paint(ACanvas, ViewClipRect, nil, False); end end; Item := Groups.NextItemInRect(Item, ViewClipRect); end; if Assigned(Selection.FocusedItem) then if Selection.FocusedItem.View.OverlappedFocus then Selection.FocusedItem.Paint(ACanvas, ViewClipRect, nil, False); if not SelectedOnly and ((View = elsReport) or (View = elsGrid)) then begin // Paint the Grid Lines if PaintInfoItem.GridLines then begin ClipHeader(ACanvas, True); FirstVisibleGroup := Groups.FirstVisibleGroup; ACanvas.Pen.Color := PaintInfoItem.GridLineColor; Column := Header.FirstColumnInRect(ViewClipRect); while Assigned(Column) do begin Group := FirstVisibleGroup; while Assigned(Group) do begin R := Column.DisplayRect; ACanvas.MoveTo(R.Right, Group.BoundsRectBkGnd.Top); ACanvas.LineTo(R.Right, Group.BoundsRectBkGnd.Bottom); Group := Groups.NextVisibleGroup(Group) end; Column := Header.NextColumnInRect(Column, ViewClipRect); end; Item := Groups.FirstItemInRect(ViewClipRect); while Assigned(Item) do begin R := Item.DisplayRect; ACanvas.MoveTo(Scrollbars.OffsetX, R.Bottom-1); ACanvas.LineTo(Scrollbars.OffsetX + ClientWidth, R.Bottom-1); Item := Groups.NextItemInRect(Item, ViewClipRect) end end end; finally SetWindowOrgEx(ACanvas.Handle, OrgPt.X, OrgPt.Y, nil); GroupCollapseButton.Canvas.UnLock; GroupExpandButton.Canvas.UnLock; end end; procedure TCustomEasyListview.DoQueryOLEData(const FormatEtcIn: TFormatEtc; var FormatAvailable: Boolean; var Handled: Boolean); // Called from the IDataObject when a target wants the source (us) to tell it // what formats the DataObject supports begin Handled := False; FormatAvailable := False; if Assigned(OnOLEQueryData) then OnOLEQueryData(Self, FormatEtcIn, FormatAvailable, Handled) end; procedure TCustomEasyListview.DoResize(DeltaX, DeltaY: Integer); begin end; procedure TCustomEasyListview.DoScroll(DeltaX, DeltaY: Integer); begin if Assigned(OnScroll) then OnScroll(Self, DeltaX, DeltaY) end; procedure TCustomEasyListview.DoThreadCallback(var Msg: TWMThreadRequest); begin end; procedure TCustomEasyListview.DoUpdate; begin if not(csDestroying in ComponentState) then begin Groups.Rebuild(True); Scrollbars.ReCalculateScrollbars(True, False); end; end; procedure TCustomEasyListview.DoViewChange; begin if Assigned(OnViewChange) then OnViewChange(Self) end; procedure TCustomEasyListview.EndUpdate(Invalidate: Boolean = True); begin // Sort.EndUpdate; inherited EndUpdate(Invalidate); end; procedure TCustomEasyListview.FinalizeDrag(WindowPoint: TPoint; KeyState: TCommonKeyStates); // Called after the mouse is released and a Drag Selection or a D&D operation // was completed. It cleans up and resets the flags. begin // Do these after the flags have been reset in case a resulting operation of // these calls checks if the dragging is still occuring if ebcsDragging in States then begin Exclude(FStates, ebcsDragging); DragManager.DragEnd(Canvas, WindowPoint, KeyState); end; if ebcsDragSelecting in States then begin Exclude(FStates, ebcsDragSelecting); DragRect.DragEnd(Canvas, WindowPoint, KeyState); end; ClearStates; Mouse.Capture := 0; end; procedure TCustomEasyListview.HandleDblClick(Button: TCommonMouseButton; Msg: TWMMouse); var Group: TEasyGroup; Keys: TCommonKeyStates; GroupHitInfo: TEasyGroupHitTestInfoSet; GroupInfo: TEasyHitInfoGroup; Item: TEasyItem; ItemHitInfo: TEasyItemHitTestInfoSet; ItemInfo: TEasyHitInfoItem; ViewPt: TPoint; begin Keys := KeyToKeyStates(Msg.Keys); ViewPt := Scrollbars.MapWindowToView(Msg.Pos); if ViewSupportsHeader and (Header.Visible) and (Msg.YPos < Header.Height) then Header.WMLButtonDblClk(Msg) else begin Item := Groups.ItembyPoint(ViewPt); DoDblClick(Button, SmallPointToPoint(Msg.Pos), KeysToShiftState(Msg.Keys)); if Assigned(Item) then begin Item.HitTestAt(ViewPt, ItemHitInfo); ItemInfo.Group := Item.OwnerGroup; ItemInfo.Item := Item; if ViewSupportsHeader then ItemInfo.Column := Header.Columns.ColumnByPoint(ViewPt) else ItemInfo.Column := nil; ItemInfo.HitInfo := ItemHitInfo; DoItemDblClick(Button, SmallPointToPoint(Msg.Pos), ItemInfo) end else begin Group := Groups.GroupByPoint(ViewPt); if Assigned(Group) then begin Group.HitTestAt(ViewPt, GroupHitInfo); GroupInfo.Group := Group; GroupInfo.HitInfo := GroupHitInfo; DoGroupDblClick(Button, SmallPointToPoint(Msg.Pos), GroupInfo) end end end end; procedure TCustomEasyListview.HandleKeyDown(Msg: TWMKeyDown); procedure MoveFocus(KeyStates: TShiftState; Item: TEasyItem); begin if Assigned(Item) then begin // Do this underhanded so we don't cause a grid rebuild but will keep the // window from getting WM_PAINT messages until we are done Inc(FUpdateCount); try if Selection.FocusedItem <> Item then begin if not Selection.Enabled and Selection.UseFocusRect then Selection.FocusedItem := Item else if ssCtrl in KeyStates then Selection.FocusedItem := Item else if ssShift in KeyStates then begin if Assigned(Selection.AnchorItem) then begin Selection.SelectRange(Selection.AnchorItem, Item, Selection.RectSelect, True); Selection.FocusedItem := Item; Selection.FocusedItem.Selected := True; end else begin Selection.ClearAll; Selection.FocusedItem := Item; Selection.FocusedItem.Selected := True; end end else begin Selection.ClearAll; Selection.FocusedItem := Item; Selection.FocusedItem.Selected := True; Selection.AnchorItem := Selection.FocusedItem; end; end; finally if Assigned(Selection.FocusedItem) then begin if Selection.FocusedItem.DisplayRect.Top < ClientInViewportCoords.Top + (RectHeight(ClientInViewportCoords) div 2) then Selection.FocusedItem.MakeVisible(emvAuto {emvTop}) else Selection.FocusedItem.MakeVisible(emvAuto{emvBottom}); end; Dec(FUpdateCount); UpdateWindow(Handle); end end end; function FocusFirst: Boolean; var Item: TEasyItem; begin Result := False; if not Assigned(Selection.FocusedItem) then begin Item := Groups.FirstVisibleItem; if Assigned(Item) then begin Selection.FocusedItem := Item; Result := True end end end; var Item: TEasyItem; KeyStates: TShiftState; Handled, Mark: Boolean; begin KeyStates := KeyDataToShiftState(Msg.KeyData); Selection.IncMultiChangeCount; try case Msg.CharCode of VK_RIGHT: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdRight); MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetX := Scrollbars.OffsetX + 1; end; VK_LEFT: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdLeft); MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetX := Scrollbars.OffsetX - 1; end; VK_UP: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdUp); MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetY := Scrollbars.OffsetY + 1; end; VK_DOWN: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdDown); // Special case with one item if not Assigned(Item) and (Selection.Count = 0) and (Groups.ItemCount = 1) then begin Selection.FocusedItem := nil; Item := Groups.FirstItem; end; MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetY := Scrollbars.OffsetY + 1; end; VK_HOME: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.FirstVisibleItem; MoveFocus(KeyStates, Item); end end else begin Scrollbars.OffsetX := 0; Scrollbars.OffsetY := 0; end end; VK_END: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.LastVisibleItem; MoveFocus(KeyStates, Item); end end else begin Scrollbars.OffsetX := Scrollbars.MaxOffsetX; Scrollbars.OffsetY := Scrollbars.MaxOffsetY; end end; VK_NEXT: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdPageDown); MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetY := Scrollbars.OffsetY + ClientHeight; end; VK_PRIOR: begin if Selection.Enabled or Selection.UseFocusRect then begin if not FocusFirst then begin Item := Groups.AdjacentItem(Selection.FocusedItem, acdPageUp); MoveFocus(KeyStates, Item); end end else Scrollbars.OffsetY := Scrollbars.OffsetY - ClientHeight; end; VK_F2: begin if Assigned(Selection.FocusedItem) then begin EditManager.BeginEdit(Selection.FocusedItem, nil) end; end; VK_SPACE: begin if Assigned(Selection.FocusedItem) then if Selection.FocusedItem.PaintInfo.CheckType in [ectBox, ectRadio] then Selection.FocusedItem.Checked := not Selection.FocusedItem.Checked end; VK_ADD: begin if (ssCtrl in KeyStates) then AutoFitAllCells(True) end; Ord('A'), Ord('a'): begin if ssCtrl in KeyStates then Selection.SelectAll end; Ord('C'), Ord('c'): // Ctrl + 'C' Copy begin if ssCtrl in KeyStates then begin Handled := False; DoClipboardCopy(Handled); if not Handled then CopyToClipboard; end end; Ord('X'), Ord('x'): // Ctrl + 'X' Cut begin if ssCtrl in KeyStates then begin Handled := False; Mark := True; DoClipboardCut(Mark, Handled); if not Handled then CutToClipboard else if Mark then MarkSelectedCut end end; Ord('V'), Ord('v'): // // Ctrl + 'V' Paste begin if ssCtrl in KeyStates then begin Handled := False; DoClipboardPaste(Handled); if not Handled then PasteFromClipboard; end end; VK_ESCAPE: begin CancelCut; Invalidate; end; end finally Selection.DecMultiChangeCount end end; procedure TCustomEasyListview.HandleMouseDown(Button: TCommonMouseButton; Msg: TWMMouse); var WindowPt: TPoint; KeyState: TCommonKeyStates; Group: TEasyGroup; Item: TEasyItem; GroupHitInfo: TEasyGroupHitTestInfoSet; ItemHitInfo: TEasyItemHitTestInfoSet; MouseDown, StartTimer, CtlDown, ShiftDown: Boolean; Allow, DoDefaultItemDown: Boolean; begin Item := nil; KeyState := KeyToKeyStates(Msg.Keys); WindowPt := Scrollbars.MapWindowToView(Msg.Pos); MouseDown := KeyState * [cksLButton, cksMButton, cksRButton] <> []; CtlDown := cksControl in KeyState; ShiftDown := cksShift in KeyState; Gesture.Path := ''; Group := ClickTestGroup(WindowPt, KeyState, GroupHitInfo); if Assigned(Group) then begin // First see if the group expand button or checkbox was hit if GroupTestExpand(GroupHitInfo) then begin // Only the left button can expand if Button = cmbLeft then begin // Deal with the expansion in the mouse down Allow := True; if Group.Expanded then DoGroupCollapsing(Group, Allow) else DoGroupExpanding(Group, Allow); if Allow then begin BeginUpdate; try Include(FStates, ebcsGroupExpandPending); Group.Expanded := not Group.Expanded; // Need to make sure focused item is not in the collapsed group. if not Group.Expanded and Assigned(Selection.FocusedItem) then begin if Selection.FocusedItem.OwnerGroup = Group then begin Item := Groups.NextVisibleItem(Selection.FocusedItem); while Assigned(Item) do begin if Item.Enabled then Break else Item := Groups.NextVisibleItem(Item) end; Selection.FocusedItem := Item; end end finally EndUpdate end end; end end else // Next see if it hit the Group CheckBox if egtOnCheckbox in GroupHitInfo then begin // Only the left button can Check Groups if Button = cmbLeft then begin Include(FStates, ebcsCheckboxClickPending); HotTrack.PendingObjectCheck := nil; CheckManager.PendingObject := Group; end end else begin if Group.Expanded then begin // Exhausted Group hit tests, move into Item level testing Item := ClickTestItem(WindowPt, Group, KeyState, ItemHitInfo); if Assigned(Item) then begin DoDefaultItemDown := True; DoItemMouseDown(Item, Button, DoDefaultItemDown); if DoDefaultItemDown then begin // First see it the hit was on the items check box if ehtOnCheck in ItemHitInfo then begin // Only the left button can Check Items if Button = cmbLeft then begin Include(FStates, ebcsCheckboxClickPending); HotTrack.PendingObjectCheck := nil; CheckManager.PendingObject := Item; end end else // Next see if Selection is enabled and if so handle item selection // through direct hit or drag rectangle if Selection.Enabled then begin Selection.IncMultiChangeCount; Selection.GroupSelectBeginUpdate; try if Item.SelectionHitPt(WindowPt, eshtClickselect) then begin if MouseDown and (Button in Selection.MouseButton) then begin // See if the user click on the item a second time, if so get ready for // an edit StartTimer := (Button = cmbLeft) and ((Selection.Count = 1) and ((Selection.FocusedItem = Item) and Item.EditAreaHitPt(WindowPt) and Item.Selected)) and Focused; if Selection.MultiSelect then begin // Multi Selection Mode......... if not Item.Selected and not(CtlDown or ShiftDown) then Selection.ClearAll; // Focus the item if the Ctl key is not down. It will be done in the ButtonUp event if (Selection.FocusedItem <> Item) and not CtlDown then Selection.FocusedItem := Item; if not( CtlDown or ShiftDown) then begin Selection.AnchorItem := Item; end else begin if not ShiftDown then Selection.AnchorItem := Item else Selection.SelectRange(Selection.AnchorItem, Item, Selection.RectSelect, not CtlDown); end end else begin // Single Selection Mode......... // Set the Focus to the hit item if (Selection.FocusedItem <> Item) then Selection.FocusedItem := Item; Selection.AnchorItem := Item; Selection.ClearAll; end; // CtlClick then it will be selected in the Mouse Up if not CtlDown then Item.Selected := True; // This test allows descendent to cancel out of drags incase they do something in the Focus or Selection Changing events if (((Button in DragRect.MouseButton) or (Button in DragManager.MouseButton)) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> [])) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), Item.AllowDrag(WindowPt), True); if StartTimer then begin EditManager.AutoEditStartClickPt := WindowPt; EditManager.StartAutoEditTimer; end end else begin if (Button in DragManager.MouseButton) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> []) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), True, False); end end else begin // All mouse button down actions trigger the same events // Since it is unknown what the user is trying to do yet if (Button in DragRect.MouseButton) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> []) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), False, True); end finally Selection.GroupSelectEndUpdate; Selection.DecMultiChangeCount end end else if Selection.UseFocusRect then begin if Item.SelectionHitPt(WindowPt, eshtClickselect) then Selection.FocusedItem := Item end end end else begin // All mouse button down actions trigger the same events // Since it is unknown what the user is trying to do yet if (Button in DragRect.MouseButton) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> []) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), False, True); end end else // Did not hit an anything so get ready for a drag rectangle if (Button in DragRect.MouseButton) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> []) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), False, True); end; end else begin // All mouse button down actions trigger the same events // Since it is unknown what the user is trying to do yet // Did not hit a group so get ready for a drag rectangle if (Button in DragRect.MouseButton) and (States * [ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] <> []) then InitializeDragPendings(Item, SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys), False, True); end; end; procedure TCustomEasyListview.HandleMouseUp(Button: TCommonMouseButton; Msg: TWMMouse); // Called when the Left Mouse button is released var Pt: TPoint; KeyState: TCommonKeyStates; GroupHitInfo: TEasyGroupHitTestInfoSet; ItemHitInfo: TEasyItemHitTestInfoSet; Group: TEasyGroup; Item: TEasyItem; GesturedHandled: Boolean; CtlDown, ShiftDown, DoDefaultItemUp: Boolean; begin Group := nil; KeyState := KeyToKeyStates(Msg.Keys); CtlDown := cksControl in KeyState; ShiftDown := cksShift in KeyState; Pt := Scrollbars.MapWindowToView(Msg.Pos); GesturedHandled := False; if Gesture.Enabled and (Gesture.Path <> '') and ([ebcsGroupExpandPending, ebcsCheckboxClickPending, ebcsDragSelecting, ebcsDragging] * States = []) then DoGesture(Gesture.Path, GesturedHandled); // In some cases we can get a mouse up message without a corresponding mouse // down message. For example if we full expand the application if the mouse // is over the Easy window after the expand we get a mouse up message if ([ebcsLButtonDown, ebcsRButtonDown, ebcsMButtonDown] * States <> []) then begin if ebcsGroupExpandPending in States then begin // Don't do any other processing if the group expand button was clicked end else if ebcsCheckboxClickPending in States then begin Group := ClickTestGroup(Pt, KeyState, GroupHitInfo); if CheckManager.PendingObject is TEasyGroup then begin if (egtOnCheckbox in GroupHitInfo) and Assigned(Group) then Group.Checked := not Group.Checked; end else if CheckManager.PendingObject is TEasyItem then begin Item := ClickTestItem(Pt, Group, KeyState, ItemHitInfo); if (ehtOnCheck in ItemHitInfo) and Assigned(Item) then Item.Checked := not Item.Checked end; CheckManager.PendingObject.CheckHovering := False; CheckManager.PendingObject.CheckPending := False; CheckManager.PendingObject := nil; end else if ebcsDragSelecting in States then begin FinalizeDrag(SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys)); end else if ebcsDragging in States then begin // The VCL will send us a fake mouse button up when the drag starts. // This screws everything. We will send a mouse up after the drag ends // with the cbcsVCLDrag cleared if not(ebcsVCLDrag in States) then FinalizeDrag(SmallPointToPoint(Msg.Pos), KeyToKeyStates(Msg.Keys)); end else begin // If not dragging or drag selecting then check if it is necessary to unselect // the items if not GesturedHandled then begin Item := ClickTestItem(Pt, Group, KeyState, ItemHitInfo); if Assigned(Item) then begin DoDefaultItemUp := True; DoItemMouseUp(Item, Button, DoDefaultItemUp); if DoDefaultItemUp then begin DoItemClick(Item, KeyToKeyStates(Msg.Keys), ItemHitInfo); if not Item.SelectionHitPt(Pt, eshtClickselect) then Selection.ClearAll else begin // Allow MultiSelect if Selection.MultiSelect then begin if not (ShiftDown or CtlDown) and (not Item.Selected or (Button = cmbLeft)) then Selection.ClearAllExcept(Item) else begin if CtlDown then begin EditManager.StopAutoEditTimer; if not ShiftDown then Item.Selected := not Item.Selected; Item.Focused := True; end end end end end end else begin Group := ClickTestGroup(Pt, KeyToKeyStates(Msg.Keys), GroupHitInfo); if Assigned(Group) then DoGroupClick(Group, KeyToKeyStates(Msg.Keys), GroupHitInfo); Selection.ClearAll end end end end; end; procedure TCustomEasyListview.InitializeDragPendings(HitItem: TEasyItem; WindowPoint: TPoint; KeyState: TCommonKeyStates; AllowDrag, AllowDragRect: Boolean); // Called from the mouse down messages. It initializes the DragManager and the // DragSelection Manager to prepare for a possible action. If the click was not // on an item then it is interperted as a drag select. If it hit an item it // is interperted as a D&D action. var StartSelectDrag, StartDrag: Boolean; Pt: TPoint; begin // At least NT4 does not set the focus on a mouse click CheckFocus; Mouse.Capture := Handle; // Initialize both Drag Select and Drag object just in case StartSelectDrag := AllowDragRect and DragRect.InitializeDrag(WindowPoint, KeyState); StartDrag := AllowDrag and DragManager.InitializeDrag(HitItem, WindowPoint, KeyState); Pt := Scrollbars.MapWindowToView(WindowPoint); if Assigned(DragManager.DragItem) and StartDrag then begin Include(FStates, ebcsDragPending); DragRect.FinalizeDrag(KeyState) end else if StartSelectDrag then begin Include(FStates, ebcsDragSelectPending); DragManager.FinalizeDrag(KeyState) end; end; function TCustomEasyListview.IsGrouped: Boolean; begin // Default definition that the control is in grouped mode is if the Top Margin is enabled Result := PaintInfoGroup.MarginTop.Visible end; procedure TCustomEasyListview.Loaded; begin inherited; DoUpdate; end; procedure TCustomEasyListview.LoadFromFile(FileName: WideString; Mode: Word); var F: TWideFileStream; begin F := TWideFileStream.Create(FileName, Mode); try LoadFromStream(F) finally F.Free end end; procedure TCustomEasyListview.LoadFromStream(S: TStream); var Version: Integer; AView: TEasyListStyle; begin BeginUpdate; try S.Read(Version, SizeOf(Version)); if Version > 0 then begin S.Read(AView, SizeOf(AView)); View := AView; Groups.LoadFromStream(S, Version); Header.LoadFromStream(S, Version); Groups.Rebuild(True); end; { if Version > n then begin end; } finally EndUpdate end end; procedure TCustomEasyListview.MarkSelectedCut; var Item: TEasyItem; begin CancelCut; Item := Selection.First; while Assigned(Item) do begin Item.Cut := True; Item := Selection.Next(Item) end end; procedure TCustomEasyListview.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if Operation = opRemove then begin if AComponent = FImagesGroup then FImagesGroup := nil; if AComponent = FImagesExLarge then FImagesExLarge := nil; if AComponent = FImagesLarge then FImagesLarge := nil; if AComponent = FImagesSmall then FImagesSmall := nil; if AComponent = FImagesState then FImagesState := nil; if AComponent = Header.Images then Header.Images := nil; end end; procedure TCustomEasyListview.PasteFromClipboard; var Handled: Boolean; begin Handled := False; DoClipboardPaste(Handled) end; procedure TCustomEasyListview.ResizeBackBits(NewWidth, NewHeight: Integer); // Resizes the Bitmap for the DoubleBuffering. Called mainly when the window // is resized. Note the bitmap only gets larger to maximize speed during dragging begin if CacheDoubleBufferBits and Assigned(BackBits) then begin // The Backbits grow to the largest window size if (NewWidth > BackBits.Width) then begin if NewWidth > 0 then BackBits.Width := NewWidth else BackBits.Width := 1 end; if NewHeight > BackBits.Height then begin if NewHeight > 0 then BackBits.Height := NewHeight else BackBits.Height := 1; end end end; procedure TCustomEasyListview.SaveToFile(FileName: WideString; Mode: Word); var F: TWideFileStream; begin F := TWideFileStream.Create(FileName, Mode); try SaveToStream(F) finally F.Free end end; procedure TCustomEasyListview.SaveToStream(S: TStream); var Version: Integer; begin Version := EASYLISTVIEW_STREAM_VERSION; S.Write(Version, SizeOf(Version)); S.Write(View, SizeOf(View)); Groups.SaveToStream(S, Version); Header.SaveToStream(S, Version) end; procedure TCustomEasyListview.SetBackGround(const Value: TEasyBackgroundManager); begin if Assigned(FBackGround) then FreeAndNil(FBackGround); FBackGround := Value; end; procedure TCustomEasyListview.SetCacheDoubleBufferBits(const Value: Boolean); begin if FCacheDoubleBufferBits <> Value then begin FCacheDoubleBufferBits := Value; if Value then begin if not Assigned(FBackBits) then begin FBackBits := TBitmap.Create; FBackBits.PixelFormat := pf32Bit end end else FreeAndNil(FBackBits) end end; procedure TCustomEasyListview.SetGroupCollapseImage(Value: TBitmap); begin FGroupCollapseButton.Assign(Value); if Assigned(FGroupCollapseButton) then FGroupCollapseButton.PixelFormat := pf32Bit end; procedure TCustomEasyListview.SetGroupExpandImage(Value: TBitmap); begin FGroupExpandButton.Assign(Value); if Assigned(FGroupExpandButton) then FGroupExpandButton.PixelFormat := pf32Bit end; procedure TCustomEasyListview.SetGroupFont(Value: TFont); begin FGroupFont.Assign(Value) end; procedure TCustomEasyListview.SetHintType(Value: TEasyHintType); begin HintInfo.HintType := Value end; procedure TCustomEasyListview.SetImagesExLarge(Value: TCustomImageList); begin if Value <> FImagesExLarge then begin FImagesExLarge := Value; SafeInvalidateRect(nil, False); end end; procedure TCustomEasyListview.SetImagesGroup(Value: TCustomImageList); begin if Value <> FImagesGroup then begin FImagesGroup := Value; SafeInvalidateRect(nil, False); end end; procedure TCustomEasyListview.SetImagesLarge(Value: TCustomImageList); begin if Value <> FImagesLarge then begin FImagesLarge := Value; SafeInvalidateRect(nil, False); end end; procedure TCustomEasyListview.SetImagesSmall(Value: TCustomImageList); begin if Value <> FImagesSmall then begin FImagesSmall := Value; SafeInvalidateRect(nil, False); end end; procedure TCustomEasyListview.SetImagesState(const Value: TCustomImageList); begin if Value <> FImagesState then begin FImagesState := Value; SafeInvalidateRect(nil, False); end end; procedure TCustomEasyListview.SetPaintInfoColumn(const Value: TEasyPaintInfoBaseColumn); begin if Value <> FPaintInfoColumn then begin FreeAndNil(FPaintInfoColumn); FPaintInfoColumn := Value; end end; procedure TCustomEasyListview.SetPaintInfoGroup(const Value: TEasyPaintInfoBaseGroup); begin if Value <> FPaintInfoGroup then begin FreeAndNil(FPaintInfoGroup); FPaintInfoGroup := Value; end end; procedure TCustomEasyListview.SetPaintInfoItem(const Value: TEasyPaintInfoBaseItem); begin if Value <> FPaintInfoItem then begin FreeAndNil(FPaintInfoItem); FPaintInfoItem := Value; end end; procedure TCustomEasyListview.SetSelection(Value: TEasySelectionManager); begin if Value <> FSelection then begin FreeAndNil(FSelection); FSelection := Value end end; procedure TCustomEasyListview.SetShowGroupMargins(const Value: Boolean); begin if FShowGroupMargins <> Value then begin FShowGroupMargins := Value; DoUpdate; end; end; procedure TCustomEasyListview.SetShowInactive(const Value: Boolean); begin if FShowInactive <> Value then begin FShowInactive := Value; SafeInvalidateRect(nil, True) end end; procedure TCustomEasyListview.SetShowThemedBorder(Value: Boolean); begin if Value <> FShowThemedBorder then begin FShowThemedBorder := Value; // Need to modify the NonClient area RecreateWnd; end end; procedure TCustomEasyListview.SetView(Value: TEasyListStyle); begin if FView <> Value then begin FView := Value; Groups.Rebuild(True); if IsVertView then WheelMouseDefaultScroll := edwsVert else WheelMouseDefaultScroll := edwsHorz; end end; procedure TCustomEasyListview.WMChar(var Msg: TWMChar); begin inherited; IncrementalSearch.HandleWMChar(Msg); end; procedure TCustomEasyListview.WMClose(var Msg: TWMClose); begin EditManager.EndEdit; inherited; end; procedure TCustomEasyListview.WMContextMenu(var Msg: TMessage); var Item: TEasyItem; Group: TEasyGroup; Pt: TPoint; HitInfoGroup: TEasyHitInfoGroup; HitInfoItem: TEasyHitInfoItem; Menu: TPopupMenu; Handled, SkipHitTest, MenuKey: Boolean; begin if not EditManager.Editing and not (Gesture.Enabled and (Gesture.Path <> '')) then begin Handled := False; MenuKey := False; if not (ebcsCancelContextMenu in States) then begin SkipHitTest := False; // Support Dual monitors with SmallPointToPoint Pt:= SmallPointToPoint(SmallPoint(Msg.LParamLo, Msg.LParamHi)); if ((Pt.X = 65535) and (Pt.Y = 65535)) or ((Pt.X = -1) and (Pt.Y = -1)) then begin MenuKey := True; Pt := ScreenToClient(Mouse.CursorPos); if not PtInRect(ClientRect, Pt) or (Selection.Count = 0) then begin Pt.X := 0; Pt.Y := 0; SkipHitTest := True; end; Pt := ClientToScreen(Pt); end; if MenuKey and (Selection.Count > 0) then begin HitInfoItem.Item := Selection.First; Pt := ClientToScreen(HitInfoItem.Item.DisplayRect.TopLeft); Pt.Y := Pt.Y + Header.RuntimeHeight; HitInfoItem.Column := nil; HitInfoItem.Group := HitInfoItem.Item.OwnerGroup; HitInfoItem.HitInfo := [ehtOnLabel, ehtOnIcon]; DoItemContextMenu(HitInfoItem, Pt, Menu, Handled) end else if not SkipHitTest then begin if IsHeaderMouseMsg(PointToSmallPoint( ScreenToClient(Pt))) then begin Pt := ClientToScreen(Pt); Header.WMContextMenu(Msg); Handled := True; end else begin Menu := nil; Exclude(FStates, ebcsDragSelectPending); Exclude(FStates, ebcsDragPending); Handled := False; Group := Groups.GroupByPoint(Scrollbars.MapWindowToView(ScreenToClient(Pt))); if Assigned(Group) then begin // The hit was in a group so now see if it was in an item Item := Group.ItembyPoint(Scrollbars.MapWindowToView( ScreenToClient(Pt))); if Assigned(Item) then begin if Item.HitTestAt(Scrollbars.MapWindowToView( ScreenToClient(Pt)), HitInfoItem.HitInfo) then begin HitInfoItem.Column := nil; HitInfoItem.Group := Group; HitInfoItem.Item := Item; DoItemContextMenu(HitInfoItem, Pt, Menu, Handled) end end; if not Assigned(Menu) and not Handled then begin HitInfoGroup.Group := Group; Group.HitTestAt(Scrollbars.MapWindowToView(ScreenToClient(Pt)), HitInfoGroup.HitInfo); DoGroupContextMenu(HitInfoGroup, Pt, Menu, Handled) end end end end; if not Handled then DoContextMenu(Pt, Handled); if Assigned(Menu) and not Handled then begin Menu.Popup(Msg.LParamLo, Msg.LParamHi); Msg.Result := 1 end else if not Handled then inherited // Use the PopupMenu property from TControl end; end else begin Msg.Result := 1; inherited end; Exclude(FStates, ebcsCancelContextMenu); end; procedure TCustomEasyListview.WMDestroy(var Msg: TMessage); begin EditManager.EndEdit; DragManager.Registered := False; Header.DragManager.Registered := False; inherited; end; procedure TCustomEasyListview.WMEasyThreadCallback(var Msg: TWMThreadRequest); begin DoThreadCallback(Msg) end; procedure TCustomEasyListview.WMEraseBkGnd(var Msg: TWMEraseBkGnd); begin Msg.Result := 1; end; procedure TCustomEasyListview.WMGetDlgCode(var Msg: TWMGetDlgCode); // The VCL forms use the Dialog Window Proc so we need to tell windows we want // the arrow keys for navigation begin Msg.Result := Msg.Result or DLGC_WANTALLKEYS or DLGC_WANTARROWS or DLGC_WANTCHARS; end; procedure TCustomEasyListview.WMHScroll(var Msg: TWMHScroll); // Called to scroll the Window, the Window is responsible for actually performing // the scroll begin inherited; if Msg.ScrollCode <> SB_ENDSCROLL then Include(FStates, ebcsScrolling) else Exclude(FStates, ebcsScrolling); ScrollBars.WMHScroll(Msg); SafeInvalidateRect(nil, False); end; procedure TCustomEasyListview.WMKeyDown(var Msg: TWMKeyDown); // Called when the user pressed a key on the keyboard. The Scrollbars need to // know in case the user is scrolling using the keys. var Shift: TShiftState; DoDefault: Boolean; begin inherited; if (ebcsDragSelecting in States) then begin DragRect.WMKeyDown(Msg); end else begin IncrementalSearch.HandleWMKeyDown(Msg); Shift := KeyDataToShiftState(Msg.KeyData); DoDefault := True; DoKeyAction(Msg.CharCode, Shift, DoDefault); if DoDefault then HandleKeyDown(Msg); end; end; procedure TCustomEasyListview.WMKillFocus(var Msg: TWMKillFocus); begin inherited; if HotTrack.OnlyFocused then HotTrack.PendingObject[Point(0, 0)] := nil; SafeInvalidateRect(nil, True); end; procedure TCustomEasyListview.WMLButtonDblClk(var Msg: TWMLButtonDblClk); begin // Cancel the edit (called in WMLButtonDown) EditManager.EndEdit; inherited; HandleDblClick(cmbLeft, Msg); end; procedure TCustomEasyListview.WMLButtonDown(var Msg: TWMLButtonDown); // Called when the Left Mouse button is pressed begin Include(FStates, ebcsLButtonDown); CheckFocus; if IsHeaderMouseMsg(Msg.Pos) then begin // Should this call a Column manager or a Column? if Assigned(Header) then begin Header.CaptureMouse; Header.WMLButtonDown(Msg); end end else begin inherited; HandleMouseDown(cmbLeft, Msg) end; LastMousePos := Msg.Pos end; procedure TCustomEasyListview.WMLButtonUp(var Msg: TWMLButtonUp); // Called when the Left Mouse button is released begin if IsHeaderMouseMsg(Msg.Pos) then begin // Should this call a Column manager or a Column? if Assigned(Header) then begin Header.WMLButtonUp(Msg); // Need to allow HotTracking to finish up. Header.WMMouseMove(Msg); Header.ReleaseMouse; end end else begin // The VCL D&D will "Perform" a Left Button Up when StartDrag is called. As such // a lot of the State Flags get prematurely reset. if not (ebcsVCLDrag in States) then ClearPendingDrags; inherited; HandleMouseUp(cmbLeft, Msg); Mouse.Capture := 0; end; // ClearStates will get called from the VCL end Drag event if not (ebcsVCLDrag in States) then ClearStates; end; procedure TCustomEasyListview.WMMButtonDblClk(var Msg: TWMMButtonDblClk); begin inherited; HandleDblClick(cmbMiddle, Msg) end; procedure TCustomEasyListview.WMMButtonDown(var Msg: TWMMButtonDown); begin Include(FStates, ebcsMButtonDown); CheckFocus; inherited; HandleMouseDown(cmbMiddle, Msg); LastMousePos := Msg.Pos end; procedure TCustomEasyListview.WMMButtonUp(var Msg: TWMMButtonUp); begin HandleMouseUp(cmbMiddle, Msg); ClearPendingDrags; inherited; Mouse.Capture := 0; ClearStates; end; procedure TCustomEasyListview.WMMouseActivate(var Msg: TWMMouseActivate); // Called when the mouse is clicked in a window and the window does not have // focus. By responding MA_ACTIVATE the window should recieve focus but this // does not seem to happen on NT4. Necded a SetFocus when the mouse is pressed begin inherited; if not EditManager.Editing then begin CheckFocus; Msg.Result := MA_ACTIVATE; end else Msg.Result := MA_NOACTIVATE; end; procedure TCustomEasyListview.WMMouseMove(var Msg: TWMMouseMove); // Called when the mouse is moved var KeyState: TCommonKeyStates; GroupHitInfo: TEasyGroupHitTestInfoSet; ItemHitInfo: TEasyItemHitTestInfoSet; Effects: TCommonDropEffect; Group: TEasyGroup; HotTrackCheckObj, HotTrackObj: TEasyCollectionItem; Item: TEasyItem; Pt: TPoint; Dx, Dy: Integer; LocalGesture: WideChar; begin KeyState := KeyToKeyStates(Msg.Keys); Pt := Scrollbars.MapWindowToView(Msg.Pos); HotTrackCheckObj := nil; if Gesture.Enabled then begin Dx := Msg.XPos - LastMousePos.x; Dy := Msg.YPos - LastMousePos.y; if ((cksLButton in KeyState) and (cmbLeft in Gesture.Button)) or ((cksRButton in KeyState) and (cmbRight in Gesture.Button)) or ((cksMButton in KeyState) and (cmbMiddle in Gesture.Button)) then begin LocalGesture := '*'; if (Dx > Gesture.Tolerance) and (Abs(Dy) < 2 * Gesture.Tolerance) then LocalGesture := 'R' else if (-Dx > Gesture.Tolerance) and (Abs(Dy) < 2 * Gesture.Tolerance) then LocalGesture := 'L' else if (Dy > Gesture.Tolerance) and (Abs(Dx) < 2 * Gesture.Tolerance) then LocalGesture := 'D' else if (-Dy > Gesture.Tolerance) and (Abs(Dx) < 2 * Gesture.Tolerance) then LocalGesture := 'U'; if LocalGesture <> '*' then begin if Length(Gesture.Path) > 0 then begin if Gesture.Path[Length(Gesture.Path)] <> LocalGesture then Gesture.Path := Gesture.Path + LocalGesture end else Gesture.Path := LocalGesture end end end; if IsHeaderMouseMsg(Msg.Pos) then begin HotTrack.PendingObject[Point(0, 0)] := nil; Header.WMMouseMove(Msg) end else begin if not Assigned(HotTrack.PendingObject[Point(0,0)]) then Cursor := crDefault; // First see if there is any kind of drag operation pending or occuring if DragInitiated then begin // First check for special cases, such as when the drag selection rectangle // is active or an item is being dragged in a D&D operation. If not see if // this is the first move after a mouse press and one of the above cases is // pending. If we then detect a drag start then setup the flags and initialize // the action with the appropiate mananger. if ebcsDragSelecting in States then DragRect.Drag(Canvas, SmallPointToPoint(Msg.Pos), KeyState, Effects) else if ebcsDragging in States then // his only works for VCL drag and drop. The System takes the mouse for OLE DragManager.Drag(Canvas, SmallPointToPoint(Msg.Pos), KeyState, Effects) else // We are not drag selecting; check if we have a drag pending if [ebcsDragSelectPending, ebcsDragPending] * States <> [] then begin if DragDetectPlus(Handle, SmallPointToPoint(Msg.Pos)) then begin // The decision to if the mouse was a drag or a select was made when the // mouse was pressed, based on the area of the control the click occured if ebcsDragSelectPending in States then begin // We are now drag selecting so update the states Include(FStates, ebcsDragSelecting); Exclude(FStates, ebcsDragSelectPending); if KeyState * [cksShift, cksControl] = [] then Include(FStates, ebcsDragSelecting); Exclude(FStates, ebcsDragSelectPending); if KeyState * [cksShift, cksControl] = [] then Selection.ClearAll; EditManager.StopAutoEditTimer; DragRect.BeginDrag(SmallPointToPoint(Msg.Pos), KeyState); // Since for a selection rect we have the mouse captured we can just // call DragEnter once here and be done with it DragRect.DragEnter(nil, Canvas, ScreenToClient(Mouse.CursorPos), KeyState, Effects); end else if ebcsDragPending in States then begin Item := Groups.ItembyPoint(Scrollbars.MapWindowToView(SmallPointToPoint(Msg.Pos))); if Assigned(Item) then begin // Since we don't select until a MouseUp on Ctl-Click we must do it here just in case if cksControl in KeyState then begin Item.Selected := True; Item.Focused := True; end; Include(FStates, ebcsDragging); if edtVCL = DragManager.DragType then Include(FStates, ebcsVCLDrag); Exclude(FStates, ebcsDragPending); EditManager.StopAutoEditTimer; try DragManager.BeginDrag(SmallPointToPoint(Msg.Pos), KeyState); finally // If was an OLE drag then the subsystem has taken the mouse and we // will never get a mouse up so fake it, the VCL system fakes it on // its own but if the drag/drop is not enabled then it never will so // fake it for all cases if not(ebcsVCLDrag in States) then begin if ebcsLButtonDown in States then Perform(WM_LBUTTONUP, TMessage(Msg).wParam, TMessage(Msg).LParam) else if ebcsRButtonDown in States then begin // Don't want to show the context menu after a drag drop with // the right button Include(FStates, ebcsCancelContextMenu); Perform(WM_RBUTTONUP, TMessage(Msg).wParam, TMessage(Msg).LParam) end else if ebcsMButtonDown in States then Perform(WM_MBUTTONUP, TMessage(Msg).wParam, TMessage(Msg).LParam) end end end else begin Selection.ClearAll; // Switch from a DragDrop Pending to a DragSelect Pending Exclude(FStates, ebcsDragPending); if DragRect.Enabled then Include(FStates, ebcsDragSelectPending); end end end end end else // Not DragInitiated begin HotTrackObj := nil; Group := Groups.GroupByPoint(Pt); if Assigned(Group) then begin if Group.HitTestAt(Pt, GroupHitInfo) then // See if it is in a Group Check box first if egtOnCheckbox in GroupHitInfo then HotTrackCheckObj := Group else begin if (htgAnyWhere in HotTrack.GroupTrack) or ((htgIcon in HotTrack.GroupTrack) and (egtOnIcon in GroupHitInfo)) or ((htgText in HotTrack.GroupTrack) and (egtOnText in GroupHitInfo)) or ((htgTopMargin in HotTrack.GroupTrack) and (egtOnHeader in GroupHitInfo)) or ((htgBottomMargin in HotTrack.GroupTrack) and (egtOnFooter in GroupHitInfo)) or ((htgLeftMargin in HotTrack.GroupTrack) and (egtOnLeftMargin in GroupHitInfo)) or ((htgRightMargin in HotTrack.GroupTrack) and (egtOnRightMargin in GroupHitInfo)) then HotTrackObj := Group; end end; // Next See if it is in an Item Check box if not (Assigned(HotTrackCheckObj) or Assigned(HotTrackObj)) then begin Item := Groups.ItembyPoint(Pt); if Assigned(Item) then begin if Item.HitTestAt(Pt, ItemHitInfo) then begin if ehtOnCheck in ItemHitInfo then HotTrackCheckObj := Item else begin if (htiAnyWhere in HotTrack.ItemTrack) or ((htiIcon in HotTrack.ItemTrack) and (ehtOnIcon in ItemHitInfo)) or ((htiText in HotTrack.ItemTrack) and (ehtOnText in ItemHitInfo)) then HotTrackObj := Item end end end end; if (ebcsCheckboxClickPending in States) then begin if Assigned(HotTrackCheckObj) then begin if CheckManager.PendingObject <> HotTrackCheckObj then begin CheckManager.PendingObject.CheckHovering := True; HotTrackCheckObj := nil end else CheckManager.PendingObject.CheckHovering := False; end else begin CheckManager.PendingObject.CheckHovering := True; end; if HotTrackCheckObj <> nil then HotTrackCheckObj := nil; end; if not Assigned(CheckManager.PendingObject) and (Self.Focused or not HotTrack.OnlyFocused) and PtInRect(ClientRect, SmallPointToPoint(Msg.Pos)) and (Assigned(HotTrackObj) and (HotTrackObj.Enabled)) then HotTrack.PendingObject[SmallPointToPoint(Msg.Pos)] := HotTrackObj else HotTrack.PendingObject[SmallPointToPoint(Msg.Pos)] := nil; HotTrack.PendingObjectCheck := HotTrackCheckObj; // We are not drag selecting and do not have a drag pending so it is a normal // mouse move inherited; end end; LastMousePos := Msg.Pos; end; procedure TCustomEasyListview.WMNCCalcSize(var Msg: TWMNCCalcSize); {$IFDEF USETHEMES} var R: TRect; {$ENDIF USETHEMES} begin if DrawWithThemes then begin DefaultHandler(Msg); {$IFDEF USETHEMES} if succeeded(GetThemeBackgroundContentRect(Themes.ListviewTheme, Canvas.Handle, LVP_EMPTYTEXT, LIS_NORMAL, Msg.CalcSize_Params^.rgrc[0], @R)) then begin InflateRect(R, -1-BorderWidth, -1-BorderWidth); Msg.CalcSize_Params^.rgrc[0] := R; end {$ENDIF USETHEMES} end else begin inherited; end end; procedure TCustomEasyListview.WMNCPaint(var Msg: TWMNCPaint); // The VCL screws this up and draws over the scrollbars making them flicker and // be covered up by backgound painting when dragging the the window from off the // screen const InnerStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENINNER, BDR_RAISEDINNER, 0); OuterStyles: array[TBevelCut] of Integer = (0, BDR_SUNKENOUTER, BDR_RAISEDOUTER, 0); EdgeStyles: array[TBevelKind] of Integer = (0, 0, BF_SOFT, BF_FLAT); Ctl3DStyles: array[Boolean] of Integer = (BF_MONO, 0); var ClientR, WindowR, WindowROrig, Filler: TRect; DC: HDC; Style, StyleEx: Longword; Pt: TPoint; {$IFDEF USETHEMES} R: TRect; {$ENDIF USETHEMES} begin // Let Windows paint the scrollbars first DefaultHandler(Msg); // Always paint the NC area as refreshing it can be tricky and it sometimes // is not redrawn on startup // if UpdateCount = 0 then begin DC := GetWindowDC(Handle); try NCCanvas.Handle := DC; if (BevelKind <> bkNone) or (BorderWidth > 0){ or DrawWithThemes} then begin Windows.GetClientRect(Handle, ClientR); Windows.GetWindowRect(Handle, WindowR); Pt := WindowR.TopLeft; Windows.ScreenToClient(Handle, Pt); // Map the screen coordinates of the WindowRect to a 0,0 offset OffsetRect(WindowR, -WindowR.Left, -WindowR.Top); // Make a copy WindowROrig := WindowR; // Map the ClientRect to Window coordinates OffsetRect(ClientR, -Pt.X, -Pt.Y); Style := GetWindowLong(Handle, GWL_STYLE); if (Style and WS_VSCROLL) <> 0 then begin StyleEx := GetWindowLong(Handle, GWL_EXSTYLE); if (StyleEx and WS_EX_LEFTSCROLLBAR) <> 0 then Dec(ClientR.Left, GetSystemMetrics(SM_CYVSCROLL)) else Inc(ClientR.Right, GetSystemMetrics(SM_CYVSCROLL)) end; if (Style and WS_HSCROLL) <> 0 then Inc(ClientR.Bottom, GetSystemMetrics(SM_CYHSCROLL)); // Paint the little square in the corner made by the scroll bars if ((Style and WS_VSCROLL) <> 0) and ((Style and WS_HSCROLL) <> 0) then begin Filler := ClientR; Filler.Left := Filler.Right - GetSystemMetrics(SM_CYVSCROLL); Filler.Top := Filler.Bottom - GetSystemMetrics(SM_CYHSCROLL); NCCanvas.Brush.Color := clBtnFace; NCCanvas.FillRect(Filler); end; // if not DrawWithThemes then // Punch out the client area and the scroll bar area ExcludeClipRect(DC, ClientR.Left, ClientR.Top, ClientR.Right, ClientR.Bottom); if DrawWithThemes then begin {$IFDEF USETHEMES} if not ShowThemedBorder then begin R := Rect(0, 0, 0, 0); GetThemeBackgroundExtent(Themes.ListviewTheme, NCCanvas.Handle, LVP_EMPTYTEXT, LIS_NORMAL, ClientRect, R); InflateRect(WindowROrig, R.Left - ClientRect.Left, R.Top - ClientRect.Top); end; DrawThemeBackground(Themes.ListviewTheme, NCCanvas.Handle, LVP_EMPTYTEXT, LIS_NORMAL, WindowROrig, nil); {$ENDIF USETHEMES} end else begin Windows.FillRect(DC, WindowR, Brush.Handle); DrawEdge(DC, WindowROrig, InnerStyles[BevelInner] or OuterStyles[BevelOuter], Byte(BevelEdges) or EdgeStyles[BevelKind] or Ctl3DStyles[Ctl3D] or BF_ADJUST); end end else begin Windows.GetWindowRect(Handle, WindowR); end; finally NCCanvas.Handle := 0; ReleaseDC(Handle, DC); end end end; procedure TCustomEasyListview.WMPaint(var Msg: TWMPaint); // The VCL does a poor job at optimizing the paint messages. It does not look // to see what rectangle the system actually needs painted. Sometimes it only // needs a small slice of the window painted, why paint it all? This implementation // also handles DoubleBuffering better var PaintInfo: TPaintStruct; ClientR: TRect; begin BeginPaint(Handle, PaintInfo); try if (UpdateCount = 0) or ForcePaint then begin try if not CacheDoubleBufferBits then begin BackBits := TBitmap.Create; BackBits.PixelFormat := pf32Bit; Windows.GetClientRect(Handle, ClientR); if ClientWidth > 0 then BackBits.Width := ClientWidth else BackBits.Width := 1; if ClientHeight > 0 then BackBits.Height := ClientHeight else BackBits.Height := 1; end; BackBits.Canvas.Lock; try if not IsRectEmpty(PaintInfo.rcPaint) and (ClientWidth > 0) and (ClientHeight > 0) then begin // Assign attributes to the Canvas used BackBits.Canvas.Font.Assign(Font); BackBits.Canvas.Brush.Color := Color; BackBits.Canvas.Brush.Assign(Brush); SetWindowOrgEx(BackBits.Canvas.Handle, 0, 0, nil); SetViewportOrgEx(BackBits.Canvas.Handle, 0, 0, nil); FillRect(BackBits.Canvas.Handle, PaintInfo.rcPaint, Brush.Handle); SelectClipRgn(BackBits.Canvas.Handle, 0); // Remove the clipping region we created // Paint the rectangle that is needed DoPaintRect(BackBits.Canvas, PaintInfo.rcPaint, False); // Remove any clipping regions applied by the views. SelectClipRgn(BackBits.Canvas.Handle, 0); // Redraw the drag selecting rectangle if (ebcsDragSelecting in States) then DragRect.PaintSelectionRect(BackBits.Canvas); DoAfterPaint(BackBits.Canvas, PaintInfo.rcPaint); // Blast the bits to the screen BitBlt(PaintInfo.hdc, PaintInfo.rcPaint.Left, PaintInfo.rcPaint.Top, PaintInfo.rcPaint.Right - PaintInfo.rcPaint.Left, PaintInfo.rcPaint.Bottom - PaintInfo.rcPaint.Top, BackBits.Canvas.Handle, PaintInfo.rcPaint.Left, PaintInfo.rcPaint.Top, SRCCOPY); end finally BackBits.Canvas.Unlock; end; finally if not CacheDoubleBufferBits then FreeAndNil(FBackBits) end; end finally EndPaint(Handle, PaintInfo); end end; procedure TCustomEasyListview.WMRButtonDblClk(var Msg: TWMRButtonDblClk); begin inherited; HandleDblClick(cmbRight, Msg) end; procedure TCustomEasyListview.WMRButtonDown(var Msg: TWMRButtonDown); begin Include(FStates, ebcsRButtonDown); CheckFocus; if IsHeaderMouseMsg(Msg.Pos) then begin // Should this call a Column manager or a Column? if Assigned(Header) then begin Header.WMRButtonDown(Msg); Header.ReleaseMouse; end end else begin inherited; HandleMouseDown(cmbRight, Msg) end; LastMousePos := Msg.Pos end; procedure TCustomEasyListview.WMRButtonUp(var Msg: TWMRButtonUp); begin if IsHeaderMouseMsg(Msg.Pos) then begin // Should this call a Column manager or a Column? if Assigned(Header) then begin inherited; // ContextMenu handled it if Msg.Result = 0 then Header.WMRButtonUp(Msg); // Need to allow HotTracking to finish up. if Assigned(Header.HotTrackedColumn) then Header.WMMouseMove(Msg); Header.ReleaseMouse; end end else begin if [ebcsDragSelecting, ebcsDragging, ebcsVCLDrag] * States <> [] then Include(FStates, ebcsCancelContextMenu); if Msg.Result = 0 then HandleMouseUp(cmbRight, Msg); ClearPendingDrags; inherited; // Handles the context menu Mouse.Capture := 0; end; ClearStates; end; procedure TCustomEasyListview.WMSetCursor(var Msg: TWMSetCursor); begin inherited; end; procedure TCustomEasyListview.WMSetFocus(var Msg: TWMSetFocus); begin inherited; SafeInvalidateRect(nil, True); //Selection.Invalidate(False)VisibleSelected(False); end; procedure TCustomEasyListview.WMSize(var Msg: TWMSize); begin {$IFDEF GXDEBUG} SendDebug('TCustomEasyListview.WMSize'); {$ENDIF GXDEBUG} Header.WMSize(Msg); // do it first inherited; end; procedure TCustomEasyListview.WMTabMoveFocus(var Msg: TMessage); var NextItem: TEasyItem; JumpToNextItem: Boolean; NextColumn: TEasyColumn; begin JumpToNextItem := True; NextItem := EditManager.TabMoveFocusItem; if EditManager.TabEditColumns then begin NextColumn := EditManager.TabMoveFocusColumn; if Assigned(NextColumn) then begin EditManager.TabMoveFocusItem := nil; JumpToNextItem := False; NextColumn.MakeVisible(emvTop); EditManager.BeginEdit(NextItem, NextColumn); end end; if JumpToNextItem then begin EditManager.TabMoveFocusItem := nil; if Assigned(NextItem) then begin NextItem.Focused := True; NextItem.MakeVisible(emvAuto); EditManager.BeginEdit(NextItem, nil) end; end end; procedure TCustomEasyListview.WMVScroll(var Msg: TWMVScroll); // Called to scroll the Window, the Window is responsible for actually performing // the scroll begin inherited; if Msg.ScrollCode <> SB_ENDSCROLL then Include(FStates, ebcsScrolling) else Exclude(FStates, ebcsScrolling); ScrollBars.WMVScroll(Msg); SafeInvalidateRect(nil, False); end; procedure TCustomEasyListview.WMWindowPosChanged(var Msg: TWMWindowPosChanged); // Called after the window has changed size var YChanged, XChanged: Boolean; begin {$IFDEF GXDEBUG} SendDebug('TCustomEasyListview.WMWindowPosChanged'); {$ENDIF GXDEBUG} YChanged := False; XChanged := False; // Only use cx and cy if NOSIZE is not used if Msg.WindowPos^.flags and SWP_NOSIZE = 0 then begin YChanged := Height <> Msg.WindowPos.cy; XChanged := Width <> Msg.WindowPos.cx; end; inherited; if YChanged or XChanged then begin try Groups.Rebuild(True); ScrollBars.ReCalculateScrollbars(True, False); finally ResizeBackBits(Msg.WindowPos.cx, Msg.WindowPos.cy); end; end end; procedure TCustomEasyListview.WMWindowPosChanging(var Msg: TWMWindowPosChanging); // Called when the window is changing size var YChanged, XChanged: Boolean; begin {$IFDEF GXDEBUG} SendDebug('TCustomEasyListview.WMWindowPosChanging'); {$ENDIF GXDEBUG} YChanged := False; XChanged := False; // Only use cx and cy if NOSIZE is not used if Msg.WindowPos^.flags and SWP_NOSIZE = 0 then begin YChanged := Height <> Msg.WindowPos.cy; XChanged := Width <> Msg.WindowPos.cx; end; // Track the offset of the background image if desired before the control size is updated BackGround.WMWindowPosChanging(Msg); inherited; if YChanged or XChanged then DoResize(Msg.WindowPos.cx - Width, Msg.WindowPos.cy - Height) end; { TEasyItem } constructor TEasyCollectionItem.Create(ACollection: TEasyCollection); begin inherited Create(); Collection := ACollection; Include(FState, esosVisible); Include(FState, esosEnabled); FVisibleIndex := -1; end; destructor TEasyCollectionItem.Destroy; begin SetDestroyFlags; DataInf := nil; if Assigned(OwnerListview) then begin if OwnerListview.HotTrack.PendingObjectCheck = Self then OwnerListview.HotTrack.PendingObjectCheck := nil; if OwnerListview.HotTrack.FPendingObject = Self then OwnerListview.HotTrack.FPendingObject := nil; end; Freeing; inherited; if OwnsPaintInfo then FreeAndNil(FPaintInfo); end; function TEasyCollectionItem.AllowDrag(ViewportPt: TPoint): Boolean; begin Result := True end; function TEasyCollectionItem.DefaultImageList(ImageSize: TEasyImageSize): TCustomImageList; begin Result := nil; case ImageSize of eisSmall: Result := OwnerListview.ImagesSmall; eisLarge: Result := OwnerListview.ImagesLarge; eisExtraLarge: Result := OwnerListview.ImagesExLarge; end end; function TEasyCollectionItem.GetAlignment: TAlignment; begin Result := PaintInfo.Alignment end; function TEasyCollectionItem.GetBold: Boolean; begin Result := esosBold in State end; function TEasyCollectionItem.GetBorder: Integer; begin Result := PaintInfo.Border end; function TEasyCollectionItem.GetBorderColor: TColor; begin Result := PaintInfo.BorderColor end; function TEasyCollectionItem.GetCaption: WideString; begin Result := GetCaptions(0) end; function TEasyCollectionItem.GetCaptionIndent: Integer; begin Result := PaintInfo.CaptionIndent end; function TEasyCollectionItem.GetChecked: Boolean; begin Result := esosChecked in State end; function TEasyCollectionItem.GetCheckFlat: Boolean; begin Result := PaintInfo.CheckFlat end; function TEasyCollectionItem.GetCheckHovering: Boolean; begin Result := esosCheckHover in FState end; function TEasyCollectionItem.GetCheckIndent: Integer; begin Result := PaintInfo.CheckIndent end; function TEasyCollectionItem.GetCheckPending: Boolean; begin Result := esosCheckPending in FState end; function TEasyCollectionItem.GetChecksize: Integer; begin Result := PaintInfo.Checksize end; function TEasyCollectionItem.GetCheckType: TEasyCheckType; begin Result := PaintInfo.CheckType end; function TEasyCollectionItem.GetClicking: Boolean; begin Result := esosClicking in State end; function TEasyCollectionItem.GetCut: Boolean; begin Result := esosCut in State end; function TEasyCollectionItem.GetDataInf: IUnknown; begin Result := FDataInf; end; function TEasyCollectionItem.GetDestroying: Boolean; begin Result := esosDestroying in State end; function TEasyCollectionItem.GetDisplayName: WideString; begin if Caption <> '' then Result := Caption else Result:= ClassName; end; function TEasyCollectionItem.GetEnabled: Boolean; begin Result := esosEnabled in State end; function TEasyCollectionItem.GetFocused: Boolean; begin Result := esosFocused in State end; function TEasyCollectionItem.GetGhosted: Boolean; begin Result := esosGhosted in State end; function TEasyCollectionItem.GetHilighted: Boolean; begin Result := esosHilighted in State end; function TEasyCollectionItem.GetHotTracking(MousePos: TPoint): Boolean; begin Result := esosHotTracking in State end; function TEasyCollectionItem.GetImageIndent: Integer; begin Result := PaintInfo.ImageIndent end; function TEasyCollectionItem.GetImageIndex: TCommonImageIndexInteger; begin Result := GetImageIndexes(0) end; function TEasyCollectionItem.GetImageOverlayIndex: TCommonImageIndexInteger; begin Result := GetImageOverlayIndexes(0) end; function TEasyCollectionItem.GetIndex: Integer; begin Result := Collection.FList.IndexOf(Self) end; function TEasyCollectionItem.GetInitialized: Boolean; begin Result := esosInitialized in State end; function TEasyCollectionItem.GetOwner: TPersistent; begin Result := FCollection end; function TEasyCollectionItem.GetOwnerListview: TCustomEasyListview; begin Result := TEasyCollection( Collection).FOwnerListview end; function TEasyCollectionItem.GetPaintInfo: TEasyPaintInfoBasic; begin if Assigned(FPaintInfo) then Result := FPaintInfo else Result := LocalPaintInfo end; function TEasyCollectionItem.GetSelected: Boolean; begin Result := esosSelected in State end; function TEasyCollectionItem.GetVAlignment: TCommonVAlignment; begin Result := PaintInfo.VAlignment end; function TEasyCollectionItem.GetViewRect: TRect; begin Result := DisplayRect end; function TEasyCollectionItem.GetVisible: Boolean; begin Result := esosVisible in State end; function TEasyCollectionItem.QueryInterface(const IID: TGUID; out Obj): HResult; begin Result := E_NOINTERFACE end; function TEasyCollectionItem._AddRef: Integer; begin Result := -1 end; function TEasyCollectionItem._Release: Integer; begin Result := -1 end; procedure TEasyCollectionItem.Invalidate(ImmediateUpdate: Boolean); var R: TRect; begin if OwnerListview.UpdateCount = 0 then begin R := OwnerListview.Scrollbars.MapViewRectToWindowRect(DisplayRect); if IntersectRect(R, R, OwnerListview.ClientRect) then OwnerListview.SafeInvalidateRect(@R, ImmediateUpdate); end end; procedure TEasyCollectionItem.InvalidateItem(ImmediateRefresh: Boolean); begin Invalidate(ImmediateRefresh) end; procedure TEasyCollectionItem.LoadFromStream(S: TStream; var Version: Integer); var Temp: TEasyStorageObjectStates; T: Longword; begin S.Read(T, SizeOf(T)); // See if we have an old style stream if T <> STREAM_ID_KEY then begin // Old poor way S.Seek(-SizeOf(T), soFromCurrent); Version := 2 // Use to be Collection.StreamVersion but we can hard code 2 since that appeared in version 2 only end else S.Read(Version, SizeOf(Version)); S.Read(Temp, SizeOf(Temp)); // Add back in the stored persisted states Selected := esosSelected in Temp; Enabled := esosEnabled in Temp; Visible := esosVisible in Temp; Checked := esosChecked in Temp; Bold := esosBold in Temp; // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyCollectionItem.MakeVisible(Position: TEasyMakeVisiblePos); begin end; procedure TEasyCollectionItem.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); var Temp: TEasyStorageObjectStates; Key: Integer; begin Key := STREAM_ID_KEY; S.Write(Key, SizeOf(Key)); S.Write(Version, SizeOf(Version)); Temp := State; // Only save certin states that should be persistent Temp := State * PERSISTENTOBJECTSTATES; S.Write(Temp, SizeOf(Temp)); // For new objects test the stream version first // if Version then // begin // WriteStream.... // end end; procedure TEasyCollectionItem.SetAlignment(Value: TAlignment); begin if Value <> Alignment then begin PaintInfo.Alignment := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetBold(const Value: Boolean); begin if Value xor (esosBold in FState) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosBold); LosingBold end else begin if CanChangeBold(Value) then begin if Value then begin Include(FState, esosBold); GainingBold end else begin Exclude(FState, esosBold); LosingBold end end end end end; procedure TEasyCollectionItem.SetBorder(Value: Integer); begin if Value <> Border then begin if Value < 0 then PaintInfo.Border := 0 else PaintInfo.Border := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetBorderColor(Value: TColor); begin if Value <> BorderColor then begin if Value < 0 then PaintInfo.BorderColor := 0 else PaintInfo.BorderColor := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetCaption(Value: WideString); begin Captions[0] := Value end; procedure TEasyCollectionItem.SetCaptionIndent(Value: Integer); begin if Value <> CaptionIndent then begin if Value < 0 then PaintInfo.CaptionIndent := 0 else PaintInfo.CaptionIndent := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetChecked(Value: Boolean); begin if Value xor (esosChecked in FState) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosChecked); LosingCheck end else begin if CanChangeCheck(Value) then begin if Value then begin Include(FState, esosChecked); GainingCheck end else begin Exclude(FState, esosChecked); LosingCheck end end end end end; procedure TEasyCollectionItem.SetCheckFlat(Value: Boolean); begin if Value <> CheckFlat then begin PaintInfo.CheckFlat := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetCheckHovering(Value: Boolean); begin if Value xor (esosCheckHover in FState) then begin if Value then Include(FState,esosCheckHover) else Exclude(FState, esosCheckHover); Invalidate(False) end end; procedure TEasyCollectionItem.SetCheckIndent(Value: Integer); begin if Value <> CheckIndent then begin if Value < 1 then PaintInfo.CheckIndent := 0 else PaintInfo.CheckIndent := Value; Invalidate(False) end; end; procedure TEasyCollectionItem.SetCheckPending(Value: Boolean); begin if Value xor (esosCheckPending in FState) then begin if Value then Include(FState,esosCheckPending) else Exclude(FState, esosCheckPending); Invalidate(False) end end; procedure TEasyCollectionItem.SetChecksize(Value: Integer); begin if Value <> Checksize then begin if Value < 0 then PaintInfo.Checksize := 0 else PaintInfo.Checksize := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetCheckType(Value: TEasyCheckType); begin if Value <> CheckType then begin PaintInfo.CheckType := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetClicking(Value: Boolean); begin if Value then Include(FState, esosClicking) else Exclude(FState, esosClicking) end; procedure TEasyCollectionItem.SetCut(Value: Boolean); begin if Value xor (esosCut in State) then begin if Value then Include(FState, esosCut) else Exclude(FState, esosCut); Invalidate(False) end end; procedure TEasyCollectionItem.SetData(Value: TObject); begin FData := Value end; procedure TEasyCollectionItem.SetDataInf(const Value: IUnknown); var Notifier: IEasyNotifier; begin if Value <> FDataInf then begin if Supports(DataInf, IEasyNotifier, Notifier) then Notifier.OnUnRegisterNotify(Self); FDataInf := Value; if Supports(DataInf, IEasyNotifier, Notifier) then Notifier.OnRegisterNotify(Self) end end; procedure TEasyCollectionItem.SetDestroyFlags; begin Include(FState, esosDestroying); end; procedure TEasyCollectionItem.SetEnabled(Value: Boolean); begin if Value xor (esosEnabled in FState) then begin if State * [esosDestroying] <> [] then begin // Disabled items can't have the focus or selection Focused := False; Selected := False; Exclude(FState, esosEnabled); LosingEnable end else begin if CanChangeEnable(Value) then begin if Value then begin Include(FState, esosEnabled); GainingEnable end else begin // Disabled items can't have the focus or selection Focused := False; Selected := False; Exclude(FState, esosEnabled); LosingEnable end end end end end; procedure TEasyCollectionItem.SetFocused(Value: Boolean); begin if Visible and Enabled then begin if Value xor (esosFocused in State) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosFocused); LosingFocus end else begin if CanChangeFocus(Value) then begin if Value then begin Include(FState, esosFocused); GainingFocus end else begin Exclude(FState, esosFocused); LosingFocus end end end end end end; procedure TEasyCollectionItem.SetGhosted(const Value: Boolean); begin if Value xor (esosGhosted in FState) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosGhosted); LosingGhosted end else begin if Value then begin Include(FState, esosGhosted); GainingGhosted end else begin Exclude(FState, esosGhosted); LosingGhosted end end end end; procedure TEasyCollectionItem.SetHilighted(Value: Boolean); begin if Value xor (esosHilighted in FState) then begin if State * [esosDestroying] <> [] then begin // Disabled items can't have the focus or selection Focused := False; Selected := False; Exclude(FState, esosHilighted); LosingHilight end else begin if Value then begin Include(FState, esosHilighted); GainingHilight end else begin Exclude(FState, esosHilighted); LosingHilight end end end end; procedure TEasyCollectionItem.SetHotTracking(MousePos: TPoint; Value: Boolean); begin if Value xor (esosHotTracking in FState) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosHotTracking); LosingHotTracking end else begin if CanChangeHotTracking(Value) then begin if Value then begin Include(FState, esosHotTracking); GainingHotTracking(MousePos) end else begin Exclude(FState, esosHotTracking); LosingHotTracking end end end end end; procedure TEasyCollectionItem.SetImageIndent(Value: Integer); begin if Value <> ImageIndent then begin if Value < 0 then PaintInfo.ImageIndent := 0 else PaintInfo.ImageIndent := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetImageIndex(const Value: TCommonImageIndexInteger); begin ImageIndexes[0] := Value end; procedure TEasyCollectionItem.SetImageOverlayIndex(const Value: TCommonImageIndexInteger); begin ImageOverlayIndexes[0] := Value end; procedure TEasyCollectionItem.SetInitialized(Value: Boolean); begin if Value xor (esosInitialized in State) then begin if Value then begin Include(FState, esosInitialized); Initialize; end else Exclude(FState, esosInitialized) end end; procedure TEasyCollectionItem.SetPaintInfo(Value: TEasyPaintInfoBasic); begin FPaintInfo := Value end; procedure TEasyCollectionItem.SetSelected(Value: Boolean); begin if Visible and Enabled then begin if Value xor (esosSelected in State) then begin if State * [esosDestroying] <> [] then begin Exclude(FState, esosSelected); LosingSelection end else begin if CanChangeSelection(Value) then begin if Value then begin Include(FState, esosSelected); GainingSelection end else begin Exclude(FState, esosSelected); LosingSelection end end end end end end; procedure TEasyCollectionItem.SetVAlignment(Value: TCommonVAlignment); begin if Value <> VAlignment then begin PaintInfo.VAlignment := Value; Invalidate(False) end end; procedure TEasyCollectionItem.SetVisible(Value: Boolean); begin if Value xor (esosVisible in State) then begin if State * [esosDestroying] <> [] then begin // Invisible Objects can't be focused or selected Focused := False; Selected := False; if not OwnerListview.AllowHiddenCheckedItems then Checked := False; Exclude(FState, esosVisible); LosingVisibility; end else begin if CanChangeVisibility(Value) then begin if Value then begin Include(FState, esosVisible); GainingVisibility end else begin // Invisible Objects can't be focused or selected or Focused Focused := False; Selected := False; if not OwnerListview.AllowHiddenCheckedItems then Checked := False; Exclude(FState, esosVisible); LosingVisibility; end end end end end; procedure TEasyCollectionItem.UnRegister; begin FDataInf := nil end; { TEasyCollection } constructor TEasyCollection.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FItemClass := TEasyCollectionItem; FList := TList.Create; VisibleList := TList.Create; end; destructor TEasyCollection.Destroy; begin Clear; inherited; FreeAndNil(FVisibleList); FreeAndNil(FList); end; function TEasyCollection.Add(Data: TObject = nil): TEasyCollectionItem; begin Result := ItemClass.Create(Self); if Assigned(Result) then begin FList.Add(Result); ReIndexItems; DoItemAdd(Result, FList.Count - 1); Result.Data := Data; DoStructureChange end end; function TEasyCollection.DoStore: Boolean; begin Result := (FList.Count > 0) and not HideFromDFM end; function TEasyCollection.FirstVisible: TEasyColumn; begin if VisibleList.Count > 0 then Result := TEasyColumn( VisibleList[0]) else Result := nil end; function TEasyCollection.GetCount: Integer; begin Result := FList.Count end; function TEasyCollection.GetItem(Index: Integer): TEasyCollectionItem; begin Result := TEasyCollectionItem(FList.List[Index]) end; function TEasyCollection.GetOwner: TPersistent; begin Result:= FOwnerListview end; function TEasyCollection.GetOwnerListview: TCustomEasyListview; begin Result := FOwnerListview end; function TEasyCollection.GetReIndexDisable: Boolean; begin Result := FReIndexCount > 0 end; function TEasyCollection.GetVisibleCount: Integer; begin Result := FVisibleList.Count end; function TEasyCollection.Insert(Index: Integer; Data: TObject = nil): TEasyCollectionItem; begin Result := ItemClass.Create(Self); if Assigned(Result) then begin FList.Insert(Index, Result); ReIndexItems; DoItemAdd(Result, Index); Result.Data := Data; DoStructureChange end end; function TEasyCollection.LastVisible: TEasyColumn; begin if VisibleList.Count > 0 then Result := TEasyColumn( VisibleList[VisibleList.Count - 1]) else Result := nil end; function TEasyCollection.NextVisible(Column: TEasyColumn): TEasyColumn; var i: Integer; begin Result := nil; if Assigned(Column) then begin i := Column.Index + 1; while not Assigned(Result) and (i < Count) do begin if Items[i].Visible then Result := TEasyColumn( Items[i]); Inc(i) end end end; function TEasyCollection.PrevVisible(Column: TEasyColumn): TEasyColumn; var i: Integer; begin Result := nil; if Assigned(Column) then begin i := Column.Index - 1; while not Assigned(Result) and (i < Count) do begin if Items[i].Visible then Result := TEasyColumn( Items[i]); Dec(i) end end end; procedure TEasyCollection.Clear(FreeItems: Boolean = True); var i: Integer; begin if FList.Count > 0 then begin BeginUpdate(False); try // Need to make sure all items are valid so nothing unexpected happens in the // controls events when the item state changes for i := 0 to FList.Count - 1 do begin TEasyCollectionItem(FList[i]).SetDestroyFlags; TEasyCollectionItem(FList[i]).Focused := False; TEasyCollectionItem(FList[i]).Selected := False; end; if FreeItems then for i := FList.Count - 1 downto 0 do // Walk backwords TEasyCollectionItem(FList[i]).Free; finally FList.Clear; FVisibleList.Clear; // The scrollbars do not update correctly on nested BeginUpdate/EndUpdate if Assigned(OwnerListview) and OwnerListview.HandleAllocated then begin OwnerListview.Scrollbars.OffsetX := 0; OwnerListview.Scrollbars.OffsetY := 0; end; EndUpdate; end; end; end; procedure TEasyCollection.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineBinaryProperty('Items', ReadItems, WriteItems, DoStore); end; procedure TEasyCollection.Delete(Index: Integer); var Item: TEasyCollectionItem; begin Item := FList[Index]; Item.SetDestroyFlags; Item.Focused := False; Item.Selected := False; FList.Delete(Index); Item.Free; ReIndexItems; DoStructureChange end; procedure TEasyCollection.DoItemAdd(Item: TEasyCollectionItem; Index: Integer); begin end; procedure TEasyCollection.DoStructureChange; begin end; procedure TEasyCollection.EndUpdate(Invalidate: Boolean = True); begin inherited; OwnerListview.EndUpdate(Invalidate); end; procedure TEasyCollection.BeginUpdate(ReIndex: Boolean); begin inherited; OwnerListview.BeginUpdate; end; procedure TEasyCollection.Exchange(Index1, Index2: Integer); var Temp: TEasyCollectionItem; begin Temp := TEasyCollectionItem( FList[Index1]); FList[Index1] := FList[Index2]; FList[Index2] := Temp; ReIndexItems; DoStructureChange end; procedure TEasyCollection.MakeAllVisible; var i: Integer; begin for i := 0 to Count - 1 do Items[i].Visible := True end; procedure TEasyCollection.ReadItems(Stream: TStream); var i, ItemCount: Integer; StreamVersion: Integer; Cls: TClass; begin Clear; StreamVersion := StreamHelper.ReadInteger(Stream); ItemCount := StreamHelper.ReadInteger(Stream); if StreamVersion > 4 then begin // Since ELV can store more than one class type of Collection Items the streaming // must be more sophisticated (i.e. it can have virtual, custom, and stored items // all in the listview at the same time) It must check the class type of every // object to make sure it creates the correct item type for i := 0 to ItemCount - 1 do begin Cls := GetClass(StreamHelper.ReadString(Stream)); Assert(Cls <> nil, 'If using custom item types for Item, Groups or Columns you must register them with the streaming system with RegisterClass(TMyEasyClassItemType)'); if Assigned(Cls) then begin FItemClass := TEasyCollectionItemClass( Cls); Add.LoadFromStream(Stream, StreamVersion); end end end else begin // Stream will fill version in on first read for i := 0 to ItemCount - 1 do Add.LoadFromStream(Stream, StreamVersion); end end; procedure TEasyCollection.ReIndexItems; var i: Integer; begin if not OwnerListview.Groups.ReIndexDisable then begin for i := 0 to List.Count - 1 do TEasyCollectionItem( List[i]).FIndex := i end end; procedure TEasyCollection.SetItem(Index: Integer; Value: TEasyCollectionItem); begin FList[Index] := Value end; procedure TEasyCollection.SetReIndexDisable(const Value: Boolean); begin if Value then begin Inc(FReIndexCount) end else begin Dec(FReIndexCount); if ReIndexCount <=0 then begin ReIndexCount := 0; ReIndexItems end end end; procedure TEasyCollection.WriteItems(Stream: TStream); var i: Integer; begin // Write the Current Stream Version to the stream StreamHelper.WriteInteger(Stream, EASYLISTVIEW_STREAM_VERSION); // Store the number of items we are storing StreamHelper.WriteInteger(Stream, FList.Count); for i := 0 to FList.Count - 1 do begin StreamHelper.WriteString(Stream, TEasyCollectionItem( Items[i]).ClassName); TEasyCollectionItem( Items[i]).SaveToStream(Stream); // Write custom data to the stream end end; { TEasyHeader } constructor TEasyHeader.Create(AnOwner: TCustomEasyListview); begin inherited; FColumns := TEasyColumns.Create(AnOwner); FPositions := TColumnPos.Create; FDragManager := TEasyHeaderDragManager.Create(AnOwner); DragManager.Header := Self; FFont := TFont.Create; FHeight := 21; FColor := clBtnFace; FSizeable := True; Draggable := True; LastWidth := -1; FStreamColumns := True; FAutoSizeHeight := True; FAutoSizeHeightMargin := 8; end; destructor TEasyHeader.Destroy; begin Columns.Clear; FreeAndNil(FCanvasStore); inherited; FreeAndNil(FColumns); FreeAndNil(FPositions); FreeAndNil(FFont); FreeAndNil(FDragManager); end; function TEasyHeader.FirstColumn: TEasyColumn; begin if Columns.Count > 0 then Result := Columns[0] else Result := nil end; function TEasyHeader.FirstColumnByPosition: TEasyColumn; begin if Positions.Count > 0 then Result := Positions[0] else Result := nil end; function TEasyHeader.FirstColumnInRect(ViewportRect: TRect): TEasyColumn; // // Always assumes by Position as this is a UI function // var i: Integer; ScratchR: TRect; begin Result := nil; i := 0; OffsetRect(ViewportRect, 0, -ViewportRect.Top); while (i < Positions.Count) and not Assigned(Result) do begin if Positions[i].Visible then if IntersectRect(ScratchR, Positions[i].DisplayRect, ViewportRect) then Result := Positions[i]; Inc(i) end end; function TEasyHeader.FirstVisibleColumn: TEasyColumn; var i: Integer; Column: TEasyColumn; begin Result := nil; Column := FirstColumn; i := 0; while not Assigned(Result) and (i < Columns.Count) do begin if Assigned(Column) then begin if Column.Visible then Result := Column else begin Column := NextColumn(Column); Inc(i) end; end end end; function TEasyHeader.GetCanvasStore: TEasyCanvasStore; begin if not Assigned(FCanvasStore) then FCanvasStore := TEasyCanvasStore.Create; Result := FCanvasStore end; function TEasyHeader.GetDisplayRect: TRect; begin Result := Rect(0, 0, OwnerListview.ClientWidth, RuntimeHeight) end; function TEasyHeader.GetDraggable: Boolean; begin Result := DragManager.Enabled end; function TEasyHeader.GetFixedSingleColumn: Boolean; begin if OwnerListview.HandleAllocated then begin if Columns.Count = 0 then Columns.Add.Width := OwnerListview.ClientWidth - 1 end; Result := FFixedSingleColumn; end; function TEasyHeader.GetHeight: Integer; var TextMetrics: TTextMetric; DC: HDC; OldFont: THandle; begin Result := FHeight; if AutoSizeHeight then begin DC := GetDC(0); OldFont := SelectObject(DC, Font.Handle); try if GetTextMetrics(DC, TextMetrics) then if TextMetrics.tmHeight + AutoSizeHeightMargin > FHeight then Result := TextMetrics.tmHeight + AutoSizeHeightMargin; ReleaseDC(0, DC); finally if OldFont <> 0 then SelectObject(DC, OldFont); end end end; function TEasyHeader.GetMouseCaptured: Boolean; begin Result := (ebcsHeaderCapture in OwnerListview.States) and (ehsMouseCaptured in State) end; function TEasyHeader.GetRuntimeHeight: Integer; begin if OwnerListview.ViewSupportsHeader and Visible then Result := Height else Result := 0; end; function TEasyHeader.InCheckZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; var RectArray: TEasyRectArrayObject; begin Result := False; Column := Columns.ColumnByPoint(ViewportPt); if Assigned(Column) then begin Column.View.ItemRectArray(Column, RectArray); Result := PtInRect(RectArray.CheckRect, ViewportPt) end end; function TEasyHeader.InDropDownButtonZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; var RectArray: TEasyRectArrayObject; begin Result := False; Column := Columns.ColumnByPoint(ViewportPt); if Assigned(Column) then begin Column.View.ItemRectArray(Column, RectArray); Result := PtInRect(RectArray.DropDownArrow, ViewportPt) end end; function TEasyHeader.InHotTrackZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; var i: Integer; R, ClientR: TRect; begin Result := False; if OwnerListview.PaintInfoColumn.HotTrack then begin Column := nil; ClientR := OwnerListview.ClientRect; if OwnerListview.ScrollHeaderHorz then OffsetRect(ClientR, OwnerListview.Scrollbars.OffsetX, 0); i := 0; while not Result and (i < OwnerListview.Header.Positions.Count) do begin R := OwnerListview.Header.Positions[i].DisplayRect; // Don't switch hottracking column until done with resize arrow Inc(R.Right, RESIZEHITZONEMARGIN + 1); IntersectRect(R, R, ClientR); if PtInRect(R, ViewportPt) then begin Column := OwnerListview.Header.Positions[i]; Result := True end; Inc(i) end; if not Result then Result := Assigned(HotTrackedColumn); end end; function TEasyHeader.InPressZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; var i: Integer; R: TRect; begin Result := False; Column := nil; i := OwnerListview.Header.Positions.Count - 1; while not Result and (i > -1) do begin R := OwnerListview.Header.Positions[i].DisplayRect; if PtInRect(R, ViewportPt) then begin Column := OwnerListview.Header.Positions[i]; if Assigned(Column) then Result := Column.Clickable end; Dec(i) end end; function TEasyHeader.InResizeZone(ViewportPt: TPoint; var Column: TEasyColumn): Boolean; var i: Integer; R, ClientR: TRect; begin Result := False; if Sizeable then begin Column := nil; i := OwnerListview.Header.Positions.Count - 1; ClientR := OwnerListview.ClientRect; if OwnerListview.ScrollHeaderHorz then OffsetRect(ClientR, OwnerListview.Scrollbars.OffsetX, 0); while not Result and (i > -1) do begin if Positions[i].Visible then begin R := Positions[i].DisplayRect; if (ViewportPt.X <= R.Right + RESIZEHITZONEMARGIN) and (ViewportPt.X > R.Right - RESIZEHITZONEMARGIN) and (ViewportPt.Y < Height) and (ViewportPt.Y > 0) and (R.Right <= ClientR.Right) then begin Column := OwnerListview.Header.Positions[i]; Result := True end; end; Dec(i) end end end; function TEasyHeader.IsFontStored: Boolean; begin Result := not OwnerListview.ParentFont and not OwnerListview.DesktopFont; end; function TEasyHeader.LastColumn: TEasyColumn; begin if Columns.Count > 0 then Result := Columns[Columns.Count - 1] else Result := nil end; function TEasyHeader.LastColumnByPosition: TEasyColumn; begin if Positions.Count > 0 then Result := Positions[Positions.Count - 1] else Result := nil end; function TEasyHeader.LastVisibleColumn: TEasyColumn; var i: Integer; Column: TEasyColumn; begin Result := nil; Column := LastColumn; i := Columns.Count - 1; while not Assigned(Result) and (i > -1 ) do begin if Assigned(Column) then begin if Column.Visible then Result := Column else begin Column := PrevColumn(Column); Dec(i) end; end end end; function TEasyHeader.NextColumn(AColumn: TEasyColumn): TEasyColumn; begin Result := nil; if AColumn.Index < Columns.Count - 1 then Result := Columns[AColumn.Index + 1] end; function TEasyHeader.NextColumnByPosition(AColumn: TEasyColumn): TEasyColumn; begin Result := nil; if AColumn.Position < Columns.Count - 1 then Result := Positions[AColumn.Position + 1] end; function TEasyHeader.NextColumnInRect(Column: TEasyColumn; ViewportRect: TRect): TEasyColumn; // // Always assumes by Position as this is a UI function // var i: Integer; ScratchR: TRect; Done: Boolean; begin Result := nil; Done := False; if Assigned(Column) then begin i := Column.Position + 1; OffsetRect(ViewportRect, 0, -ViewportRect.Top); while not Assigned(Result) and (i < Positions.Count) and not Done do begin if Positions[i].Visible and (Positions[i].Width > 0) then begin if IntersectRect(ScratchR, Positions[i].DisplayRect, ViewportRect) then Result := Positions[i] else Done := True end; Inc(i) end end end; function TEasyHeader.NextVisibleColumn(Column: TEasyColumn): TEasyColumn; var i: Integer; begin Result := nil; Column := NextColumn(Column); if Assigned(Column) then begin i := Column.Index; while not Assigned(Result) and (i < Columns.Count) do begin if Column.Visible then Result := Column else begin Column := NextColumn(Column); Inc(i) end; end end end; function TEasyHeader.PrevColumn(AColumn: TEasyColumn): TEasyColumn; begin Result := nil; if AColumn.Index > 0 then Result := Columns[AColumn.Index - 1] end; function TEasyHeader.PrevColumnByPosition(AColumn: TEasyColumn): TEasyColumn; begin Result := nil; if AColumn.Position > 0 then Result := Positions[AColumn.Position - 1] end; function TEasyHeader.PrevVisibleColumn(Column: TEasyColumn): TEasyColumn; var i: Integer; begin Result := nil; Column := PrevColumn(Column); if Assigned(Column) then begin i := Column.Index; while not Assigned(Result) and (i > -1 ) do begin if Column.Visible then Result := Column else begin Column := PrevColumn(Column); Dec(i) end end end end; procedure TEasyHeader.CaptureMouse; begin Include(OwnerListview.FStates, ebcsHeaderCapture); Include(FState, ehsMouseCaptured); SetCapture(OwnerListview.Handle); end; procedure TEasyHeader.ClearStates; begin Exclude(FState, ehsMouseCaptured); Exclude(FState, ehsResizing); Exclude(FState, ehsDragging); Exclude(FState, ehsDragPending); Exclude(FState, ehsClickPending); Exclude(FState, ehsResizePending); Exclude(FState, ehsLButtonDown); Exclude(FState, ehsRButtonDown); Exclude(FState, ehsMButtonDown); ReleaseMouse; end; procedure TEasyHeader.ClickColumn(Column: TEasyColumn); const NEXT_SORT_DIRECTION: array[TEasySortDirection] of TEasySortDirection = (esdAscending, esdDescending, esdAscending); var PreviousFocusedColumn: TEasyColumn; begin Exclude(Column.FState, esosClicking); if Column.AutoToggleSortGlyph then begin // If sorting takes a bit it is better to "freeze" the painting // so the sort arrows don't show the "wrong" way then change when // the sort is done. OwnerListview.BeginUpdate; try PreviousFocusedColumn := OwnerListview.Selection.FocusedColumn; OwnerListview.Selection.FocusedColumn := Column; // If the column has changed the previous column must forget its // sort direction. When it is clicked on next time it will start // again with SortDirection = esdAscending. if PreviousFocusedColumn <> Column then PreviousFocusedColumn.SortDirection := esdNone; // Now toggle new column's sort direction and regroup / resort // if necded. Column.SortDirection := NEXT_SORT_DIRECTION[Column.SortDirection]; if OwnerListview.Sort.AutoReGroup and OwnerListview.IsGrouped then OwnerListview.Sort.ReGroup(Column) else if (OwnerListview.Sort.AutoSort) or (Column.AutoSortOnClick) then OwnerListview.Sort.SortAll(Column.AutoSortOnClick); finally OwnerListview.EndUpdate end; end; end; procedure TEasyHeader.DoMouseDown(var Message: TWMMouse; Button: TCommonMouseButton; Shift: TShiftState; Column: TEasyColumn); begin if Assigned(OwnerListview.OnHeaderMouseDown) then OwnerListview.OnHeaderMouseDown(OwnerListview, Button, Shift, Message.XPos, Message.YPos, Column) end; procedure TEasyHeader.DoMouseMove(var Message: TWMMouse; Shift: TShiftState); begin if Assigned(OwnerListview.OnHeaderMouseUp) then OwnerListview.OnHeaderMouseMove(OwnerListview, Shift, Message.XPos, Message.YPos) end; procedure TEasyHeader.DoMouseUp(var Message: TWMMouse; Button: TCommonMouseButton; Shift: TShiftState; Column: TEasyColumn); begin if Assigned(OwnerListview.OnHeaderMouseUp) then OwnerListview.OnHeaderMouseUp(OwnerListview, Button, Shift, Message.XPos, Message.YPos, Column) end; procedure TEasyHeader.HandleHotTrack(Msg: TWMMouse; ForceClear: Boolean); var TempColumn, OldColumn: TEasyColumn; DropDownButtonPending: Boolean; begin if ForceClear then begin if Assigned(HotTrackedColumn) then begin ReleaseMouse; OldColumn := HotTrackedColumn; HotTrackedColumn := nil; OldColumn.Invalidate(True) end; end else begin DropDownButtonPending := False; if Assigned(DropDownHoverColumn) then DropDownButtonPending := cdbsClickPending in DropDownHoverColumn.DropDownButton.State; if not DropDownButtonPending then begin if OwnerListview.ScrollHeaderHorz then Inc(Msg.Pos.x, OwnerListview.Scrollbars.OffsetX); if not ([ehsResizing, ehsResizePending, ehsClickPending, ehsDragging, ehsClickPending] * State <> []) {and not DropDownButtonPending} then if InHotTrackZone(SmallPointToPoint(Msg.Pos), TempColumn) or Assigned(HotTrackedColumn) then begin if TempColumn <> HotTrackedColumn then begin if Assigned(HotTrackedColumn) then begin ReleaseMouse; OldColumn := HotTrackedColumn; HotTrackedColumn := nil; OldColumn.Invalidate(True) end; HotTrackedColumn := TempColumn; if Assigned(HotTrackedColumn) then begin CaptureMouse; HotTrackedColumn.Invalidate(True) end end end end end end; procedure TEasyHeader.Invalidate(ImmediateUpdate: Boolean); begin if OwnerListview.UpdateCount = 0 then OwnerListview.SafeInvalidateRect(nil, ImmediateUpdate) end; procedure TEasyHeader.InvalidateColumn(Item: TEasyColumn; ImmediateUpdate: Boolean); begin end; procedure TEasyHeader.LoadFromStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited LoadFromStream(S, Version); if StreamColumns then Columns.ReadItems(S) end; procedure TEasyHeader.PaintTo(ACanvas: TCanvas; ARect: TRect); var Column: TEasyColumn; Handled: Boolean; {$IFDEF USETHEMES} PartID, StateID: LongWord; {$ENDIF} begin Handled := False; CanvasStore.StoreCanvasState(ACanvas); OwnerListview.DoPaintHeaderBkGnd(ACanvas, ViewRect, Handled); CanvasStore.RestoreCanvasState(ACanvas); if not Handled then begin {$IFDEF USETHEMES} if OwnerListview.DrawWithThemes then begin PartID := HP_HEADERITEM; StateID := HIS_NORMAL; DrawThemeBackground(OwnerListview.Themes.HeaderTheme, ACanvas.Handle, PartID, StateID, ViewRect, nil); end else {$ENDIF USETHEMES} begin ACanvas.Brush.Color := Color; ACanvas.FillRect(DisplayRect); end; end; Column := FirstColumnInRect(ARect); while Assigned(Column) do begin // Reset the clipping region SelectClipRgn(ACanvas.Handle, 0); Column.Paint(ACanvas, ehtHeader); Column := NextColumnInRect(Column, ARect); end end; procedure TEasyHeader.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S, Version); if StreamColumns then Columns.WriteItems(S) end; procedure TEasyHeader.SetAutoSizeHeight(const Value: Boolean); begin if FAutoSizeHeight <> Value then begin FAutoSizeHeight := Value; OwnerListview.Groups.Rebuild(False) end end; procedure TEasyHeader.SetAutoSizeHeightMargin(const Value: Integer); begin if FAutoSizeHeightMargin <> Value then begin FAutoSizeHeightMargin := Value; if FAutoSizeHeightMargin < 0 then FAutoSizeHeightMargin := 0; if AutoSizeHeight then OwnerListview.Groups.Rebuild(False) end end; procedure TEasyHeader.SetDraggable(Value: Boolean); begin DragManager.Enabled := Value end; procedure TEasyHeader.SetDropDownHoverColumn(const Value: TEasyColumn); begin if FDropDownHoverColumn <> Value then begin if Assigned(FDropDownHoverColumn) then begin Exclude(FDropDownHoverColumn.DropDownButton.FState, cdbsHovering); Exclude(FDropDownHoverColumn.DropDownButton.FState, cdbsDown); Exclude(FDropDownHoverColumn.DropDownButton.FState, cdbsClickPending); FDropDownHoverColumn.Invalidate(True); end; FDropDownHoverColumn := Value; if Assigned(FDropDownHoverColumn) then begin Include(FDropDownHoverColumn.DropDownButton.FState, cdbsHovering); FDropDownHoverColumn.Invalidate(True); end; end end; procedure TEasyHeader.SetFixedSingleColumn(const Value: Boolean); var i: Integer; begin // Columns.Clear; if Value <> FFixedSingleColumn then begin if OwnerListview.HandleAllocated then begin for i := 1 to Columns.Count - 1 do Columns[i].Visible := not Value; if Value then begin if Columns.Count = 0 then Columns.Add.Width := OwnerListview.ClientWidth - 1 else Columns[0].Width := OwnerListview.ClientWidth - 1; end; OwnerListview.Groups.Rebuild; end; FFixedSingleColumn := Value; end end; procedure TEasyHeader.SetHotTrackedColumn(const Value: TEasyColumn); var Pt: TPoint; begin if Value <> FHotTrackedColumn then begin Pt.x := 0; Pt.y := 0; if Assigned(HotTrackedColumn) then HotTrackedColumn.HotTracking[Pt] := False; if Assigned(Value) then Value.HotTracking[Pt] := True; FHotTrackedColumn := Value; end end; procedure TEasyHeader.SetShowInAllViews(const Value: Boolean); begin if Value <> FShowInAllViews then begin FShowInAllViews := Value; OwnerListview.Groups.Rebuild end; end; procedure TEasyHeader.SizeFixedSingleColumn(NewWidth: Integer); begin if Columns.Count > 0 then begin if Columns[0].Width <> NewWidth then begin Columns[0].Width := NewWidth; OwnerListview.Groups.Rebuild(True); end end end; procedure TEasyHeader.SpringColumns(NewWidth: Integer); // // Credit goes to VirtualTreeview by Mike Lischke var I: Integer; SpringCount: Integer; Sign: Integer; ChangeBy: Single; Difference: Single; NewAccumulator: Single; begin ChangeBy := RectWidth(DisplayRect) - FLastWidth; if (ChangeBy <> 0) then begin // Stay positive if downsizing the control. if ChangeBy < 0 then Sign := -1 else Sign := 1; ChangeBy := Abs(ChangeBy); // Count how many columns have spring enabled. SpringCount := 0; for I := 0 to Columns.Count-1 do if Columns[i].AutoSpring and Columns[i].Visible then Inc(SpringCount); if SpringCount > 0 then begin // Calculate the size to add/sub to each columns. Difference := ChangeBy / SpringCount; // Adjust the column's size accumulators and resize if the result is >= 1. for I := 0 to Columns.Count - 1 do if Columns[i].AutoSpring and Columns[i].Visible then begin // Sum up rest changes from previous runs and the amount from this one and store it in the // column. If there is at least one pixel difference then do a resize and reset the accumulator. NewAccumulator := Columns[I].FSpringRest + Difference; // Set new width if at least one pixel size difference is reached. if NewAccumulator >= 1 then FColumns[I].SetWidth(FColumns[I].FWidth + (Trunc(NewAccumulator) * Sign)); FColumns[I].FSpringRest := Frac(NewAccumulator); // Keep track of the size count. ChangeBy := ChangeBy - Difference; // Exit loop if resize count drops below freezing point. if ChangeBy < 0 then Break; end; end; end; end; procedure TEasyHeader.WMContextMenu(var Msg: TMessage); var Column: TEasyColumn; ViewPt, Pt: TPoint; HitInfoColumn: TEasyHitInfoColumn; Menu: TPopupMenu; begin Menu := OwnerListview.PopupMenuHeader; Pt := OwnerListview.ScreenToClient(Point( Msg.LParamLo, Msg.LParamHi)); if OwnerListview.ScrollHeaderHorz then ViewPt := OwnerListview.Scrollbars.MapWindowToView(Pt, False); HitInfoColumn.Column := Columns.ColumnByPoint(ViewPt); Column := Columns.ColumnByPoint(ViewPt); if Assigned(HitInfoColumn.Column) then Column.HitTestAt(ViewPt, HitInfoColumn.HitInfo) else HitInfoColumn.HitInfo := []; // HitInfoColumn.Column will be nil if it hits the backgound of the header OwnerListview.DoColumnContextMenu(HitInfoColumn, Pt, Menu); if Assigned(Menu) then begin Menu.Popup(Msg.LParamLo, Msg.LParamHi); Msg.Result := 1 end else inherited; end; procedure TEasyHeader.WMSize(var Msg: TWMSize); begin {$IFDEF GXDEBUG} SendDebug('Header WMSize'); {$ENDIF GXDEBUG} if LastWidth < 0 then LastWidth := RectWidth(DisplayRect); if FixedSingleColumn then SizeFixedSingleColumn(Msg.Width - 1) else SpringColumns(Msg.Width); LastWidth := RectWidth(DisplayRect) end; function SortByPosition(Item1, Item2: Pointer): Integer; begin Result := TEasyColumn(Item1).Position - TEasyColumn(Item2).Position end; procedure TEasyHeader.Rebuild(Force: Boolean); var i: Integer; begin if Force or ((OwnerListview.UpdateCount = 0) and not(csLoading in OwnerListview.ComponentState) and (OwnerListview.HandleAllocated)) then begin Positions.Clear; Columns.VisibleList.Clear; Positions.Capacity := Positions.Count; for i := 0 to Columns.Count - 1 do Positions.Add(Columns[i]); Positions.Sort(SortByPosition); for i := 0 to Columns.Count - 1 do Positions[i].FPosition := i; for i := 0 to Columns.Count - 1 do begin if Columns[i].Visible then begin Columns.VisibleList.Add(Columns[i]); if FixedSingleColumn then Columns[i].FWidth := OwnerListview.ClientWidth; // do this direct so not to fire events end end; SetRect(FViewRect, 0, 0, 0, 0); for i := 0 to Positions.Count - 1 do begin if i > 0 then begin Positions[i].FDisplayRect := Positions[i-1].FDisplayRect; Positions[i].FDisplayRect.Left := Positions[i].FDisplayRect.Right; if Positions[i].Visible then Positions[i].FDisplayRect.Right := Positions[i].FDisplayRect.Left + Positions[i].Width else Positions[i].FDisplayRect.Right := Positions[i].FDisplayRect.Left; end else begin if Positions[i].Visible then Positions[i].FDisplayRect := Rect(0, 0, Positions[i].Width, Height) else Positions[i].FDisplayRect := Rect(0, 0, 0, Height) end; UnionRect(FViewRect, ViewRect, Positions[i].DisplayRect); if RectWidth(ViewRect) < OwnerListview.Width then FViewRect.Right := OwnerListview.ClientWidth; end; end end; procedure TEasyHeader.ReleaseMouse; begin Exclude(FState, ehsMouseCaptured); Exclude(OwnerListview.FStates, ebcsHeaderCapture); if GetCapture = OwnerListview.Handle then ReleaseCapture end; procedure TEasyHeader.SetColor(Value: TColor); begin if FColor <> Value then begin FColor := Value; Invalidate(False); end end; procedure TEasyHeader.SetFont(Value: TFont); begin Font.Assign(Value) end; procedure TEasyHeader.SetHeight(Value: Integer); begin if FHeight <> Value then begin if Value > -1 then FHeight := Value else FHeight := 0; OwnerListview.Groups.Rebuild end end; procedure TEasyHeader.SetImages(Value: TCustomImageList); begin if Value <> FImages then begin FImages := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyHeader.SetVisible(Value: Boolean); begin if Value <> FVisible then begin FVisible := Value; OwnerListview.Groups.Rebuild end; end; { TEasyItemView } procedure TEasyHeader.WMLButtonDblClk(var Msg: TWMLButtonDblClk); var ViewPt: TPoint; Column: TEasyColumn; Button: TCommonMouseButton; begin Button := KeyStatesToMouseButton(Msg.Keys); ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then Inc(ViewPt.X, OwnerListview.Scrollbars.OffsetX); if InResizeZone(ViewPt, Column) and (ehsResizePending in State) then begin if Column.AutoSizeOnDblClk then Column.AutoSizeToFit end; Column := Columns.ColumnByPoint(ViewPt); OwnerListview.DoHeaderDblClick(Button, SmallPointToPoint(Msg.Pos), KeysToShiftState(Msg.Keys)); if Assigned(Column) then OwnerListview.DoColumnDblClick(Button, KeysToShiftState(Msg.Keys), SmallPointToPoint(Msg.Pos), Column); end; procedure TEasyHeader.WMLButtonDown(var Msg: TWMLButtonDown); var ViewPt: TPoint; TempColumn: TEasyColumn; begin ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then Inc(ViewPt.X, OwnerListview.Scrollbars.OffsetX); Include(FState, ehsLButtonDown); if ehsResizePending in State then begin Exclude(FState, ehsResizePending); Include(FState, ehsResizing); end else if InCheckZone(ViewPt, TempColumn) then begin Include(FState, ehsCheckboxClickPending); OwnerListview.HotTrack.PendingObjectCheck := nil; OwnerListview.CheckManager.PendingObject := TempColumn; end else if InDropDownButtonZone(ViewPt, TempColumn) then begin if TempColumn.DropDownButton.Enabled then begin DropDownHoverColumn := TempColumn; Include(DropDownHoverColumn.DropDownButton.FState, cdbsClickPending); Include(DropDownHoverColumn.DropDownButton.FState, cdbsDown); DropDownHoverColumn.Invalidate(True) end end else if InPressZone(ViewPt, FPressColumn) then begin // Clear the Hottrack item if OwnerListview.PaintInfoColumn.HotTrack then HandleHotTrack(Msg, True); CaptureMouse; if PressColumn.Clickable then begin Include(FState, ehsClickPending); Include(PressColumn.FState, esosClicking); end; if Draggable then Include(FState, ehsDragPending); PressColumn.Invalidate(True); DoMouseDown(Msg, cmbLeft, KeysToShiftState(Msg.Keys), Columns.ColumnByPoint(ViewPt)); end end; procedure TEasyHeader.WMLButtonUp(var Msg: TWMLButtonUp); const NEXT_SORT_DIRECTION: array[TEasySortDirection] of TEasySortDirection = (esdAscending, esdDescending, esdAscending); var ViewPt, Pt: TPoint; PreviousFocusedColumn: TEasyColumn; DoDefault: Boolean; RectArray: TEasyRectArrayObject; begin ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then Inc(ViewPt.X, OwnerListview.Scrollbars.OffsetX); if ehsCheckboxClickPending in State then begin if InCheckZone(ViewPt, PreviousFocusedColumn) then PreviousFocusedColumn.Checked := not PreviousFocusedColumn.Checked; OwnerListview.CheckManager.PendingObject.CheckHovering := False; OwnerListview.CheckManager.PendingObject.CheckPending := False; OwnerListview.CheckManager.PendingObject := nil; end else if ehsResizing in State then begin OwnerListview.DoColumnSizeChanged(ResizeColumn); end else if Assigned(DropDownHoverColumn) and (cdbsClickPending in DropDownHoverColumn.DropDownButton.State) then begin // NEED SHORT CIRCUIT BOOLEAN EVALUATION for this to work if cdbsDown in DropDownHoverColumn.DropDownButton.State then begin DoDefault := True; OwnerListview.DoColumnDropDownButtonClick(DropDownHoverColumn, cmbLeft, KeysToShiftState(Msg.Keys), SmallPointToPoint(Msg.Pos), DoDefault); if DoDefault then begin if Assigned(DropDownHoverColumn.DropDownButton.Menu) then begin DropDownHoverColumn.View.ItemRectArray(DropDownHoverColumn, RectArray); Pt.x := RectArray.DropDownArrow.Left; Pt.y := RectArray.DropDownArrow.Bottom; Pt := OwnerListview.Scrollbars.MapViewToWindow(Pt, False); Pt := OwnerListview.ClientToScreen(Pt); DropDownHoverColumn.DropDownButton.Menu.Popup(Pt.x, Pt.y) end end end; Exclude(DropDownHoverColumn.DropDownButton.FState, cdbsClickPending); DropDownHoverColumn := nil; end else if Assigned(PressColumn) then begin if esosClicking in PressColumn.State then begin ClickColumn(PressColumn); OwnerListview.DoColumnClick(cmbLeft, PressColumn); end else PressColumn.Invalidate(True); end; if [ehsResizing, ehsDragging] * FState = [] then DoMouseUp(Msg, cmbLeft, KeysToShiftState(Msg.Keys), Columns.ColumnByPoint(ViewPt)); Exclude(FState, ehsLButtonDown); Exclude(FState, ehsResizing); Exclude(FState, ehsClickPending); Exclude(FState, ehsDragging); Exclude(FState, ehsDragPending); Exclude(FState, ehsCheckboxClickPending); end; procedure TEasyHeader.WMMouseMove(var Msg: TWMMouseMove); procedure Press(Column: TEasyColumn; Pressed: Boolean); begin if Assigned(Column) then begin if Pressed then Include(Column.FState, esosClicking) else Exclude(Column.FState, esosClicking); Column.Invalidate(True); end; end; var ViewPt: TPoint; Allow, ClearDropDownBtn: Boolean; TempColumn: TEasyColumn; ClientR: TRect; HotTrackCheckObj: TEasyCollectionItem; Effects: TCommonDropEffect; begin ClearDropDownBtn := True; ClientR := ViewRect; ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then begin ViewPt.X := ViewPt.X + OwnerListview.Scrollbars.OffsetX; OffsetRect(ClientR, OwnerListview.Scrollbars.OffsetX, 0); end; if not MouseCaptured and Assigned(Self.HotTrackedColumn) then CaptureMouse; HotTrackCheckObj := nil; if OwnerListview.PaintInfoColumn.HotTrack then HandleHotTrack(Msg, False); if ehsResizing in State then begin Allow := True; OwnerListview.DoColumnSizeChanging(ResizeColumn, ResizeColumn.Width, ViewPt.X - ResizeColumn.DisplayRect.Left, Allow); if Allow then begin ResizeColumn.Width := ViewPt.X - ResizeColumn.DisplayRect.Left; OwnerListview.Groups.Rebuild(True) end end else if ehsDragging in State then begin Effects := cdeMove; DragManager.Drag(OwnerListview.Canvas, ViewPt, KeyToKeyStates(Msg.Keys), Effects); end else if ehsResizePending in State then begin if not InResizeZone(ViewPt, FResizeColumn) then begin FResizeColumn := nil; Exclude(FState, ehsResizePending); ReleaseMouse; OwnerListview.Cursor := crDefault; if Assigned(HotTrackedColumn) then CaptureMouse end end else if (ehsDragPending in State) and DragManager.Enabled then begin if DragDetectPlus(OwnerListview.Handle, SmallPointToPoint(Msg.Pos)) then begin Exclude(FState, ehsDragPending); Exclude(FState, ehsClickPending); Include(FState, ehsDragging); DragManager.Column := PressColumn; Press(PressColumn, False); PressColumn := nil; DragManager.BeginDrag(ViewPt, KeyToKeyStates(Msg.Keys)); end end else if ehsClickPending in State then begin // end else if Assigned(DropDownHoverColumn) and (cdbsClickPending in DropDownHoverColumn.DropDownButton.State) then begin // NEED SHORT CIRCUIT BOOLEAN EVALUATION for this to work if InDropDownButtonZone(ViewPt, TempColumn) and (TempColumn = DropDownHoverColumn) then begin Include(DropDownHoverColumn.DropDownButton.FState, cdbsDown); DropDownHoverColumn.Invalidate(True) end else begin Exclude(DropDownHoverColumn.DropDownButton.FState, cdbsDown); DropDownHoverColumn.Invalidate(True) end; ClearDropDownBtn := False; end else if InCheckZone(ViewPt, TempColumn) then begin HotTrackCheckObj := TempColumn; end else if InResizeZone(ViewPt, FResizeColumn) then begin Allow := True; OwnerListview.DoColumnSizeChanging(ResizeColumn, ResizeColumn.Width, ResizeColumn.Width, Allow); if Allow then begin // Some other thing may have the mouse captured and the Cursor won't take ReleaseCapture; Include(FState, ehsResizePending); OwnerListview.Cursor := crVHeaderSplit; CaptureMouse; end end else if InDropDownButtonZone(ViewPt, TempColumn) then begin DropDownHoverColumn := TempColumn; ClearDropDownBtn := False; end else begin OwnerListview.Cursor := crDefault; DoMouseMove(Msg, KeysToShiftState(Msg.Keys)); end; if (ehsCheckboxClickPending in State) then begin if Assigned(HotTrackCheckObj) then begin if OwnerListview.CheckManager.PendingObject <> HotTrackCheckObj then begin OwnerListview.CheckManager.PendingObject.CheckHovering := True; HotTrackCheckObj := nil end else OwnerListview.CheckManager.PendingObject.CheckHovering := False; end else begin OwnerListview.CheckManager.PendingObject.CheckHovering := True; end; if HotTrackCheckObj <> nil then HotTrackCheckObj := nil; end; if OwnerListview.CheckManager.PendingObject = HotTrackCheckObj then HotTrackCheckObj := nil; OwnerListview.HotTrack.PendingObjectCheck := HotTrackCheckObj; if ClearDropDownBtn then DropDownHoverColumn := nil; end; procedure TEasyHeader.WMRButtonDown(var Msg: TWMRButtonDown); var ViewPt: TPoint; begin ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then Inc(ViewPt.X, OwnerListview.Scrollbars.OffsetX); Include(FState, ehsRButtonDown); DoMouseDown(Msg, cmbRight, KeysToShiftState(Msg.Keys), Columns.ColumnByPoint(ViewPt)); end; procedure TEasyHeader.WMRButtonUp(var Msg: TWMRButtonUp); var ViewPt: TPoint; begin ViewPt := SmallPointToPoint(Msg.Pos); if OwnerListview.ScrollHeaderHorz then Inc(ViewPt.X, OwnerListview.Scrollbars.OffsetX); Exclude(FState, ehsRButtonDown); Exclude(FState, ehsResizing); Exclude(FState, ehsClickPending); Exclude(FState, ehsDragging); Exclude(FState, ehsDragPending); DoMouseUp(Msg, cmbRight, KeysToShiftState(Msg.Keys), Columns.ColumnByPoint(ViewPt)); end; function TEasyViewItem.AllowDrag(Item: TEasyItem; ViewportPoint: TPoint): Boolean; begin Result := True; end; function TEasyViewItem.EditAreaHitPt(Item: TEasyItem; ViewportPoint: TPoint): Boolean; var RectArray: TEasyRectArrayObject; begin Result := False; if Item.Enabled then begin ItemRectArray(Item, OwnerListview.Header.FirstColumn, Item.OwnerListview.ScratchCanvas, '', RectArray); Result := Windows.PtInRect(RectArray.TextRect, ViewportPoint); end end; function TEasyViewItem.ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := RectArray.IconRect end; function TEasyViewItem.ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin if Item.Focused and (OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode) then Result := RectArray.FullTextRect else Result := RectArray.TextRect; end; function TEasyViewItem.FullRowSelect: Boolean; begin Result := False; end; function TEasyViewItem.GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; begin if Image = eikNormal then Result := Item.ImageList[ValidateColumnIndex(Column), PaintImageSize] else Result := Item.StateImageList[ValidateColumnIndex(Column)]; end; function TEasyViewItem.OverlappedFocus: Boolean; // // Returns true if the view will overlap another cell when the object has the focus begin Result := False end; function TEasyViewItem.PaintImageSize: TEasyImageSize; begin Result := eisSmall end; function TEasyViewItem.PaintStateImage: Boolean; begin Result := False end; function TEasyViewItem.SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; var R: TRect; RectArray: TEasyRectArrayObject; begin Result := False; if Item.Enabled then begin ItemRectArray(Item, nil, OwnerListview.ScratchCanvas, '', RectArray); Result := IntersectRect(R, SelectViewportRect, ExpandTextR(Item, RectArray, SelectType)) or IntersectRect(R, SelectViewportRect, ExpandIconR(Item, RectArray, SelectType)) end end; function TEasyViewItem.SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; var RectArray: TEasyRectArrayObject; begin Result := False; if Item.Enabled then begin ItemRectArray(Item, nil, OwnerListview.ScratchCanvas, '', RectArray); Result := Windows.PtInRect(ExpandTextR(Item, RectArray, SelectType), ViewportPoint) or Windows.PtInRect(ExpandIconR(Item, RectArray, SelectType), ViewportPoint) end end; function TEasyViewItem.ValidateColumnIndex(Column: TEasyColumn): Integer; begin if Assigned(Column) then Result := Column.Index else Result := 0 end; procedure TEasyViewItem.AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); begin end; procedure TEasyViewItem.CalculateTextRect(Item: TEasyItem; Column: TEasyColumn; var TextR: TRect; ACanvas: TControlCanvas); // Fits the Text in the PaintInfo.Caption.Text field into the TextR based // on the values in the PaintInfo record. If Canvas is nil then a temporary // canvas is created to fit the text based on the Font in the PaintInfo var DrawTextFlags: TCommonDrawTextWFlags; LocalCanvas: TControlCanvas; begin case PaintTextAlignment(Item, Column) of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case PaintTextVAlignment(Item, Column) of cvaTop: Include(DrawTextFlags, dtTop); cvaBottom: Include(DrawTextFlags, dtBottom); cvaCenter: Include(DrawTextFlags, dtVCenter); end; if not Assigned(ACanvas) then begin LocalCanvas := TControlCanvas.Create; LocalCanvas.Control := OwnerListview end else LocalCanvas := ACanvas; try LoadTextFont(Item, 0, LocalCanvas, False); DrawTextFlags := DrawTextFlags + [dtCalcRectAdjR, dtCalcRect, dtCalcRectAlign]; DrawTextWEx(LocalCanvas.Handle, Item.Captions[0], TextR, DrawTextFlags, 1); finally if not Assigned(ACanvas) then LocalCanvas.Free end; end; function TEasyViewItem.ItemRect(Item: TEasyItem; Column: TEasyColumn; RectType: TEasyCellRectType): TRect; var RectArray: TEasyRectArrayObject; begin Result := Rect(0, 0, 0, 0); // First look for cached rectangles during a drag (* CacheRectangle(Item, RectType, Result, cdrRetrieve); *) if IsRectEmpty(Result) then begin ItemRectArray(Item, Column, OwnerListview.ScratchCanvas, '', RectArray); case RectType of ertBounds: Result := RectArray.BoundsRect; ertIcon: Result := RectArray.IconRect; ertLabel: Result := RectArray.LabelRect; ertClickselectBounds: Result := RectArray.ClickselectBoundsRect; ertDragSelectBounds: Result := RectArray.DragSelectBoundsRect; ertText: Result := RectArray.TextRect; ertFullText: Result := RectArray.FullTextRect; end; (* CacheRectangle(Item, RectType, Result, cdrStore); *) end; end; procedure TEasyViewItem.GetImageSize(Item: TEasyItem; Column: TEasyColumn; var ImageW, ImageH: Integer; Image: TEasyImageKind); var Images: TCustomImageList; ColumnPos: Integer; IsCustom: Boolean; begin ImageW := 0; ImageH := 0; ColumnPos := ValidateColumnIndex(Column); if Image = eikNormal then begin if Item.ImageIndexes[ColumnPos] > -1 then begin Item.ImageDrawIsCustom(Column, IsCustom); if IsCustom then Item.ImageDrawGetSize(Column, ImageW, ImageH) else begin Images := GetImageList(Column, Item, Image); if Assigned(Images) then begin ImageW := Images.Width; ImageH := Images.Height end end end end else begin Images := GetImageList(Column, Item, Image); if Assigned(Images) then begin ImageW := Images.Width; ImageH := Images.Height end end end; function TEasyViewItem.GetStateImageList(Column: TEasyColumn; Item: TEasyItem): TCustomImageList; begin Result := Item.StateImageList[Column.Index] end; procedure TEasyViewItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); // // Grabs all the rectangles for the items within a cell in one call // begin Item.Initialized := True; FillChar(RectArray, SizeOf(RectArray), #0); RectArray.BoundsRect := Item.DisplayRect; InflateRect(RectArray.BoundsRect, -Item.Border, -Item.Border); RectArray.IconRect := RectArray.BoundsRect; RectArray.LabelRect := RectArray.BoundsRect; RectArray.ClickselectBoundsRect := RectArray.BoundsRect; RectArray.DragSelectBoundsRect := RectArray.BoundsRect; RectArray.TextRect := RectArray.BoundsRect; RectArray.SelectionRect := RectArray.BoundsRect; RectArray.FocusChangeInvalidRect := RectArray.BoundsRect; RectArray.EditRect := RectArray.FullTextRect; SetRect(RectArray.CheckRect, 0, 0, 0, 0); end; procedure TEasyViewItem.LoadTextFont(Item: TEasyItem; Position: Integer; ACanvas: TCanvas; Hilightable: Boolean); begin ACanvas.Font.Assign(OwnerListview.Font); ACanvas.Brush.Style := bsClear; if not OwnerListview.ShowInactive then begin if Hilightable then begin if OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode or Item.Hilighted then ACanvas.Font.Color := OwnerListview.Selection.TextColor else ACanvas.Font.Color := OwnerListview.Selection.InactiveTextColor end; if OwnerListview.HotTrack.Enabled and not Item.Hilighted then begin if (OwnerListview.HotTrack.FPendingObject = Item) and not Item.Selected then begin ACanvas.Font.Color := OwnerListview.HotTrack.Color; if OwnerListview.HotTrack.Underline then ACanvas.Font.Style := ACanvas.Font.Style + [fsUnderline] end end end else ACanvas.Font.Color := clGrayText; if Item.Bold then ACanvas.Font.Style := ACanvas.Font.Style + [fsBold]; OwnerListview.DoItemPaintText(Item, Position, ACanvas); end; procedure TEasyViewItem.Paint(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; ViewportClipRect: TRect; ForceSelectionRectDraw: Boolean); // The Canvas's DC offset has been shifted on entry so that the viewport coords // of the item can be use direct within the method var RectArray: TEasyRectArrayObject; Caption: WideString; Handled: Boolean; begin if Item.Visible then begin CanvasStore.StoreCanvasState(ACanvas); try if Assigned(Column) then Caption := Item.Captions[Column.Index] else Caption := Item.Caption; ItemRectArray(Item, Column, ACanvas, Caption, RectArray); Handled := False; // First allow decendents a crack at the painting PaintBefore(Item, Column, Caption, ACanvas, RectArray, Handled); if not Handled then begin // Paint the Selection Rectangle // ************************* if not(OwnerListview.EditManager.Editing and (OwnerListview.EditManager.EditItem = Item)) then PaintSelectionRect(Item, Column, Caption, RectArray, ACanvas, ViewportClipRect, ForceSelectionRectDraw); // Next Paint the Icon or Bitmap Image // ************************* PaintImage(Item, Column, Caption, RectArray, eisSmall, ACanvas); // Now lets paint the Text // ************************* // If focused then show as many lines as necessary // Decendents should override PaintText to change the number of lines // as necessary if not(OwnerListview.EditManager.Editing and (OwnerListview.EditManager.EditItem = Item)) or ((OwnerListview.View = elsReport) and (Column <> OwnerListview.EditManager.EditColumn)) then begin PaintText(Item, Column, Caption, RectArray, ACanvas, PaintTextLineCount(Item, Column)); // Now lets paint Focus Rectangle // ************************* if OwnerListview.Selection.UseFocusRect then PaintFocusRect(Item, Column, Caption, RectArray, ACanvas); end; // Now Paint the Checkbox if applicable PaintCheckBox(Item, Column, RectArray, ACanvas); // Now give decentant a chance to paint anything PaintAfter(Item, Column, Caption, ACanvas, RectArray); end finally CanvasStore.RestoreCanvasState(ACanvas) end end end; procedure TEasyViewItem.PaintAfter(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); begin // // Called after all other drawing is done // end; procedure TEasyViewItem.PaintAlphaBlendedRoundRect(ACanvas: TCanvas; AlphaColor: TColor; GradientBottom: TColor; GradientTop: TColor; var LocalSelWindowClippedRect: TRect; var Rgn: HRGN); var Bits: TBitmap; GlassBits: TBitmap; begin // If it is a round rectangle then we need to create a round region // to "clip" the square Alpha Blended memory bitmap to the round rectangle Bits := TBitmap.Create; try Bits.PixelFormat := pf32Bit; Bits.Width := RectWidth(LocalSelWindowClippedRect); Bits.Height := RectHeight(LocalSelWindowClippedRect); // Make a copy of the background image behind the square text rect BitBlt(Bits.Canvas.Handle, 0, 0, Bits.Width, Bits.Height, ACanvas.Handle, LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, SRCCOPY); Bits.Canvas.Pen.Color := ACanvas.Pen.Color; // Draw the rectangle to it with a clear center Bits.Canvas.Brush.Style := bsClear; RoundRect(Bits.Canvas.Handle, 0, 0, Bits.Width, Bits.Height, OwnerListview.Selection.RoundRectRadius, OwnerListview.Selection.RoundRectRadius); if OwnerListview.Selection.Gradient then begin GlassBits := TBitmap.Create; GlassBits.Width := RectWidth(LocalSelWindowClippedRect); GlassBits.Height := RectHeight(LocalSelWindowClippedRect); GlassBits.PixelFormat := pf32Bit; FillGradient(0, 0, GlassBits.Width, GlassBits.Height, GradientTop, GradientBottom, 0, GlassBits.Height, GlassBits.Canvas); BlendBits(GlassBits, Bits, 80, 20, OwnerListview.Selection.BlurAlphaBkGnd); GlassBits.Free; end else // AlphaBlend the memory bitmap AlphaBlend(0, Bits.Canvas.Handle, Rect(0, 0, Bits.Width, Bits.Height), Point(0, 0), cbmConstantAlphaAndColor, OwnerListview.Selection.BlendAlphaTextRect, ColorToRGB(AlphaColor)); LocalSelWindowClippedRect := OwnerListview.Scrollbars.MapViewRectToWindowRect(LocalSelWindowClippedRect); // Create a round rect region in the Canvas DC to blast the alpha // blended memory bitmap to. The Alpha blending also blended the // corners where we do not need it so we must only copy the actual // round rect area to the Canvas Rgn := CreateRoundRectRgn( LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, LocalSelWindowClippedRect.Right + 1, LocalSelWindowClippedRect.Bottom + 1, OwnerListview.Selection.RoundRectRadius, OwnerListview.Selection.RoundRectRadius); LocalSelWindowClippedRect := OwnerListview.Scrollbars.MapWindowRectToViewRect(LocalSelWindowClippedRect); // Select the new User round rect region to the DC SelectClipRgn(ACanvas.Handle, Rgn); OwnerListview.ClipHeader(ACanvas, False); BitBlt(ACanvas.Handle, LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, RectWidth(LocalSelWindowClippedRect), RectHeight(LocalSelWindowClippedRect), Bits.Canvas.Handle, 0, 0, SRCCOPY); OwnerListview.ClipHeader(ACanvas, True); finally // Remove the User clipping region from the DC if Rgn <> 0 then DeleteObject(Rgn); Bits.Free; end; end; procedure TEasyViewItem.PaintAlphaBlendedSelection(ACanvas: TCanvas; AlphaColor: TColor; HeaderClippedWindowRect: TRect; LocalSelRect: TRect); begin // AlphaBlend does not clip and does not use the DC Origins, must be absolute to physical screen pixels AlphaBlend(0, ACanvas.Handle, HeaderClippedWindowRect, Point(0, 0), cbmConstantAlphaAndColor, OwnerListview.Selection.BlendAlphaTextRect, ColorToRGB(AlphaColor)); ACanvas.Brush.Style := bsClear; Rectangle(ACanvas.Handle, LocalSelRect.Left, LocalSelRect.Top, LocalSelRect.Right, LocalSelRect.Bottom); end; procedure TEasyViewItem.PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); // // Called before all other drawing is done // begin if Item.Border > 0 then begin ACanvas.Brush.Color := Item.BorderColor; ACanvas.FrameRect(RectArray.BoundsRect); end end; procedure TEasyViewItem.PaintCheckBox(Item: TEasyItem; Column: TEasyColumn; RectArray: TEasyRectArrayObject; ACanvas: TCanvas); var PaintCheckBox: Boolean; AbsIndex: Integer; begin PaintCheckBox := not ((Item.CheckType = ectNone) or (Item.CheckType = ettNoneWithSpace)); if Assigned(Column) then begin AbsIndex := Column.Index; if AbsIndex > 0 then PaintCheckBox := False; // Future inhancement, checkboxes in columns // PaintCheckBox := not ((Item.Details[ColumnIndex].CheckType = ectNone) or (Item.Details[ColumnIndex].CheckType = ettNoneWithSpace)); end; if PaintCheckBox then PaintCheckboxCore(Item.CheckType, // TEasyCheckType OwnerListview, // TCustomEasyListview ACanvas, // TCanvas RectArray.CheckRect, // TRect Item.Enabled, // IsEnabled Item.Checked, // IsChecked OwnerListview.CheckManager.PendingObject = Item, // IsHot Item.CheckFlat, // IsFlat Item.CheckHovering, // IsHovering Item.CheckPending, // IsPending Item, Item.Checksize); end; procedure TEasyViewItem.PaintFocusRect(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas); var AbsIndex: Integer; LocalFocusRect: TRect; begin if not FullRowSelect then begin AbsIndex := ValidateColumnIndex(Column); // Only draw the focus rect if the window has focus if Item.Focused and OwnerListview.Focused and ((AbsIndex < 1)) then begin if OwnerListview.Selection.FullCellPaint then begin LocalFocusRect := Item.DisplayRect; UnionRect(LocalFocusRect, LocalFocusRect, RectArray.FullFocusSelRect); if (OwnerListview.View = elsReport) and (OwnerListview.Header.Columns.Count > 0) then begin LocalFocusRect.Left := OwnerListview.Header.Columns[0].DisplayRect.Left; LocalFocusRect.Right := LocalFocusRect.Left + OwnerListview.Header.Columns[0].Width; end end else begin LocalFocusRect := RectArray.FullFocusSelRect; if OwnerListview.Selection.FullItemPaint then UnionRect(LocalFocusRect, LocalFocusRect, RectArray.IconRect); end; ACanvas.Brush.Color := OwnerListview.Color; ACanvas.Font.Color := clBlack; DrawFocusRect(ACanvas.Handle, LocalFocusRect); end end end; procedure TEasyViewItem.PaintAlphaBlendedGradientFill(ACanvas: TCanvas; GradientBottom: TColor; GradientTop: TColor; LocalSelRect: TRect; LocalSelWindowClippedRect: TRect; LocalSelClippedRect: TRect); var Bits: TBitmap; GlassBits: TBitmap; begin Bits := TBitmap.Create; GlassBits := TBitmap.Create; try GlassBits.Width := RectWidth(LocalSelWindowClippedRect); GlassBits.Height := RectHeight(LocalSelWindowClippedRect); GlassBits.PixelFormat := pf32Bit; Bits.Width := GlassBits.Width; Bits.Height := GlassBits.Height; Bits.PixelFormat := pf32Bit; BitBlt(Bits.Canvas.Handle, 0, 0, Bits.Width, Bits.Height, ACanvas.Handle, LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, SRCCOPY); FillGradient(0, 0, GlassBits.Width, GlassBits.Height, GradientTop, GradientBottom, 0, GlassBits.Height, GlassBits.Canvas); BlendBits(GlassBits, Bits, 80, 20, OwnerListview.Selection.BlurAlphaBkGnd); BitBlt(ACanvas.Handle, LocalSelRect.Left, LocalSelWindowClippedRect.Top, Bits.Width, Bits.Height, Bits.Canvas.Handle, 0, 0, SRCCOPY); finally GlassBits.Free; Bits.Free; end; end; procedure TEasyViewItem.PaintImage(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ImageSize: TEasyImageSize; ACanvas: TCanvas); var rgbBk, rgbFg: Longword; fStyle: Integer; OverlayIndex, ImageIndex, PositionIndex, AbsIndex, StateImageIndex: Integer; Images, StateImages: TCustomImageList; DoDefault, IsCustom: Boolean; Rgn: HRgn; TmpBits: TBitmap; R: TRect; W, H, Scale: Double; begin TestAndClipImage(ACanvas, RectArray, Rgn); try if Assigned(Column) then begin AbsIndex := Column.Index; PositionIndex := Column.Position end else begin AbsIndex := 0; PositionIndex := 0; end; DoDefault := True; Images := GetImageList(Column, Item, eikNormal); if OwnerListview.IsThumbnailView then begin InflateRect(RectArray.IconRect, -Item.Border, -Item.Border); Item.ThumbnailDraw(ACanvas, RectArray.IconRect, AlphaBlender, DoDefault); end; // If not using the thumbnail then get the information for the ImageList Indexes if DoDefault then begin Item.ImageDrawIsCustom(Column, IsCustom); if IsCustom then begin Item.ImageDraw(Column, ACanvas, RectArray, AlphaBlender); end else if DoDefault then begin ImageIndex := Item.ImageIndexes[AbsIndex]; OverlayIndex := Item.ImageOverlayIndexes[AbsIndex]; if PaintStateImage then begin StateImageIndex := Item.StateImageIndexes[AbsIndex]; StateImages := GetImageList(Column, Item, eikState); if Assigned(StateImages) and (StateImageIndex > -1) then begin // Set up a normal Imagelist icon fStyle := ILD_TRANSPARENT; rgbBk := CLR_NONE; rgbFg := CLR_NONE; RectArray.StateRect.Left := RectArray.StateRect.Left + (RectWidth(RectArray.StateRect) - Images.Width) div 2; RectArray.StateRect.Top := RectArray.StateRect.Top + (RectHeight(RectArray.StateRect) - Images.Height) div 2; ImageList_DrawEx(StateImages.Handle, StateImageIndex, ACanvas.Handle, RectArray.StateRect.Left, RectArray.StateRect.Top, 0, 0, rgbBk, rgbFg, fStyle); end end; if Assigned(Images) and (ImageIndex > -1) then begin // Set up a normal Imagelist icon fStyle := ILD_TRANSPARENT; rgbBk := CLR_NONE; rgbFg := CLR_NONE; // Set up to blend the Imagelist icon // The param is to allow Thumbnail view to use this paint method and not blend // the image if OwnerListview.Selection.BlendIcon and (((OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode) and Item.Selected) or Item.Hilighted and (PositionIndex < 1)) then begin fStyle := fStyle or ILD_SELECTED; if OwnerListview.Selection.ForceDefaultBlend then rgbFg := CLR_DEFAULT else rgbFg := ColorToRGB(OwnerListview.Selection.Color) end; if not Item.Enabled or Item.Cut or Item.Ghosted or Item.OwnerListview.ShowInactive then begin fStyle := fStyle or ILD_SELECTED; rgbFg := ColorToRGB(OwnerListview.DisabledBlendColor) end; if OverlayIndex > -1 then fStyle := FStyle or IndexToOverLayMask(OverlayIndex); if (RectWidth(RectArray.IconRect) < Images.Width) or (RectHeight(RectArray.IconRect) < Images.Height) then begin if (Images.Width > 0) and (Images.Height > 0) then begin TmpBits := TBitmap.Create; try TmpBits.PixelFormat := pf32Bit; TmpBits.Width := Images.Width; TmpBits.Height := Images.Height; ImageList_DrawEx(Images.Handle, ImageIndex, TmpBits.Canvas.Handle, 0, 0, 0, 0, rgbBk, rgbFg, fStyle); W := RectWidth(RectArray.IconRect)/Images.Width; H := RectHeight(RectArray.IconRect)/Images.Height; if W > H then Scale := H else Scale := W; R := Rect(0, 0, Round(Images.Width*Scale), Round(Images.Height*Scale)); StretchBlt(ACanvas.Handle, RectArray.IconRect.Left + ((RectWidth(RectArray.IconRect) - RectWidth(R)) div 2), RectArray.IconRect.Top + ((RectHeight(RectArray.IconRect) - RectHeight(R)) div 2), RectWidth(R), RectHeight(R), TmpBits.Canvas.Handle, 0, 0, TmpBits.Width, TmpBits.Height, SRCCOPY); finally TmpBits.Free end end end else begin RectArray.IconRect.Left := RectArray.IconRect.Left + (RectWidth(RectArray.IconRect) - Images.Width) div 2; RectArray.IconRect.Top := RectArray.IconRect.Top + (RectHeight(RectArray.IconRect) - Images.Height) div 2; ImageList_DrawEx(Images.Handle, ImageIndex, ACanvas.Handle, RectArray.IconRect.Left, RectArray.IconRect.Top, 0, 0, rgbBk, rgbFg, fStyle); end end end end finally TestAndUnClipImage(ACanvas, RectArray, Rgn); end end; procedure TEasyViewItem.PaintNonAlphaBlendedSelection(ACanvas: TCanvas; LocalSelRect: TRect); begin // Not AlphaBlended is much easier if OwnerListview.Selection.RoundRect then RoundRect(ACanvas.Handle, LocalSelRect.Left, LocalSelRect.Top, LocalSelRect.Right, LocalSelRect.Bottom, OwnerListview.Selection.RoundRectRadius, OwnerListview.Selection.RoundRectRadius) else Rectangle(ACanvas.Handle, LocalSelRect.Left, LocalSelRect.Top, LocalSelRect.Right, LocalSelRect.Bottom); end; procedure TEasyViewItem.PaintSelectionRect(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; ViewportClipRect: TRect; ForceSelectionRectDraw: Boolean); var Rgn: HRGN; // All these rectangles are necessary because the AlphaBlend routine does not respect DC origins and clipping regions. LocalSelRect, // The true Viewpoint Rectangle of the Selection Rectangle, including the Header area if applicable LocalSelWindowClippedRect, // The true Viewpoint Rectangle of the Selection Rectangle, Clipped to the current Physical Window Coordinates LocalSelClippedRect, // The true Viewpoint Rectangle of the Selection Rectangle, excluding the Header area if applicable HeaderClippedWindowRect: TRect; // Rectangle containing the Selection Rectangle that has been translated to Physical Window Coordinates and the Header area clipped off it if necesasry. This rectangle is also clipped to the ClientWindow rectangle AlphaColor, GradientTop, GradientBottom: TColor; DoDraw: Boolean; begin DoDraw := Item.Selected or Item.Hilighted; if DoDraw and Assigned(Column) then DoDraw := (Column.Index < 1); if (DoDraw and not FullRowSelect) or ForceSelectionRectDraw then begin Rgn := 0; // If the Window control is not focused show the selection with innactive colors if OwnerListview.Focused or Item.Hilighted and not Item.OwnerListview.ShowInactive or Item.OwnerListview.Selection.PopupMode then begin ACanvas.Font.Color := OwnerListview.Selection.TextColor; if (Item <> OwnerListview.Selection.FocusedItem) or not OwnerListview.Selection.UseFocusRect then ACanvas.Pen.Color := OwnerListview.Selection.BorderColor else ACanvas.Pen.Color := clLtGray; ACanvas.Brush.Color := OwnerListview.Selection.Color; AlphaColor := OwnerListview.Selection.Color; GradientTop := OwnerListview.Selection.GradientColorTop; GradientBottom := OwnerListview.Selection.GradientColorBottom; end else begin ACanvas.Font.Color := OwnerListview.Selection.InactiveTextColor; ACanvas.Pen.Color := OwnerListview.Selection.InactiveBorderColor; ACanvas.Brush.Color := OwnerListview.Selection.InactiveColor; AlphaColor := OwnerListview.Selection.InactiveColor; GradientTop := OwnerListview.Color; GradientBottom := OwnerListview.Selection.InactiveColor end; if OwnerListview.Selection.GroupSelections and (OwnerListview.View = elsReport) and (Item.Selected or Item.Hilighted or Item.Selected) then begin SetRect(LocalSelRect, 0, 0, 0, 0); if Assigned(Item.SelectionGroup) then begin if Item.Hilighted then begin LocalSelRect := Item.DisplayRect; if not ((OwnerListview.Selection.FullItemPaint) or (OwnerListview.Selection.FullCellPaint) or (OwnerListview.Selection.FullItemPaint)) then LocalSelRect.Left := RectArray.TextRect.Left end else begin if Item.SelectionGroup.FirstItem = Item then begin LocalSelRect := Item.SelectionGroup.DisplayRect; if not(OwnerListview.Selection.FullItemPaint or OwnerListview.Selection.FullCellPaint) then LocalSelRect.Left := RectArray.SelectionRect.Left end end end else begin LocalSelRect := Item.DisplayRect; if not(OwnerListview.Selection.FullItemPaint or OwnerListview.Selection.FullCellPaint) then LocalSelRect.Left := RectArray.SelectionRect.Left end end else if FullRowSelect and (Item.Selected or Item.Hilighted or Item.Selected) then begin // If full row select then the First Column paints the entire row if OwnerListview.Selection.FullCellPaint then LocalSelRect := Item.DisplayRect else begin LocalSelRect := Item.DisplayRect; if not OwnerListview.Selection.FullItemPaint then LocalSelRect.Left := RectArray.SelectionRect.Left; end end else begin if Item.Focused and (OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode) then begin if OwnerListview.Selection.FullCellPaint then begin LocalSelRect := Item.DisplayRect; UnionRect(LocalSelRect, LocalSelRect, RectArray.FullFocusSelRect); if (OwnerListview.View = elsReport) and (OwnerListview.Header.Columns.Count > 0) then begin LocalSelRect.Left := OwnerListview.Header.Columns[0].DisplayRect.Left; LocalSelRect.Right := LocalSelRect.Left + OwnerListview.Header.Columns[0].Width; end end else begin LocalSelRect := RectArray.FullFocusSelRect; // Cover the Icon if FullItemPaint if OwnerListview.Selection.FullItemPaint then UnionRect(LocalSelRect, LocalSelRect, RectArray.IconRect); end end else begin if OwnerListview.Selection.FullCellPaint then begin LocalSelRect := Item.DisplayRect; if (OwnerListview.View = elsReport) and (OwnerListview.Header.Positions.Count > 0) then begin LocalSelRect.Left := OwnerListview.Header.Columns[0].DisplayRect.Left; LocalSelRect.Right := LocalSelRect.Left + OwnerListview.Header.Columns[0].Width; end end else begin LocalSelRect := RectArray.SelectionRect; // Cover the Icon if FullItemPaint if OwnerListview.Selection.FullItemPaint then UnionRect(LocalSelRect, LocalSelRect, RectArray.IconRect); end end end; // LocalSelRect is now set up AfterSelRectCalc(Item, Column, Caption, LocalSelRect); // Clip out the header from the Selection Rectangle, don't need to account for Header // as the DC is offset to take it into account LocalSelClippedRect := LocalSelRect; HeaderClippedWindowRect := OwnerListview.Scrollbars.MapViewRectToWindowRect(LocalSelClippedRect); LocalSelWindowClippedRect := HeaderClippedWindowRect; if HeaderClippedWindowRect.Top < OwnerListview.Header.RuntimeHeight then begin HeaderClippedWindowRect.Top := OwnerListview.Header.RuntimeHeight; // Make it a 0 height rect if it is an improper rect after adjustment if HeaderClippedWindowRect.Top > HeaderClippedWindowRect.Bottom then HeaderClippedWindowRect.Top := HeaderClippedWindowRect.Bottom; LocalSelClippedRect := OwnerListview.Scrollbars.MapViewRectToWindowRect(HeaderClippedWindowRect); end; IntersectRect(LocalSelWindowClippedRect, LocalSelWindowClippedRect, OwnerListview.ClientRect); LocalSelWindowClippedRect := OwnerListview.Scrollbars.MapWindowRectToViewRect(LocalSelWindowClippedRect); IntersectRect(HeaderClippedWindowRect, HeaderClippedWindowRect, OwnerListview.ClientRect); // Stop right side from having rounded corners if extends past right edge of window, // but don't go past the actual width Inc(LocalSelWindowClippedRect.Right, OwnerListview.Selection.RoundRectRadius); if LocalSelWindowClippedRect.Right > LocalSelRect.Right then LocalSelWindowClippedRect.Right := LocalSelRect.Right; if not IsRectEmpty(LocalSelRect) then begin if OwnerListview.Selection.Gradient and not OwnerListview.Selection.AlphaBlend then begin if RectHeight(LocalSelWindowClippedRect) > 0 then begin FillGradient(LocalSelRect.Left, LocalSelWindowClippedRect.Top, LocalSelWindowClippedRect.Right, LocalSelWindowClippedRect.Bottom, GradientTop, GradientBottom, LocalSelWindowClippedRect.Top, LocalSelWindowClippedRect.Bottom, ACanvas); ACanvas.FrameRect(LocalSelRect); end end else if HasMMX and OwnerListview.Selection.AlphaBlend then begin if OwnerListview.Selection.RoundRect then PaintAlphaBlendedRoundRect(ACanvas, AlphaColor, GradientBottom, GradientTop, LocalSelWindowClippedRect, Rgn) else begin if OwnerListview.Selection.Gradient then PaintAlphaBlendedGradientFill(ACanvas, GradientBottom, GradientTop, LocalSelRect, LocalSelWindowClippedRect, LocalSelClippedRect) else PaintAlphaBlendedSelection(ACanvas, AlphaColor, HeaderClippedWindowRect, LocalSelRect); end end else PaintNonAlphaBlendedSelection(ACanvas, LocalSelRect); end end end; procedure TEasyViewItem.PaintText(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; LinesToDraw: Integer); var DrawTextFlags: TCommonDrawTextWFlags; AbsIndex: Integer; Hilightable: Boolean; begin if not IsRectEmpty(RectArray.TextRect) then begin AbsIndex := ValidateColumnIndex(Column); Hilightable := (Item.Selected or Item.Hilighted) and ((AbsIndex = 0) or (FullRowSelect or OwnerListview.Selection.GroupSelections)); LoadTextFont(Item, AbsIndex, ACanvas, Hilightable); DrawTextFlags := [dtEndEllipsis]; if LinesToDraw = 1 then Include(DrawTextFlags, dtSingleLine); case PaintTextAlignment(Item, Column) of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case PaintTextVAlignment(Item, Column) of cvaTop: Include(DrawTextFlags, dtTop); cvaCenter: Include(DrawTextFlags, dtVCenter); cvaBottom: Include(DrawTextFlags, dtBottom); end; OwnerListview.ClipHeader(ACanvas, False); if Item.Focused and (OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode) then DrawTextWEx(ACanvas.Handle, Caption, RectArray.TextRect, DrawTextFlags, LinesToDraw) else DrawTextWEx(ACanvas.Handle, Caption, RectArray.TextRect, DrawTextFlags, LinesToDraw) end end; function TEasyViewItem.PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; begin Result := taCenter end; function TEasyViewItem.PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; begin Result := 2 end; function TEasyViewItem.PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; begin Result := cvaTop end; function TEasyViewItem.PtInRect(Item: TEasyItem; Column: TEasyColumn; Pt: TPoint): Integer; // Compares the passed point with the rectangle of the item. // // If Rect > Pt then Result = 1 // If Rect < Pt then Result = -1 // If Rect = Pt (i.e. the point is within the rect) then Result = 0 // // This code works if the layout of the items is vertical with item numbering // increasing from Left to Right in each Row var CellRect: TRect; begin CellRect := Item.DisplayRect; if Pt.y < CellRect.Top then Result := 1 else if Pt.y > CellRect.Bottom then Result := -1 else if Pt.x < CellRect.Left then begin Result := 1 end else if Pt.x > CellRect.Right then Result := -1 else Result := 0 end; procedure TEasyViewItem.ReSizeRectArray( var RectArray: TEasyRectArrayObjectArray); var OldLen, i: Integer; begin if Length(RectArray) < OwnerListview.Header.Positions.Count then begin OldLen := Length(RectArray); SetLength(RectArray, OwnerListview.Header.Positions.Count); for i := OldLen to OwnerListview.Header.Positions.Count - 1 do FillChar(RectArray[i], SizeOf(RectArray[i]), #0); end else if Length(RectArray) > OwnerListview.Header.Positions.Count then SetLength(RectArray, OwnerListview.Header.Positions.Count); if Length(RectArray) = 0 then begin SetLength(RectArray, 1); FillChar(RectArray[0], SizeOf(RectArray[0]), #0); end end; procedure TEasyViewItem.TestAndClipImage(ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Rgn: HRgn); var R, ImageRect: TRect; begin Rgn := 0; UnionRect(ImageRect, RectArray.IconRect, RectArray.StateRect); if not ContainsRect(RectArray.BoundsRect, ImageRect) then begin // I was hoping that IntersectClipRect would set a clipping region when // I clipped the header in the main control. Then I would get it here and // resort it later. Unfortunately it does not and GetClipRgn returns 0 so // I have to call ClipHeader explicitly. GetClipRgn(ACanvas.Handle, Rgn); IntersectRect(R, ImageRect, RectArray.BoundsRect); IntersectClipRect(ACanvas.Handle, R.Left, R.Top, R.Right, R.Bottom); OwnerListview.ClipHeader(ACanvas, False) end; end; procedure TEasyViewItem.TestAndUnClipImage(ACanvas: TCanvas; RectArray: TEasyRectArrayObject; Rgn: HRgn); var ImageRect: TRect; begin UnionRect(ImageRect, RectArray.IconRect, RectArray.StateRect); if not ContainsRect(RectArray.BoundsRect, ImageRect) then begin if Rgn <> 0 then begin SelectClipRgn(ACanvas.Handle, Rgn); DeleteObject(Rgn) end else begin SelectClipRgn(ACanvas.Handle, 0); OwnerListview.ClipHeader(ACanvas, False) end end; end; function TEasyHeader.GetViewWidth: Integer; begin if Positions.Count > 0 then Result := Positions[Positions.Count - 1].DisplayRect.Right else Result := 0 end; { TEasyDefaultCellSize } constructor TEasyCellSize.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 75; FHeight := 75; FAutoSizeHeight := 75; FAutoSizeWidth := 75; end; function TEasyCellSize.GetHeight: Integer; begin if AutoSize then Result := FAutoSizeHeight else begin Result := FHeight; if Result < 1 then Result := 1 end end; function TEasyCellSize.GetWidth: Integer; begin if AutoSize then Result := FAutoSizeWidth else begin Result := FWidth; if Result < 1 then Result := 1 end end; procedure TEasyCellSize.Assign(Source: TPersistent); begin if Source is TEasyCellSize then begin FHeight := TEasyCellSize(Source).Height; FWidth := TEasyCellSize(Source).Width; // OwnerListview.Groups.Rebuild; end; end; procedure TEasyCellSize.SetAutoSize(const Value: Boolean); begin if Value <> FAutoSize then begin FAutoSize := Value; if not FAutoSize then begin FAutoSizeWidth := FWidth; FAutoSizeHeight := FHeight end; OwnerListview.Groups.Rebuild; end end; procedure TEasyCellSize.SetSize(AWidth, AHeight: Integer); begin if AWidth < 0 then AWidth := 0; if AHeight < 0 then AHeight := 0; if AutoSize then begin if (AWidth <> FWidth) or (AHeight <> FHeight) then begin FAutoSizeWidth := AWidth; FAutoSizeHeight := AHeight; end; end else begin if (AWidth <> FWidth) or (AHeight <> FHeight) then begin FWidth := AWidth; FHeight := AHeight; end; OwnerListview.Groups.Rebuild; end end; procedure TEasyCellSize.SetHeight(Value: Integer); begin if AutoSize then SetSize(FAutoSizeWidth, Value) else SetSize(FWidth, Value); end; procedure TEasyCellSize.SetWidth(Value: Integer); begin if AutoSize then SetSize(Value, FAutoSizeHeight) else SetSize(Value, FHeight); end; { TEasyIconItemView} function TEasyViewIconItem.ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := RectArray.IconRect; end; function TEasyViewIconItem.OverlappedFocus: Boolean; begin Result:= True end; function TEasyViewIconItem.PaintImageSize: TEasyImageSize; begin Result := eisLarge end; function TEasyViewIconItem.PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; begin if Item.Focused and OwnerListview.Focused then Result := -1 else Result := 2 end; procedure TEasyViewIconItem.AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); begin if OwnerListview.Selection.FullCellPaint then InflateRect(LocalSelRect, -2, -2) end; procedure TEasyViewIconItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); var ImageW, ImageH, Left: Integer; DrawTextFlags: TCommonDrawTextWFlags; R: TRect; PositionIndex, AbsIndex: Integer; ACaption: WideString; begin if Assigned(Item) then begin if not Item.Initialized then Item.Initialized := True; if Assigned(Column) then begin AbsIndex := Column.Index; PositionIndex := Column.Position end else begin AbsIndex := 0; PositionIndex := 0 end; if PositionIndex > -1 then begin FillChar(RectArray, SizeOf(RectArray), #0); GetImageSize(Item, Column, ImageW, ImageH, eikNormal); // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** RectArray.BoundsRect := Item.DisplayRect; Inc(RectArray.BoundsRect.Left); // Calculate where the Icon is positioned // ********** // Center Icon horziontally and a few pixels from the top of the cell Left := RectArray.BoundsRect.Left + ((RectWidth(RectArray.BoundsRect) - ImageW) div 2); RectArray.IconRect := Rect(Left, RectArray.BoundsRect.Top + 2, Left + ImageW, RectArray.BoundsRect.Top + 2 + ImageH); // Some margin between the Icon and the Text that belongs to the Icon Rect Inc(RectArray.IconRect.Bottom, 4); // Calculate area that the Checkbox may be drawn // ********** if Item.CheckType <> ectNone then begin R := Checks.Bound[Item.Checksize]; RectArray.CheckRect.Top := RectArray.IconRect.Bottom + 1; // This looks better than centered RectArray.CheckRect.Left := RectArray.BoundsRect.Left + Item.CheckIndent; RectArray.CheckRect.Bottom := RectArray.CheckRect.Top + R.Bottom; RectArray.CheckRect.Right := RectArray.CheckRect.Left + R.Right; end else begin RectArray.CheckRect.Top := RectArray.IconRect.Bottom; RectArray.CheckRect.Left := RectArray.BoundsRect.Left; RectArray.CheckRect.Bottom := RectArray.BoundsRect.Bottom; RectArray.CheckRect.Right := RectArray.BoundsRect.Left; end; // Calculate area that the label may be drawn // ********** // The Label Rect is the remaining area between the Icon Rect and the Bottom // of the Bounds Rect RectArray.LabelRect := Rect(RectArray.CheckRect.Right, RectArray.IconRect.Bottom + 1, RectArray.BoundsRect.Right, RectArray.BoundsRect.Bottom); // Calculate the portion of the Label Rect that the current Text will use // ********** RectArray.TextRect := RectArray.LabelRect; RectArray.FullTextRect := RectArray.LabelRect; // Leave room for a small border between edge of the selection rect and text InflateRect(RectArray.TextRect, -2, -2); InflateRect(RectArray.FullTextRect, -2, -2); DrawTextFlags := [dtCalcRect, dtCalcRectAlign]; DrawTextFlags := DrawTextFlags + [dtCenter]; case PaintTextAlignment(Item, Column) of taCenter: DrawTextFlags := DrawTextFlags + [dtCenter]; taLeftJustify: DrawTextFlags := DrawTextFlags + [dtLeft]; taRightJustify: DrawTextFlags := DrawTextFlags + [dtRight]; end; case PaintTextVAlignment(Item, Column) of cvaCenter: DrawTextFlags := DrawTextFlags + [dtVCenter]; cvaTop: DrawTextFlags := DrawTextFlags + [dtTop]; cvaBottom: DrawTextFlags := DrawTextFlags + [dtBottom]; end; if Assigned(OwnerListview.ScratchCanvas) then begin ACaption := Item.Captions[AbsIndex]; if ACaption = '' then ACaption := ' '; LoadTextFont(Item, PositionIndex, OwnerListview.ScratchCanvas, Item.Selected); DrawTextWEx(OwnerListview.ScratchCanvas.Handle, ACaption, RectArray.FullTextRect, DrawTextFlags, -1); DrawTextWEx(OwnerListview.ScratchCanvas.Handle, ACaption, RectArray.TextRect, DrawTextFlags, 2); end; // Calculate Selection rectangle paint box // ********** RectArray.SelectionRect := RectArray.TextRect; InflateRect(RectArray.SelectionRect, 2, 2); RectArray.FullFocusSelRect := RectArray.FullTextRect; InflateRect(RectArray.FullFocusSelRect, 2, 2); UnionRect(RectArray.ClickselectBoundsRect, RectArray.IconRect, RectArray.TextRect); RectArray.DragSelectBoundsRect := RectArray.ClickselectBoundsRect; UnionRect(RectArray.FocusChangeInvalidRect, RectArray.IconRect, RectArray.FullFocusSelRect); RectArray.EditRect := RectArray.FullTextRect; end end end; procedure TEasyViewIconItem.PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); begin // Skip inherited end; { TEasySmallIconItemView } function TEasyViewSmallIconItem.CalculateDisplayRect(Item: TEasyItem; Column: TEasyColumn): TRect; begin Result := Item.DisplayRect end; function TEasyViewSmallIconItem.ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := Rect(0, 0, 0, 0) end; function TEasyViewSmallIconItem.ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin UnionRect(Result, RectArray.IconRect, RectArray.TextRect); Result.Top := RectArray.BoundsRect.Top; Result.Bottom := RectArray.BoundsRect.Bottom; end; procedure TEasyViewSmallIconItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); var TextSize: TSize; SelectW, BoundsH, CheckH: Integer; CheckType: TEasyCheckType; R: TRect; CheckIndent, CaptionIndent, Checksize, ImageIndex, ImageIndent, PositionIndex, AbsIndex, StateImageIndex: Integer; ImageW, ImageH: Integer; ACaption: WideString; begin if Assigned(Item) then begin // This is faster if not Item.Initialized then Item.Initialized := True; if Assigned(Column) then begin AbsIndex := Column.Index; PositionIndex := Column.Position end else begin AbsIndex := 0; PositionIndex := 0 end; if PositionIndex > -1 then begin FillChar(RectArray, SizeOf(RectArray), #0); // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** // Report view is based on this class so take care if that possibility too. if not Assigned(Column) and (OwnerListview.Header.Positions.Count > 0) then RectArray.BoundsRect := CalculateDisplayRect(Item, OwnerListview.Header.Positions[0]) else RectArray.BoundsRect := CalculateDisplayRect(Item, Column); CheckType := Item.CheckType; Checksize := Item.Checksize; ImageIndex := Item.ImageIndexes[AbsIndex]; StateImageIndex := Item.StateImageIndexes[AbsIndex]; CaptionIndent := Item.CaptionIndent; CheckIndent := Item.CheckIndent; ImageIndent := Item.ImageIndent; // Calculate the space necded for the CheckBox, if enabled if (CheckType <> ectNone) and (AbsIndex = 0) then begin R := Checks.Bound[Checksize]; BoundsH := RectHeight(RectArray.BoundsRect); CheckH := RectHeight(R); RectArray.CheckRect := Rect(RectArray.BoundsRect.Left + CheckIndent, RectArray.BoundsRect.Top + (BoundsH - CheckH) div 2, RectArray.BoundsRect.Left + CheckIndent + R.Right, RectArray.BoundsRect.Top + CheckH + (BoundsH - CheckH) div 2) end else RectArray.CheckRect := Rect(RectArray.BoundsRect.Left, RectArray.BoundsRect.Top, RectArray.BoundsRect.Left, RectArray.BoundsRect.Bottom); // Check Rect has a width of 0 // Set the rectangle of the Image if avaialable, note Bitmap is not supported if PaintStateImage and ((StateImageIndex > -1) or (GetImageList(Column, Item, eikState) <> nil)) then begin GetImageSize(Item, Column, ImageW, ImageH, eikState); RectArray.StateRect.Top := RectArray.BoundsRect.Top + (RectHeight(RectArray.BoundsRect) - ImageH) div 2; RectArray.StateRect.Left := RectArray.CheckRect.Right + ImageIndent; // State Images must be the same size as the main image RectArray.StateRect.Bottom := RectArray.StateRect.Top + ImageH; RectArray.StateRect.Right := RectArray.StateRect.Left + ImageW; end else RectArray.StateRect := Rect(RectArray.CheckRect.Right, RectArray.CheckRect.Top, RectArray.CheckRect.Right, RectArray.CheckRect.Bottom); // Set the rectangle of the Image if avaialable, note Bitmap is not supported if (ImageIndex > -1) then begin GetImageSize(Item, Column, ImageW, ImageH, eikNormal); RectArray.IconRect.Top := RectArray.BoundsRect.Top + (RectHeight(RectArray.BoundsRect) - ImageH) div 2; RectArray.IconRect.Left := RectArray.StateRect.Right + ImageIndent; RectArray.IconRect.Bottom := RectArray.IconRect.Top + ImageH; RectArray.IconRect.Right := RectArray.IconRect.Left + ImageW; end else RectArray.IconRect := Rect(RectArray.StateRect.Right, RectArray.StateRect.Top, RectArray.StateRect.Right, RectArray.StateRect.Bottom); // Calculate where the Label is positioned // ********** // The Cell may be narrow enough that only the image will fit. If that is // the case leave the LabelR a Zero sized rect if RectArray.BoundsRect.Right - 1 > RectArray.IconRect.Right + CaptionIndent {+ (2*LABEL_MARGIN) }then RectArray.LabelRect := Rect(RectArray.IconRect.Right + CaptionIndent {+ LABEL_MARGIN}, RectArray.BoundsRect.Top, RectArray.BoundsRect.Right {- 2*LABEL_MARGIN}, RectArray.BoundsRect.Bottom); // Calculate Text based rectangles // ********** if Assigned(OwnerListview.ScratchCanvas) then begin LoadTextFont(Item, PositionIndex, OwnerListview.ScratchCanvas, Item.Selected); ACaption := Item.Captions[AbsIndex]; if ACaption = '' then ACaption := ' '; TextSize := TextExtentW(ACaption, OwnerListview.ScratchCanvas); end else begin TextSize.cx := 0; TextSize.cy := 0 end; // Calculate Text Rectangle // ********** RectArray.TextRect := RectArray.LabelRect; InflateRect(RectArray.TextRect, -2, -2); // Center it horz and vert to start with // This will also clip the text rect to to size of the Label if necessary RectArray.TextRect := CenterRectInRect(RectArray.TextRect, Rect(0, 0, TextSize.cx, TextSize.cy)); case PaintTextAlignment(Item, Column) of taLeftJustify: OffsetRect(RectArray.TextRect, -(RectArray.TextRect.Left - RectArray.LabelRect.Left), 0); taRightJustify: OffsetRect(RectArray.TextRect, (RectArray.LabelRect.Right - RectArray.TextRect.Right - 8), 0); end; // Calculate Focus Text Rectangle // ********** RectArray.FullTextRect := RectArray.TextRect; // Calculate Selection Rectangle // ********** RectArray.SelectionRect := RectArray.TextRect; InflateRect(RectArray.SelectionRect, 2, 2); RectArray.FullFocusSelRect := RectArray.SelectionRect; // Calculate Rectangle used for Clickselecting // ********** UnionRect(RectArray.ClickselectBoundsRect, RectArray.IconRect, RectArray.SelectionRect); // Calculate Rectangle used for DragSelecting // ********** // During a drag selection the hit area is only a fraction of the Click bounds RectArray.DragSelectBoundsRect := RectArray.ClickselectBoundsRect; SelectW := Round(RectWidth(RectArray.DragSelectBoundsRect) * SELECTION_OFFSET); InflateRect(RectArray.DragSelectBoundsRect, -SelectW, 0); UnionRect(RectArray.FocusChangeInvalidRect, RectArray.IconRect, RectArray.FullTextRect); RectArray.EditRect := RectArray.FullTextRect; end end end; procedure TEasyViewSmallIconItem.PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); begin // Don't do default end; function TEasyViewSmallIconItem.PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; begin if Assigned(Column) then Result := Column.Alignment else Result := taLeftJustify end; function TEasyViewSmallIconItem.PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; begin Result := 1 end; function TEasyViewSmallIconItem.PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; begin if Assigned(Column) then Result := Column.VAlignment else Result := cvaCenter end; { TEasyDefaultCellSizes } constructor TEasyCellSizes.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FIcon := TEasyCellSizeIcon.Create(AnOwner); FSmallIcon := TEasyCellSizeSmallIcon.Create(AnOwner); FThumbnail := TEasyCellSizeThumbnail.Create(AnOwner); FTile := TEasyCellSizeTile.Create(AnOwner); FList := TEasyCellSizeList.Create(AnOwner); FReport := TEasyCellSizeReport.Create(AnOwner); FFilmStrip := TEasyCellSizeFilmStrip.Create(AnOwner); FGrid := TEasyCellGrid.Create(AnOwner); end; destructor TEasyCellSizes.Destroy; begin FreeAndNil(FIcon); FreeAndNil(FSmallIcon); FreeAndNil(FThumbnail); FreeAndNil(FTile); FreeAndNil(FList); FreeAndNil(FReport); FreeAndNil(FFilmStrip); FreeAndNil(FGrid); inherited Destroy; end; { TEasyDefaultSmallIconCellSize } constructor TEasyCellSizeSmallIcon.Create( AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 200; FHeight := 17; FAutoSizeHeight := 17; FAutoSizeWidth := 200; end; { TEasyDefaultThumbnailCellSize } constructor TEasyCellSizeThumbnail.Create( AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 125; FHeight := 143; FAutoSizeHeight := 143; FAutoSizeWidth := 125; end; { TEasyDefaultTileCellSize } constructor TEasyCellSizeTile.Create( AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 218; FHeight := 58; FAutoSizeHeight := 58; FAutoSizeWidth := 218; end; { TEasyDefaultListCellSize } constructor TEasyCellSizeList.Create( AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 200; FHeight := 17; FAutoSizeHeight := 17; FAutoSizeWidth := 200; end; { TEasyDefaultReportCellSize } constructor TEasyCellSizeReport.Create( AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FWidth := 75; FHeight := 17; FAutoSizeHeight := 17; FAutoSizeWidth := 75; end; function TEasyViewTileItem.ExpandIconR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := Rect(0, 0, 0, 0) end; function TEasyViewTileItem.ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin UnionRect(Result, RectArray.IconRect, RectArray.TextRect); Result.Top := RectArray.BoundsRect.Top + 2; Result.Bottom := RectArray.BoundsRect.Bottom - 2; end; function TEasyViewTileItem.GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; begin Result := inherited GetImageList(Column, Item, Image); if not Assigned(Result) then Result := Item.ImageList[ValidateColumnIndex(Column), eisLarge] end; function TEasyViewTileItem.PaintImageSize: TEasyImageSize; begin Result := eisExtraLarge end; function TEasyViewTileItem.PaintTextAlignment(Item: TEasyItem; Column: TEasyColumn): TAlignment; begin Result := taLeftJustify end; procedure TEasyViewTileItem.AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); begin InflateRect(LocalSelRect, -2, -2) end; procedure TEasyViewTileItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); var ACaption: WideString; PositionIndex, i, YOffset, ImageW, ImageH, DetailCount: Integer; DrawTextFlags: TCommonDrawTextWFlags; R: TRect; Done: Boolean; begin if Assigned(Item) then begin if not Item.Initialized then Item.Initialized := True; PositionIndex := ValidateColumnIndex(Column); if PositionIndex > -1 then begin FillChar(RectArray, SizeOf(RectArray), #0); GetImageSize(Item, Column, ImageW, ImageH, eikNormal); // Get the cell size for the main caption, aligned with the top case PaintTextAlignment(Item, Column) of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; DrawTextFlags := [dtCalcRect, dtCalcRectAlign, dtEndEllipsis, dtTop]; // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** RectArray.BoundsRect := Item.DisplayRect; InflateRect(RectArray.BoundsRect, -Item.Border, -Item.Border); // Calculate where the Checkbox is positioned // ********** if Item.CheckType <> ectNone then begin R := Checks.Bound[Item.Checksize]; RectArray.CheckRect.Left := RectArray.BoundsRect.Left + Item.CheckIndent; RectArray.CheckRect.Top := RectArray.BoundsRect.Top + (RectHeight(RectArray.BoundsRect) - R.Bottom) div 2; RectArray.CheckRect.Right := RectArray.CheckRect.Left + R.Right; RectArray.CheckRect.Bottom := RectArray.CheckRect.Top + R.Bottom; end else SetRect(RectArray.CheckRect, RectArray.BoundsRect.Left, RectArray.BoundsRect.Top, RectArray.BoundsRect.Left, RectArray.BoundsRect.Bottom); // Calculate where the Icon is positioned // ********** RectArray.IconRect := Rect(RectArray.CheckRect.Right + Item.ImageIndent, RectArray.BoundsRect.Top, RectArray.CheckRect.Right + Item.ImageIndent + ImageW + 4, RectArray.BoundsRect.Bottom); // Calculate where the Label Rect is positioned // ********** RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.IconRect.Right + Item.CaptionIndent; InflateRect(RectArray.LabelRect, -2, 0); // Calculate the Text Rectangles // ********** RectArray.TextRect := RectArray.LabelRect; // Leave border for the Selection Painted rectangle around text InflateRect(RectArray.TextRect, -2, -2); DetailCount := Item.DetailCount; // Assume that there is enough room for all the Captions to be show that the user desired SetLength(RectArray.TextRects, DetailCount); for i := 0 to Length(RectArray.TextRects) - 1 do RectArray.TextRects[i] := Rect(0, 0, 0, 0); if Length(RectArray.TextRects) > 0 then begin // Lets work on the Main Caption, it gets the full LabelR to use RectArray.TextRects[0] := RectArray.LabelRect; // TextRects[0] is the main caption that can fill more then one line if necessary // if it does then details are omitted as necded if Item.Details[0] > -1 then ACaption := Item.Captions[Item.Details[0]] else ACaption := ''; // Make the first line contain something if ACaption = '' then ACaption := ' '; if Assigned(OwnerListview.ScratchCanvas) then begin LoadTextFont(Item, PositionIndex, OwnerListview.ScratchCanvas, Item.Selected); DrawTextWEx(OwnerListview.ScratchCanvas.Handle, ACaption, RectArray.TextRects[0], DrawTextFlags, PaintTextLineCount(Item, Column)); end; if RectArray.TextRects[0].Bottom > RectArray.LabelRect.Bottom then RectArray.TextRects[0] := Rect(0, 0, 0, 0) else begin // Only fill in as many detail lines that fit based on if the caption // necded two lines or not Done := False; i := 1; while not Done and (i < Length(RectArray.TextRects)) do begin if RectArray.TextRects[i - 1].Bottom < RectArray.LabelRect.Bottom then begin if Item.Details[i] > -1 then ACaption := Item.Captions[Item.Details[i]] else ACaption := ''; RectArray.TextRects[i] := RectArray.LabelRect; RectArray.TextRects[i].Top := RectArray.TextRects[i - 1].Bottom; if Assigned(OwnerListview.ScratchCanvas) then begin LoadTextFont(Item, i, OwnerListview.ScratchCanvas, Item.Selected); // Details only get one line DrawTextWEx(OwnerListview.ScratchCanvas.Handle, ACaption, RectArray.TextRects[i], DrawTextFlags, 1); end; if RectArray.TextRects[i].Bottom > RectArray.LabelRect.Bottom then begin RectArray.TextRects[i] := Rect(0, 0, 0, 0); Done := True end else Inc(i) end else begin RectArray.TextRects[i] := Rect(0, 0, 0, 0); Done := True; end end; end; RectArray.TextRect := Rect(0, 0, 0, 0); Done := False; i := 0; while not Done and (i < Length(RectArray.TextRects)) do begin if not IsRectEmpty(RectArray.TextRects[i]) then begin UnionRect(RectArray.TextRect, RectArray.TextRect, RectArray.TextRects[i]); Inc(i) end else Done := True end; if Done then SetLength(RectArray.TextRects, i); YOffset := 0; if Item.VAlignment = cvaCenter then YOffset := (RectHeight(RectArray.LabelRect)-RectHeight(RectArray.TextRect)) div 2 else if Item.VAlignment = cvaBottom then YOffset := RectArray.LabelRect.Bottom - RectHeight(RectArray.TextRect); for i := 0 to Length(RectArray.TextRects) - 1 do begin if Item.VAlignment = cvaCenter then OffsetRect(RectArray.TextRects[i], 0, YOffset) else if Item.VAlignment = cvaBottom then OffsetRect(RectArray.TextRects[i], 0, YOffset); end; if Item.VAlignment = cvaCenter then OffsetRect(RectArray.TextRect, 0, YOffset) else if Item.VAlignment = cvaBottom then OffsetRect(RectArray.TextRect, 0, YOffset); end; RectArray.FullTextRect := RectArray.TextRect; RectArray.SelectionRect := RectArray.TextRect; InflateRect(RectArray.SelectionRect, 2, 2); RectArray.FullFocusSelRect := RectArray.SelectionRect; RectArray.ClickselectBoundsRect := RectArray.IconRect; RectArray.ClickselectBoundsRect.Right := RectArray.TextRect.Right; RectArray.DragSelectBoundsRect := RectArray.TextRect; RectArray.DragSelectBoundsRect.Right := RectArray.DragSelectBoundsRect.Right - Round(RectWidth(RectArray.DragSelectBoundsRect)*0.20); UnionRect(RectArray.FocusChangeInvalidRect, RectArray.IconRect, RectArray.FullTextRect); RectArray.EditRect := RectArray.FullTextRect; end end end; procedure TEasyViewTileItem.PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); begin end; procedure TEasyViewTileItem.PaintText(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; LinesToDraw: Integer); // // Need to handle this paint directly // var DrawTextFlags: TCommonDrawTextWFlags; i: Integer; begin DrawTextFlags := [dtEndEllipsis, dtTop]; case PaintTextAlignment(Item, Column) of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; if Length(RectArray.TextRects) > 0 then begin if Item.Details[0] > -1 then begin LoadTextFont(Item, 0, ACanvas, Item.Selected); DrawTextWEx(ACanvas.Handle, Item.Captions[Item.Details[0]], RectArray.TextRects[0], DrawTextFlags, PaintTextLineCount(Item, Column)); end; for i := 1 to Length(RectArray.TextRects) - 1 do begin if Item.Details[i] > -1 then begin LoadTextFont(Item, i, ACanvas, Item.Selected); DrawTextWEx(ACanvas.Handle, Item.Captions[Item.Details[i]], RectArray.TextRects[i], DrawTextFlags, 1); end end end end; function TEasyViewThumbnailItem.ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := inherited ExpandTextR(Item, RectArray, SelectType); Result.Top := RectArray.IconRect.Bottom end; function TEasyViewThumbnailItem.GetImageList(Column: TEasyColumn; Item: TEasyItem; Image: TEasyImageKind): TCustomImageList; begin Result := inherited GetImageList(Column, Item, Image); if not Assigned(Result) then Result := Item.ImageList[ValidateColumnIndex(Column), eisLarge] end; { TEasyThumbnailItemView} function TEasyViewThumbnailItem.OverlappedFocus: Boolean; begin Result := True end; function TEasyViewThumbnailItem.PaintImageSize: TEasyImageSize; begin Result := eisExtraLarge end; function TEasyViewThumbnailItem.SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; var R: TRect; RectArray: TEasyRectArrayObject; SelectMargin: Integer; begin Result := False; if Item.Enabled then begin ItemRectArray(Item, nil, OwnerListview.ScratchCanvas,'', RectArray); if SelectType = eshtClickselect then Result := IntersectRect(R, SelectViewportRect, ExpandTextR(Item, RectArray, SelectType)) or IntersectRect(R, SelectViewportRect, ExpandIconR(Item, RectArray, SelectType)) else begin R := ExpandIconR(Item, RectArray, SelectType); SelectMargin := Round( RectWidth(R) * 0.10); InflateRect(R, -SelectMargin, -SelectMargin); Result := IntersectRect(R, SelectViewportRect, R) end end end; function TEasyViewThumbnailItem.SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; var RectArray: TEasyRectArrayObject; R: TRect; SelectMargin: Integer; begin Result := False; if Item.Enabled then begin ItemRectArray(Item, nil, OwnerListview.ScratchCanvas, '', RectArray); if SelectType = eshtClickselect then Result := Windows.PtInRect(ExpandTextR(Item, RectArray, SelectType), ViewportPoint) or Windows.PtInRect(ExpandIconR(Item, RectArray, SelectType), ViewportPoint) else begin R := ExpandIconR(Item, RectArray, SelectType); SelectMargin := Round( RectWidth(R) * 0.10); InflateRect(R, -SelectMargin, -SelectMargin); Result := Windows.PtInRect(R, ViewportPoint) end end end; procedure TEasyViewThumbnailItem.AfterSelRectCalc(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; var LocalSelRect: TRect); begin InflateRect(LocalSelRect, -2, -2) end; procedure TEasyViewThumbnailItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString; var RectArray: TEasyRectArrayObject); var DrawTextFlags: TCommonDrawTextWFlags; Canvas: TControlCanvas; R: TRect; PositionIndex, AbsIndex: Integer; Metrics: TTextMetric; ACaption: WideString; begin if Assigned(Item) then begin if not Item.Initialized then Item.Initialized := True; if Assigned(Column) then begin AbsIndex := Column.Index; PositionIndex := Column.Position end else begin AbsIndex := 0; PositionIndex := 0 end; if PositionIndex > -1 then begin FillChar(RectArray, SizeOf(RectArray), #0); Canvas := TControlCanvas.Create; try Canvas.Control := OwnerListview; Canvas.Lock; // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** RectArray.BoundsRect := Item.DisplayRect; InflateRect(RectArray.BoundsRect, -Item.Border, -Item.Border); // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** RectArray.IconRect := RectArray.BoundsRect; if not OwnerListview.PaintInfoItem.HideCaption then begin GetTextMetrics(Canvas.Handle, Metrics); RectArray.IconRect.Bottom := RectArray.IconRect.Bottom - Metrics.tmHeight * 2 end else if Item.CheckType <> ectNone then RectArray.IconRect.Bottom := RectArray.IconRect.Bottom - (RectHeight(Checks.Bound[Item.Checksize]) + 2); // Calculate area that the Checkbox may be drawn // ********** if Item.CheckType <> ectNone then begin R := Checks.Bound[Item.Checksize]; RectArray.CheckRect.Top := RectArray.IconRect.Bottom + 1; // Looks best here not centered RectArray.CheckRect.Left := RectArray.BoundsRect.Left + Item.CheckIndent; RectArray.CheckRect.Bottom := RectArray.CheckRect.Top + R.Bottom; RectArray.CheckRect.Right := RectArray.CheckRect.Left + R.Right; end else begin RectArray.CheckRect.Top := RectArray.IconRect.Bottom; RectArray.CheckRect.Left := RectArray.BoundsRect.Left; RectArray.CheckRect.Bottom := RectArray.BoundsRect.Bottom; RectArray.CheckRect.Right := RectArray.CheckRect.Left; end; // Calcuate the Bounds of the Cell that is allowed to be drawn in // ********** if not OwnerListview.PaintInfoItem.HideCaption then begin RectArray.LabelRect.Left := RectArray.CheckRect.Right + Item.CaptionIndent; RectArray.LabelRect.Top := RectArray.IconRect.Bottom + 1; RectArray.LabelRect.Right := RectArray.BoundsRect.Right; RectArray.LabelRect.Bottom := RectArray.BoundsRect.Bottom; // Calcuate the Text rectangle based on the current text // ********** RectArray.TextRect := RectArray.LabelRect; RectArray.FullTextRect := RectArray.LabelRect; // Leave room for a small border between edge of the selection rect and text InflateRect(RectArray.TextRect, -2, -2); InflateRect(RectArray.FullTextRect, -2, -2); DrawTextFlags := [dtCalcRect, dtCalcRectAlign]; case PaintTextAlignment(Item, Column) of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case PaintTextVAlignment(Item, Column) of cvaTop: Include(DrawTextFlags, dtTop); cvaBottom: Include(DrawTextFlags, dtBottom); cvaCenter: Include(DrawTextFlags, dtCenter); end; LoadTextFont(Item, PositionIndex, Canvas, Item.Selected); ACaption := Item.Captions[AbsIndex]; DrawTextWEx(Canvas.Handle, ACaption, RectArray.FullTextRect, DrawTextFlags, -1); DrawTextWEx(Canvas.Handle, ACaption, RectArray.TextRect, DrawTextFlags, 2); // Calculate Selection rectangle paint box // ********** RectArray.SelectionRect := RectArray.TextRect; InflateRect(RectArray.SelectionRect, 2, 2); RectArray.FullFocusSelRect := RectArray.FullTextRect; InflateRect(RectArray.FullFocusSelRect, 2, 2); UnionRect(RectArray.FocusChangeInvalidRect, RectArray.IconRect, RectArray.FullFocusSelRect); if Item.Focused then UnionRect(RectArray.ClickselectBoundsRect, RectArray.IconRect, RectArray.FullFocusSelRect) else UnionRect(RectArray.ClickselectBoundsRect, RectArray.IconRect, RectArray.SelectionRect); RectArray.ClickselectBoundsRect := RectArray.ClickselectBoundsRect; RectArray.DragSelectBoundsRect := RectArray.TextRect; RectArray.EditRect := RectArray.FullTextRect; end else begin RectArray.SelectionRect := RectArray.IconRect; RectArray.FullFocusSelRect := RectArray.IconRect; RectArray.FocusChangeInvalidRect := RectArray.IconRect; RectArray.ClickselectBoundsRect := RectArray.IconRect; RectArray.DragSelectBoundsRect := RectArray.IconRect; RectArray.EditRect := Rect(0, 0, 0, 0); RectArray.LabelRect := Rect(0, 0, 0, 0); RectArray.TextRect := Rect(0, 0, 0, 0); RectArray.FullTextRect := Rect(0, 0, 0, 0); end; finally Canvas.UnLock; Canvas.Free; end; end end end; function TEasyViewThumbnailItem.PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer; begin if Item.Focused and OwnerListview.Focused then Result := -1 else Result := 2 end; function TEasyViewThumbnailItem.PaintTextVAlignment(Item: TEasyItem; Column: TEasyColumn): TCommonVAlignment; begin Result := cvaCenter end; procedure TEasyViewThumbnailItem.PaintAfter(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject); begin if OwnerListview.PaintInfoItem.ShowBorder then begin // Paint the Frame around the Thumbnail if (Item.Selected or Item.Hilighted) and not OwnerListview.Selection.Gradient then begin if OwnerListview.Focused or Item.OwnerListview.Selection.PopupMode or Item.Hilighted then ACanvas.Brush.Color := OwnerListview.Selection.Color else ACanvas.Brush.Color := OwnerListview.Selection.InactiveColor; ACanvas.FrameRect(RectArray.IconRect); InflateRect(RectArray.IconRect, -1, -1); ACanvas.FrameRect(RectArray.IconRect); InflateRect(RectArray.IconRect, -1, -1); ACanvas.FrameRect(RectArray.IconRect); end else begin ACanvas.Brush.Color := Item.BorderColor; ACanvas.FrameRect(RectArray.IconRect); end end end; procedure TEasyViewThumbnailItem.PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled: Boolean); begin // Skip inherited end; { TColumnView } function TEasyViewColumn.EditAreaHitPt(Column: TEasyColumn; ViewportPoint: TPoint): Boolean; begin Result := False end; function TEasyViewColumn.GetImageList(Column: TEasyColumn): TCustomImageList; begin Result := Column.OwnerHeader.Images end; function TEasyViewColumn.ItemRect(Column: TEasyColumn; RectType: TEasyCellRectType): TRect; var RectArray: TEasyRectArrayObject; begin Result := Rect(0, 0, 0, 0); if IsRectEmpty(Result) then begin ItemRectArray(Column, RectArray); case RectType of ertBounds: Result := RectArray.BoundsRect; ertIcon: Result := RectArray.IconRect; ertLabel: Result := RectArray.LabelRect; ertClickselectBounds: Result := RectArray.ClickselectBoundsRect; ertDragSelectBounds: Result := RectArray.DragSelectBoundsRect; ertText: Result := RectArray.TextRect; ertFullText: Result := RectArray.FullTextRect; end; end; end; function TEasyViewColumn.PaintImageSize(Column: TEasyColumn; HeaderType: TEasyHeaderType): TEasyImageSize; begin Result := eisSmall end; function TEasyViewColumn.SelectionHit(Column: TEasyColumn; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; begin Result := False end; function TEasyViewColumn.SelectionHitPt(Column: TEasyColumn; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; begin Result := False end; procedure TEasyViewColumn.CalculateTextRect(Column: TEasyColumn; Canvas: TControlCanvas; var TextR: TRect); // Fits the Text in the PaintInfo.Caption.Text field into the TextR based // on the values in the PaintInfo record. If Canvas is nil then a temporary // canvas is created to fit the text based on the Font in the PaintInfo var DrawTextFlags: TCommonDrawTextWFlags; LocalCanvas: TControlCanvas; begin case Column.Alignment of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; case Column.VAlignment of cvaTop: Include(DrawTextFlags, dtTop); cvaBottom: Include(DrawTextFlags, dtBottom); cvaCenter: Include(DrawTextFlags, dtVCenter); end; if not Assigned(Canvas) then begin LocalCanvas := TControlCanvas.Create; LocalCanvas.Control := OwnerListview end else LocalCanvas := Canvas; try LoadTextFont(Column, LocalCanvas); DrawTextFlags := DrawTextFlags + [dtCalcRectAdjR, dtCalcRect, dtCalcRectAlign]; DrawTextWEx(LocalCanvas.Handle, Column.Caption, TextR, DrawTextFlags, 1); finally if not Assigned(Canvas) then LocalCanvas.Free end; end; procedure TEasyViewColumn.GetImageSize(Column: TEasyColumn; var ImageW, ImageH: Integer); var Images: TCustomImageList; IsCustom: Boolean; begin ImageW := 0; ImageH := 0; Column.ImageDrawIsCustom(Column, IsCustom); if IsCustom then Column.ImageDrawGetSize(Column, ImageW, ImageH) else begin Images := GetImageList(Column); if (Column.ImageIndexes[0] > -1) and Assigned(Images) then begin ImageW := Images.Width; ImageH := Images.Height end end end; procedure TEasyViewColumn.ItemRectArray(Column: TEasyColumn; var RectArray: TEasyRectArrayObject); var DrawTextFlags: TCommonDrawTextWFlags; i, CaptionLines: integer; R: TRect; ImageW, ImageH: Integer; Pt: TPoint; begin Pt.x := 0; Pt.y := 0; if Assigned(Column) then begin if not Column.Initialized then Column.Initialized := True; FillChar(RectArray, SizeOf(RectArray), #0); GetImageSize(Column, ImageW, ImageH); RectArray.BoundsRect := Column.DisplayRect; InflateRect(RectArray.BoundsRect, -2, -2); // Make the CheckRect 0 width to initialize it RectArray.CheckRect := RectArray.BoundsRect; RectArray.CheckRect.Right := RectArray.CheckRect.Left; // Make the DropDownArrow 0 width to initialize it to the right side RectArray.DropDownArrow := RectArray.BoundsRect; RectArray.DropDownArrow.Left := RectArray.DropDownArrow.Right; // First calculate where the CheckRect goes if Column.CheckType <> ectNone then begin R := Checks.Bound[Column.Checksize]; RectArray.CheckRect.Left := RectArray.CheckRect.Left + Column.CheckIndent; RectArray.CheckRect.Top := RectArray.CheckRect.Top + (RectHeight(RectArray.BoundsRect) - RectHeight(R)) div 2; RectArray.CheckRect.Right := RectArray.CheckRect.Left + RectWidth(R); RectArray.CheckRect.Bottom := RectArray.CheckRect.Top + RectHeight(R); end; // Initialize IconRect to 0 width RectArray.IconRect := RectArray.BoundsRect; RectArray.IconRect.Left := RectArray.CheckRect.Right; RectArray.IconRect.Right := RectArray.CheckRect.Right; // Next comes the State Image if enabled if Column.ImageIndex > -1 then begin case Column.ImagePosition of ehpLeft: begin RectArray.IconRect.Left := RectArray.CheckRect.Right + Column.ImageIndent; RectArray.IconRect.Right := RectArray.IconRect.Left + ImageW; RectArray.IconRect.Top := RectArray.BoundsRect.Top + (RectHeight(RectArray.BoundsRect) - ImageH) div 2; RectArray.IconRect.Bottom := RectArray.IconRect.Top + ImageH; RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.IconRect.Right + Column.CaptionIndent; end; ehpTop: begin RectArray.IconRect.Top := RectArray.BoundsRect.Top + Column.ImageIndent; RectArray.IconRect.Bottom := RectArray.IconRect.Top + ImageH; RectArray.IconRect.Left := RectArray.BoundsRect.Left; RectArray.IconRect.Right := RectArray.BoundsRect.Right; RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.CheckRect.Right; RectArray.LabelRect.Top := RectArray.IconRect.Bottom + Column.CaptionIndent; end; ehpRight: begin RectArray.IconRect.Right := RectArray.BoundsRect.Right - Column.ImageIndent; RectArray.IconRect.Left := RectArray.IconRect.Right - ImageW; RectArray.IconRect.Top := RectArray.BoundsRect.Top + (RectHeight(RectArray.BoundsRect) - ImageH) div 2; RectArray.IconRect.Bottom := RectArray.IconRect.Top + ImageH; RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.CheckRect.Right; RectArray.LabelRect.Right := RectArray.IconRect.Left - Column.CaptionIndent; end; ehpBottom: begin RectArray.IconRect.Bottom := RectArray.BoundsRect.Bottom - Column.ImageIndent; RectArray.IconRect.Top := RectArray.IconRect.Bottom - ImageH; RectArray.IconRect.Left := RectArray.BoundsRect.Left; RectArray.IconRect.Right := RectArray.BoundsRect.Right; RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.CheckRect.Right; RectArray.LabelRect.Bottom := RectArray.IconRect.Top - Column.CaptionIndent; end; end end else begin RectArray.LabelRect := RectArray.BoundsRect; RectArray.LabelRect.Left := RectArray.IconRect.Right; end; if Column.SortDirection <> esdNone then begin case Column.SortGlyphAlign of esgaLeft: begin RectArray.SortRect := RectArray.BoundsRect; RectArray.SortRect.Left := RectArray.LabelRect.Left; RectArray.LabelRect.Left := RectArray.LabelRect.Left + Column.SortGlyphIndent + OwnerListview.GlobalImages.ColumnSortUp.Width; RectArray.SortRect.Right := RectArray.SortRect.Left + OwnerListview.GlobalImages.ColumnSortUp.Width; RectArray.SortRect.Top := RectArray.SortRect.Top + (RectHeight(RectArray.SortRect) - OwnerListview.GlobalImages.ColumnSortUp.Height) div 2; RectArray.SortRect.Bottom := RectArray.SortRect.Top + OwnerListview.GlobalImages.ColumnSortUp.Height end; esgaRight: begin RectArray.SortRect := RectArray.BoundsRect; RectArray.SortRect.Right := RectArray.LabelRect.Right; RectArray.LabelRect.Right := RectArray.LabelRect.Right - Column.SortGlyphIndent - OwnerListview.GlobalImages.ColumnSortUp.Width; RectArray.SortRect.Left := RectArray.SortRect.Right - OwnerListview.GlobalImages.ColumnSortUp.Width; RectArray.SortRect.Top := RectArray.SortRect.Top + (RectHeight(RectArray.SortRect) - OwnerListview.GlobalImages.ColumnSortUp.Height) div 2; RectArray.SortRect.Bottom := RectArray.SortRect.Top + OwnerListview.GlobalImages.ColumnSortUp.Height end else // no Sort Glyph RectArray.SortRect := RectArray.LabelRect; RectArray.SortRect.Right := RectArray.SortRect.Left; end end; if Column.DropDownButton.Visible then begin if RectWidth(RectArray.LabelRect) > RectHeight(RectArray.BoundsRect) + 10 then begin if Column.DropDownButton.AlwaysShow or Column.HotTracking[Pt] then begin RectArray.LabelRect.Right := RectArray.LabelRect.Right - RectHeight(RectArray.BoundsRect); RectArray.DropDownArrow.Left := RectArray.DropDownArrow.Right - RectHeight(RectArray.BoundsRect) end end end; // See if there is enough room for the label if IsRectProper(RectArray.LabelRect) then begin RectArray.TextRect := RectArray.LabelRect; case Column.Alignment of taLeftJustify: begin RectArray.TextRect.Left := RectArray.TextRect.Left + Column.CaptionIndent; RectArray.TextRect.Right := RectArray.TextRect.Right - 4; end; taRightJustify: begin RectArray.TextRect.Right := RectArray.TextRect.Right - Column.CaptionIndent; RectArray.TextRect.Left := RectArray.TextRect.Left + 4; end; end; // Leave room for a small border between edge of the selection rect and text InflateRect(RectArray.TextRect, -2, -2); DrawTextFlags := [dtCalcRect, dtCalcRectAlign]; case Column.Alignment of taCenter: DrawTextFlags := DrawTextFlags + [dtCenter]; taLeftJustify: DrawTextFlags := DrawTextFlags + [dtLeft]; taRightJustify: DrawTextFlags := DrawTextFlags + [dtRight]; end; // Vertical Alignment has no meaning in mulitiple line output need to calculate // the entire text block then vert align it DrawTextFlags := DrawTextFlags + [dtTop]; CaptionLines := OwnerListview.PaintInfoColumn.CaptionLines; // Make enough room for the Details and the Caption Rect SetLength(RectArray.TextRects, CaptionLines + 1); // Get the Caption Rect RectArray.TextRects[0] := RectArray.TextRect; LoadTextFont(Column, OwnerListview.ScratchCanvas); DrawTextWEx(OwnerListview.ScratchCanvas.Handle, Column.Caption, RectArray.TextRects[0], DrawTextFlags, CaptionLines); RectArray.TextRect := Rect(0, 0, 0, 0); for i := 0 to Length(RectArray.TextRects) - 1 do UnionRect(RectArray.TextRect, RectArray.TextRect, RectArray.TextRects[i]); case Column.VAlignment of cvaCenter: OffsetRect(RectArray.TextRect, 0, (RectHeight(RectArray.LabelRect) - RectHeight(RectArray.TextRect)) div 2); cvaBottom: OffsetRect(RectArray.TextRect, 0, (RectHeight(RectArray.LabelRect) - RectHeight(RectArray.TextRect))); end; for i := 0 to Length(RectArray.TextRects) - 1 do begin case Column.VAlignment of cvaCenter: OffsetRect(RectArray.TextRects[i], 0, ((RectHeight(RectArray.LabelRect) - 4) - RectHeight(RectArray.TextRect)) div 2); cvaBottom: OffsetRect(RectArray.TextRects[i], 0, ((RectHeight(RectArray.LabelRect) - 4) - RectHeight(RectArray.TextRect))); end; end; end else RectArray.TextRect := Rect(0, 0, 0, 0); // Put the Sort Arrow right next to the Text OffsetRect(RectArray.SortRect, RectArray.TextRect.Right - RectArray.SortRect.Left, 0); RectArray.ClickselectBoundsRect := RectArray.BoundsRect; RectArray.DragSelectBoundsRect := RectArray.BoundsRect; RectArray.SelectionRect := RectArray.BoundsRect; RectArray.FullTextRect := RectArray.BoundsRect; RectArray.FullTextRect := RectArray.BoundsRect; RectArray.FocusChangeInvalidRect := RectArray.BoundsRect; RectArray.EditRect := RectArray.BoundsRect; InflateRect(RectArray.BoundsRect, 2, 2); end end; procedure TEasyViewColumn.LoadTextFont(Column: TEasyColumn; ACanvas: TCanvas); begin ACanvas.Font.Assign(OwnerListview.Header.Font); if Column.Bold then ACanvas.Font.Style := ACanvas.Font.Style +[fsBold]; end; procedure TEasyViewColumn.Paint(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType); procedure AlphaBlendColumn(AColor: TColor; R: TRect); var Bitmap: TBitmap; begin Bitmap := TBitmap.Create; try Bitmap.PixelFormat := pf32Bit; Bitmap.Width := RectWidth(R); Bitmap.Height := RectHeight(R); if (Bitmap.Width > 0) and (Bitmap.Height > 0) then begin BitBlt(Bitmap.Canvas.Handle, 0, 0, Bitmap.Width, Bitmap.Height, ACanvas.Handle, R.Left, R.Top, srcCopy); MPCommonUtilities.AlphaBlend(0, Bitmap.Canvas.Handle, Bitmap.Canvas.ClipRect, Point(0, 0), cbmConstantAlphaAndColor, 128, ColorToRGB(AColor)); BitBlt(ACanvas.Handle, R.Left, R.Top, Bitmap.Width, Bitmap.Height, Bitmap.Canvas.Handle, 0, 0, srcCopy); end finally Bitmap.Free end end; var RectArray: TEasyRectArrayObject; begin ItemRectArray(Column, RectArray); with RectArray.BoundsRect do IntersectClipRect(ACanvas.Handle, Left, Top, Right, Bottom); // First allow decendents a crack at the painting PaintBefore(Column, ACanvas, HeaderType, RectArray); // Paint the Background button PaintBkGnd(Column, ACanvas, HeaderType, RectArray); // Paint the Selection Rectangle // ************************* // PaintSelectionRect(Column, RectArray, ACanvas); // Next Paint the Icon or Bitmap Image // ************************* PaintImage(Column, ACanvas, HeaderType, RectArray, PaintImageSize(Column, HeaderType)); // Now lets paint the Text // ************************* // If focused then show as many lines as necessary // Decendents should override PaintText to change the number of lines // as necessary PaintText(Column, ACanvas, HeaderType, RectArray, OwnerListview.PaintInfoColumn.CaptionLines); PaintSortGlyph(Column, ACanvas, HeaderType, RectArray); // Now lets paint Focus Rectangle // ************************* PaintFocusRect(Column, ACanvas, HeaderType, RectArray); // Now Paint the Checkbox if applicable PaintCheckBox(Column, ACanvas, HeaderType, RectArray); PaintDropGlyph(Column, ACanvas, HeaderType, RectArray); PaintDropDownArrow(Column, ACanvas, HeaderType, RectArray); // Now give decentant a chance to paint anything PaintAfter(Column, ACanvas, HeaderType, RectArray); end; procedure TEasyViewColumn.PaintAfter(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewColumn.PaintBefore(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewColumn.PaintBkGnd(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); procedure SpiegelnHorizontal(Bitmap:TBitmap); type TRGBArray = array[0..0] OF TRGBQuad; pRGBArray = ^TRGBArray; var i, j, w : Integer; RowIn : pRGBArray; RowOut: pRGBArray; begin w := Bitmap.Width*SizeOf(TRGBQuad); GetMem(RowIn, w); for j := 0 to Bitmap.Height-1 do begin Move(Bitmap.Scanline[j]^, RowIn^,w); RowOut := Bitmap.Scanline[j]; for i := 0 to Bitmap.Width-1 do RowOut[i] := RowIn[Bitmap.Width-1-i]; end; Bitmap.Assign(Bitmap); Freemem(RowIn); end; var NormalButtonFlags, NormalButtonStyle, PressedButtonStyle, PressedButtonFlags, RaisedButtonStyle, RaisedButtonFlags: LongWord; R: TRect; Pt: TPoint; {$IFDEF USETHEMES} PartID, StateID: LongWord; Bits: TBitmap; {$ENDIF} begin Pt.x := 0; Pt.y := 0; {$IFDEF USETHEMES} if OwnerListview.DrawWithThemes then begin PartID := HP_HEADERITEM; if Column.Clicking then StateID := HIS_PRESSED else if Column.HotTracking[Pt] then StateID := HIS_HOT else StateID := HIS_NORMAL; if HeaderType = ehtFooter then begin Bits := TBitmap.Create; try Bits.Width := RectWidth(Column.DisplayRect); Bits.Height := RectHeight(Column.DisplayRect); Bits.PixelFormat := pf32Bit; DrawThemeBackground(OwnerListview.Themes.HeaderTheme, Bits.Canvas.Handle, PartID, StateID, Rect(0, 0, Bits.Width, Bits.Height), nil); SpiegelnHorizontal(Bits); BitBlt(ACanvas.Handle, Column.DisplayRect.Left, Column.DisplayRect.Top, Bits.Width, Bits.Height, Bits.Canvas.Handle, 0, 0, SRCCOPY); finally Bits.Free end; end else begin R := Column.DisplayRect; // The divider is drawn by this as well and if shorted the divider is before the button // if Column.HotTracking[Pt] and Column.DropDownButton.Visible and (RectWidth(RectArray.DropDownArrow) > 0) then // R.Right := RectArray.DropDownArrow.Left; DrawThemeBackground(OwnerListview.Themes.HeaderTheme, ACanvas.Handle, PartID, StateID, R, nil); end; Exit; end; {$ENDIF USETHEMES} { if Column.Selected then begin if OwnerListview.Focused then ACanvas.Brush.Color := Column.Selection.Color else ACanvas.Brush.Color := Column.Selection.InactiveColor end else if Column.HotTrack and Column.Hilighted then ACanvas.Brush.Color := PaintInfo.HotTrack.Color else } ACanvas.Brush.Color := Column.Color; ACanvas.FillRect(Column.DisplayRect); RaisedButtonStyle := 0; RaisedButtonFlags := 0; case Column.Style of ehbsThick: begin NormalButtonStyle := BDR_RAISEDINNER or BDR_RAISEDOUTER; NormalButtonFlags := BF_LEFT or BF_TOP or BF_BOTTOM or BF_RIGHT or BF_SOFT or BF_ADJUST; PressedButtonStyle := BDR_RAISEDINNER or BDR_RAISEDOUTER; PressedButtonFlags := NormalButtonFlags or BF_RIGHT or BF_FLAT or BF_ADJUST; end; ehbsFlat: begin NormalButtonStyle := BDR_RAISEDINNER; NormalButtonFlags := BF_LEFT or BF_TOP or BF_BOTTOM or BF_RIGHT or BF_ADJUST; PressedButtonStyle := BDR_SUNKENOUTER; PressedButtonFlags := BF_RECT or BF_ADJUST; end; else begin NormalButtonStyle := BDR_RAISEDINNER; NormalButtonFlags := BF_RECT or BF_SOFT or BF_ADJUST; PressedButtonStyle := BDR_SUNKENOUTER; PressedButtonFlags := BF_RECT or BF_ADJUST; RaisedButtonStyle := BDR_RAISEDINNER; RaisedButtonFlags := BF_LEFT or BF_TOP or BF_BOTTOM or BF_RIGHT or BF_ADJUST; end; end; R := Column.DisplayRect; if Column.Clicking then DrawEdge(ACanvas.Handle, R, PressedButtonStyle, PressedButtonFlags) else begin if (Column.Hilighted) and (Column.Style = ehbsPlate) then DrawEdge(ACanvas.Handle, R, RaisedButtonStyle, RaisedButtonFlags) else DrawEdge(ACanvas.Handle, R, NormalButtonStyle, NormalButtonFlags) end end; procedure TEasyViewColumn.PaintCheckBox(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); begin if not ((Column.CheckType = ectNone) or (Column.CheckType = ettNoneWithSpace)) then PaintCheckboxCore(Column.CheckType, // TEasyCheckType OwnerListview, // TCustomEasyListview ACanvas, // TCanvas RectArray.CheckRect, // TRect Column.Enabled, // IsEnabled Column.Checked, // IsChecked False, // IsHot Column.CheckFlat, // IsFlat Column.CheckHovering, // IsHovering Column.CheckPending, // IsPending Column, Column.Checksize); end; procedure TEasyViewColumn.PaintDropDownArrow(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); var CtlState, CtlType: Longword; R: TRect; begin if Column.DropDownButton.Visible and (RectWidth(RectArray.DropDownArrow) > 0) then begin R := RectArray.DropDownArrow; {$IFDEF USETHEMES} if OwnerListview.DrawWithThemes then begin { Draw the DropDown Button } CtlType := CP_DROPDOWNBUTTON; if Column.DropDownButton.Enabled then begin CtlState := CBXS_NORMAL; if cdbsDown in Column.DropDownButton.State then CtlState := CBXS_PRESSED else if cdbsHovering in Column.DropDownButton.State then CtlState := CBXS_HOT; end else CtlState := CBXS_DISABLED; DrawThemeBackground(OwnerListview.Themes.ComboBoxTheme, ACanvas.Handle, CtlType, CtlState, R, nil) end else {$ENDIF USETHEMES} begin InflateRect(R, -1, -1); // Looks better { Draw the DropDown Button } CtlType := DFC_SCROLL; CtlState := DFCS_SCROLLCOMBOBOX or DFCS_FLAT; if Column.DropDownButton.Enabled then begin if cdbsHovering in Column.DropDownButton.State then CtlState := CtlState or DFCS_HOT; if cdbsDown in Column.DropDownButton.State then CtlState := CtlState or DFCS_PUSHED; end else CtlState := CtlState or DFCS_INACTIVE; DrawFrameControl(ACanvas.Handle, R, CtlType, CtlState); end end end; procedure TEasyViewColumn.PaintDropGlyph(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); var R: TRect; begin if esosDropTarget in Column.State then begin ACanvas.Brush.Color := clblue; R := Column.DisplayRect; R.Left := R.Right - 2; ACanvas.FillRect(R); end end; procedure TEasyViewColumn.PaintFocusRect(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); begin end; procedure TEasyViewColumn.PaintImage(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject; ImageSize: TEasyImageSize); // // Paints the Icon/Bitmap to the Column // var fStyle: Integer; Images: TCustomImageList; IsCustom: Boolean; begin Column.ImageDrawIsCustom(Column, IsCustom); if IsCustom then Column.ImageDraw(Column, ACanvas, RectArray, AlphaBlender) else begin Images := GetImageList(Column); // Draw the image in the ImageList if available if Assigned(Column.OwnerHeader.Images) and (Column.ImageIndex > -1) then begin fStyle := ILD_TRANSPARENT; if Column.ImageOverlayIndex > -1 then begin ImageList_SetOverlayImage(Images.Handle, Column.ImageOverlayIndex, 1); fStyle := fStyle or INDEXTOOVERLAYMASK(1); end; // Get the "normalized" rectangle for the image RectArray.IconRect.Left := RectArray.IconRect.Left + (RectWidth(RectArray.IconRect) - Images.Width) div 2; RectArray.IconRect.Top := RectArray.IconRect.Top + (RectHeight(RectArray.IconRect) - Images.Height) div 2; ImageList_DrawEx(Images.Handle, Column.ImageIndex, ACanvas.Handle, RectArray.IconRect.Left, RectArray.IconRect.Top, 0, 0, CLR_NONE, CLR_NONE, fStyle); end end end; procedure TEasyViewColumn.PaintSortGlyph(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject); var Image: TBitmap; begin if Column.SortDirection <> esdNone then begin if Column.SortDirection = esdAscending then Image := OwnerListview.GlobalImages.ColumnSortUp else Image := OwnerListview.GlobalImages.ColumnSortDown; ACanvas.Draw(RectArray.SortRect.Left, RectArray.SortRect.Top, Image); end end; procedure TEasyViewColumn.PaintText(Column: TEasyColumn; ACanvas: TCanvas; HeaderType: TEasyHeaderType; RectArray: TEasyRectArrayObject; LinesToDraw: Integer); var DrawTextFlags: TCommonDrawTextWFlags; begin if not IsRectEmpty(RectArray.TextRect) then begin ACanvas.Brush.Style := bsClear; DrawTextFlags := [dtEndEllipsis]; if LinesToDraw = 1 then Include(DrawTextFlags, dtSingleLine); case Column.Alignment of taLeftJustify: Include(DrawTextFlags, dtLeft); taRightJustify: Include(DrawTextFlags, dtRight); taCenter: Include(DrawTextFlags, dtCenter); end; // Vertical Alignment is accounted for in the Text Rects LoadTextFont(Column, ACanvas); if Column.Bold then ACanvas.Font.Style := ACanvas.Font.Style + [fsBold]; OwnerListview.DoColumnPaintText(Column, ACanvas); DrawTextWEx(ACanvas.Handle, Column.Caption, RectArray.TextRects[0], DrawTextFlags, OwnerListview.PaintInfoColumn.CaptionLines); end; end; procedure TEasyViewColumn.ReSizeRectArray( var RectArray: TEasyRectArrayObjectArray); var OldLen, i: Integer; begin if Length(RectArray) < OwnerListview.Header.Positions.Count then begin OldLen := Length(RectArray); SetLength(RectArray, OwnerListview.Header.Positions.Count); for i := OldLen to OwnerListview.Header.Positions.Count - 1 do FillChar(RectArray[i], SizeOf(RectArray[i]), #0); end else if Length(RectArray) > OwnerListview.Header.Positions.Count then SetLength(RectArray, OwnerListview.Header.Positions.Count); if Length(RectArray) = 0 then begin SetLength(RectArray, 1); FillChar(RectArray[0], SizeOf(RectArray[0]), #0); end end; { TEasyGroupGrid } constructor TEasyGridGroup.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner); FOwnerGroup := AnOwnerGroup; FLayout := eglVert // Default orientation end; destructor TEasyGridGroup.Destroy; begin inherited; end; function TEasyGridGroup.AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; var ColumnPos: Integer; TestPt: TPoint; LastItem: TEasyItem; RectArray: TEasyRectArrayObject; AdjacentGroup: TEasyGroup; begin Result := nil; if Assigned(Item) then begin Assert(Item.Visible, 'Can not find TEasyGroups.AdjacentItem of an Invisible Item'); case Direction of acdLeft: begin Result := Item; if Item.VisibleIndexInGroup > 0 then Result := OwnerGroup.VisibleItem[Item.VisibleIndexInGroup - 1] else begin AdjacentGroup := PrevVisibleGroupWithNItems(OwnerGroup, 0); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[AdjacentGroup.VisibleCount - 1] end end; acdRight: begin Result := Item; if Item.VisibleIndexInGroup < OwnerGroup.VisibleCount - 1 then Result := OwnerGroup.VisibleItem[Item.VisibleIndexInGroup + 1] else begin AdjacentGroup := NextVisibleGroupWithNItems(OwnerGroup, 0); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[0] end end; acdUp: begin // First see if we can stay in the same group if Item.VisibleIndexInGroup - ColumnCount >= 0 then Result := OwnerGroup.VisibleItems[Item.VisibleIndexInGroup - ColumnCount] else begin ColumnPos := Item.ColumnPos; while not Assigned(Result) and (ColumnPos > -1) do begin AdjacentGroup := PrevVisibleGroupWithNItems(OwnerGroup, ColumnPos); if Assigned(AdjacentGroup) then Result := LastItemInNColumn(AdjacentGroup, ColumnPos); Dec(ColumnPos) end end end; acdDown: begin // First see if we can stay in the same group if Item.VisibleIndexInGroup + ColumnCount < OwnerGroup.VisibleCount then Result := OwnerGroup.VisibleItems[Item.VisibleIndexInGroup + ColumnCount] else begin ColumnPos := Item.ColumnPos; while not Assigned(Result) and (ColumnPos > -1) do begin AdjacentGroup := NextVisibleGroupWithNItems(OwnerGroup, ColumnPos); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[ColumnPos]; Dec(ColumnPos) end end end; acdPageUp: begin TestPt := Item.DisplayRect.BottomRight; // The Right is actually the Left of the next object Dec(TestPt.X); Dec(TestPt.Y, OwnerListview.ClientHeight); // Make sure we don't run past the last row of items. AdjacentGroup := OwnerGroups.FirstVisibleGroup; if Assigned(AdjacentGroup) then if TestPt.Y < AdjacentGroup.DisplayRect.Top + OwnerGroup.Grid.StaticTopItemMargin then TestPt.Y := AdjacentGroup.BoundsRectBkGnd.Top + OwnerGroup.Grid.StaticTopItemMargin; Result := OwnerGroups.ItembyPoint(TestPt); if not Assigned(Result) then begin Result := SearchForHitRight(Item.ColumnPos, TestPt); while not Assigned(Result) and (TestPt.Y > OwnerGroups.ViewRect.Top) do begin Inc(TestPt.Y, CellSize.Height); Result := SearchForHitRight(Item.ColumnPos, TestPt); end end end; acdPageDown: begin TestPt := Item.DisplayRect.TopLeft; Inc(TestPt.Y, OwnerListview.ClientHeight); // Make sure we don't run past the last row of items. LastItem := OwnerGroups.LastItem; if Assigned(LastItem) then begin LastItem.View.ItemRectArray(LastItem, nil, nil, Item.Caption, RectArray); if TestPt.Y > RectArray.LabelRect.Bottom - 1 then TestPt.Y := RectArray.LabelRect.Bottom - 1; end; // Look for an item directly below the currently selected item Result := OwnerGroups.ItembyPoint(TestPt); // If not found then look to the right until we find an item if not Assigned(Result) then begin Result := SearchForHitRight(Item.ColumnPos, TestPt); while not Assigned(Result) and (TestPt.Y < OwnerGroups.ViewRect.Bottom) do begin Inc(TestPt.Y, CellSize.Height); Result := SearchForHitRight(Item.ColumnPos, TestPt); end end end end end end; procedure TEasyGridGroup.AutoSizeCells; var Item: TEasyItem; RectArray: TEasyRectArrayObject; ACanvas: TCanvas; TextSize: TSize; begin if CellSize.AutoSize then begin FindLongestCaption(nil, Item); if Assigned(Item) then begin ACanvas := TCanvas.Create; try ACanvas.Handle := GetDC(0); Item.View.ItemRectArray(Item, nil, ACanvas, '', RectArray); Item.View.LoadTextFont(Item, 0, ACanvas, True); TextSize := TextExtentW(Item.Caption, ACanvas); CellSize.AutoSizeWidth := RectWidth(RectArray.CheckRect) + RectWidth(RectArray.IconRect) + RectWidth(RectArray.StateRect) + TextSize.cx + 18; finally ReleaseDC(0, ACanvas.Handle); ACanvas.Handle := 0; ACanvas.Free; end end end end; procedure TEasyGridGroup.FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); // // The default implementation assumes a "grid" type arrangement of the grid // var Item: TEasyItem; begin Index := -1; Group := OwnerGroups.GroupByPoint(ViewportPoint); if Assigned(Group) then begin Item := Group.ItemByPoint(ViewportPoint); if Assigned(Item) then begin if ViewportPoint.X < RectWidth( Item.DisplayRect) div 2 then Index := Item.Index else Index := Item.Index + 1 end end end; function TEasyGridGroup.GetMaxColumns(Group: TEasyGroup; WindowWidth: Integer): Integer; begin Result := (WindowWidth - (Group.MarginLeft.RuntimeSize + Group.MarginRight.RuntimeSize)) div CellSize.Width; if FColumnCount = 0 then Inc(FColumnCount); end; function TEasyGridGroup.GetOwnerGroups: TEasyGroups; begin Result := OwnerGroup.OwnerGroups end; function TEasyGridGroup.LastItemInNColumn(Group: TEasyGroup; N: Integer): TEasyItem; // // Finds the last item in the group in the specified column. It assumes // that the item does exist (N >= Group.ItemCount) // var RowPos: Integer; begin RowPos := Group.VisibleCount div Group.Grid.ColumnCount; if RowPos * ColumnCount + N >= Group.VisibleCount then Dec(RowPos); Result := Group.Items[RowPos * ColumnCount + N] end; function TEasyGridGroup.NextVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; // // Returns the first next group encountered when at least N items in it // var i: Integer; begin Result := nil; i := StartGroup.VisibleIndex + 1; while not Assigned(Result) and (i < OwnerGroups.VisibleCount) do begin if OwnerGroups.VisibleGroup[i].VisibleCount > N then Result := OwnerGroups.VisibleGroup[i]; Inc(i) end end; function TEasyGridGroup.PrevVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; // // Returns the first prev group encountered when at least N items in it // var i: Integer; begin Result := nil; i := StartGroup.VisibleIndex - 1; while not Assigned(Result) and (i >= 0) do begin if OwnerGroups.VisibleGroup[i].VisibleCount > N then Result := OwnerGroups.VisibleGroup[i]; Dec(i) end end; function TEasyGridGroup.SearchForHitRight(ColumnPos: Integer; Pt: TPoint): TEasyItem; begin Result := nil; while not Assigned(Result) and (ColumnPos >= 0) do begin Result := OwnerGroups.ItembyPoint(Pt); Dec(Pt.X, CellSize.Width); Dec(ColumnPos) end; end; function TEasyGridGroup.StaticTopItemMargin: Integer; // Distance added between the bottom of the top margin and the first // item, and the distance between the bottom of the last item and the // top of the bottom margin begin Result := 0 end; function TEasyGridGroup.StaticTopMargin: Integer; // Distance added from top of control to the top of the first group begin Result := 0; end; procedure TEasyGridGroup.FindLongestCaption(Column: TEasyColumn; var Item: TEasyItem); var TempItem: TEasyItem; ColumnIndex, i: Integer; begin Item := nil; if Assigned(Column) then ColumnIndex := Column.Index else ColumnIndex := 0; // can't use enumerators here as the list is not reindexed yet for i := 0 to OwnerGroup.Items.Count - 1 do begin TempItem := TEasyItem( OwnerGroup.Items[i]); if TempItem.Visible then begin if not Assigned(Item) then Item := TempItem else begin if Length(TempItem.Captions[ColumnIndex]) > Length(Item.Captions[ColumnIndex]) then Item := TempItem; end end end end; procedure TEasyGridGroup.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); var TopLeft: TPoint; i, LeftEdge, BottomEdge, ItemGroupVisibleIndex: Integer; RectArray: TEasyRectArrayObject; WndWidth, VisibleCount, ItemMargin, GroupMargin, MarginTop, MarginLeft, MarginRight: Integer; FocusedItem, Item: TEasyItem; LocalCellSize: TEasyCellSize; begin AutoSizeCells; BottomEdge := 0; GroupMargin := StaticTopMargin; ItemMargin := StaticTopItemMargin; LocalCellSize := CellSize; MarginLeft := OwnerGroup.MarginLeft.RuntimeSize; MarginTop := OwnerGroup.MarginTop.RuntimeSize; MarginRight := OwnerGroup.MarginRight.RuntimeSize; // First calculate the Width of the group box. The height will be dynamically // calculated during the enumeration of the items WndWidth := OwnerListview.ClientWidth - 1; if not OwnerListview.Scrollbars.VertBarVisible then WndWidth := WndWidth - GetSystemMetrics(SM_CYVSCROLL); if WndWidth < MarginRight + MarginLeft + LocalCellSize.Width then WndWidth := MarginRight + MarginLeft + LocalCellSize.Width; OwnerGroup.FDisplayRect := Rect(0, StaticTopMargin, WndWidth, GroupMargin); VisibleCount := 0; FocusedItem := nil; // Prepare the VisibleList for the worse case, all are visible OwnerGroup.VisibleItems.Clear; OwnerGroup.VisibleItems.Capacity := OwnerGroup.Items.Count; ItemGroupVisibleIndex := 0; if OwnerGroup.Visible then begin if OwnerGroup.Expanded and (OwnerGroup.Items.Count > 0) then begin // First calculate the number of columns we can accommodate FColumnCount := GetMaxColumns(OwnerGroup, WndWidth); TopLeft := Point(0, 0); LeftEdge := ColumnCount * LocalCellSize.Width; for i := 0 to OwnerGroup.Items.Count - 1 do begin if TopLeft.X + LocalCellSize.Width > LeftEdge then begin TopLeft.X := 0; Inc(TopLeft.Y, LocalCellSize.Height); end; Item := OwnerGroup.Items[i]; if Item.Visible then begin Item.FVisibleIndexInGroup := ItemGroupVisibleIndex; Item.FVisibleIndex := NextVisibleItemIndex; Inc(NextVisibleItemIndex); Inc(ItemGroupVisibleIndex); OwnerGroup.VisibleItems.Add(Item); BottomEdge := TopLeft.Y + LocalCellSize.Height; Item.FDisplayRect := Rect(TopLeft.X, TopLeft.Y, TopLeft.X + LocalCellSize.Width, BottomEdge); Inc(TopLeft.X, LocalCellSize.Width); Inc(VisibleCount); end else begin Item.FDisplayRect := Rect(TopLeft.X, TopLeft.Y, TopLeft.X, TopLeft.Y + LocalCellSize.Height); Item.FVisibleIndexInGroup := -1; end; OffsetRect(Item.FDisplayRect, MarginLeft, MarginTop + GroupMargin + ItemMargin); if Item.Focused then FocusedItem := Item; if Assigned(PrevGroup) then OffsetRect(Item.FDisplayRect, 0, PrevGroup.DisplayRect.Bottom); end end else begin // Collapsed group can't have focused item, move it to the next Visible item FocusedItem := OwnerListview.Selection.FocusedItem; if Assigned(FocusedItem) then if FocusedItem.OwnerGroup = OwnerGroup then OwnerListview.Selection.FocusedItem := Self.OwnerGroups.NextVisibleItem(FocusedItem) end; if ColumnCount > 0 then FRowCount := OwnerGroup.Items.Count div ColumnCount else FRowCount := 0; if ColumnCount > 0 then if OwnerGroup.Items.Count mod ColumnCount > 0 then Inc(FRowCount); if OwnerGroup.Expanded then Inc(OwnerGroup.FDisplayRect.Bottom, OwnerGroup.MarginBottom.RuntimeSize + OwnerGroup.MarginTop.RuntimeSize + BottomEdge + ItemMargin * 2) else Inc(OwnerGroup.FDisplayRect.Bottom, OwnerGroup.MarginBottom.RuntimeSize + OwnerGroup.MarginTop.RuntimeSize + BottomEdge) end; // Take care of the items in groups that are not visible or expanded // If the Group's is not visible then its items can not be selected. // Current it is allowed to have selected items in collapsed groups if not OwnerGroup.Visible then begin i := 0; while (i < OwnerGroup.Items.Count) and (OwnerListview.Selection.Count > 0) do begin OwnerGroup.Items[i].Selected := False; Inc(i) end; if Assigned(OwnerListview.Selection.FocusedItem) then if OwnerListview.Selection.FocusedItem.OwnerGroup = OwnerGroup then OwnerListview.Selection.FocusedItem := nil; end; // Special case if all the items are not visible if VisibleCount = 0 then begin FColumnCount := 0; FRowCount := 0; end; if Assigned(PrevGroup) then OffsetRect(OwnerGroup.FDisplayRect, 0, PrevGroup.DisplayRect.Bottom); // Always resize the group if on the bottom the the control if Assigned(FocusedItem) and (OwnerListview.Selection.ResizeGroupOnFocus or (OwnerGroup.Index + 1 = OwnerGroups.Count)) then begin FocusedItem.ItemRectArray(nil, OwnerListview.ScratchCanvas, RectArray); if RectArray.FullTextRect.Bottom > OwnerGroup.FDisplayRect.Bottom - OwnerGroup.MarginBottom.RuntimeSize then Inc(OwnerGroup.FDisplayRect.Bottom, RectArray.FullTextRect.Bottom - FocusedItem.DisplayRect.Bottom); end end; constructor TEasyGridReportGroup.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner, AnOwnerGroup); FLayout := eglGrid end; function TEasyGridReportGroup.AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; var TestPt: TPoint; begin Result := nil; if Assigned(Item) then begin case Direction of acdUp: Result := OwnerGroups.PrevVisibleItem(Item); acdDown: Result := OwnerGroups.NextVisibleItem(Item); acdPageUp: // WL, 05/01/05 begin // Look for first visible item at top. // The Makevisible offsets a bit to deal with the inplace editor TestPt := Point(0, OwnerListview.ClientInViewportCoords.Top + V_STRINGEDITORMARGIN div 2); repeat Result := OwnerGroups.ItembyPoint(TestPt); Inc(TestPt.Y, CellSize.Height); until (Result <> nil) or (Result = Item) or (TestPt.Y >= OwnerListview.ClientInViewportCoords.Bottom); // If first visible item is the parameter Item already we must look one // page further up. Find the furthest item which still allows Result // and item to be on one page. if (Result <> nil) and (Result = Item) then begin TestPt := Point(0, Item.DisplayRect.Bottom - RectHeight(OwnerListview.ClientInViewportCoords) - 1); repeat Result := OwnerGroups.ItembyPoint(TestPt); Inc(TestPt.Y, CellSize.Height); until Result <> nil; // loop terminates at Item at the latest (which must be below) if Result = Item then Result := nil; // no adjacent page-down item found, Item was already the first one end; end; acdPageDown: // WL, 05/01/05 begin // Look for last visible item at bottom. // The Makevisible offsets a bit to deal with the inplace editor TestPt := Point(0, OwnerListview.ClientInViewportCoords.Bottom - 1 - V_STRINGEDITORMARGIN div 2); repeat Result := OwnerGroups.ItembyPoint(TestPt); Dec(TestPt.Y, CellSize.Height); until (Result <> nil) or (Result = Item) or (TestPt.Y < OwnerListview.ClientInViewportCoords.Top); // If last visible item is the parameter Item already we must look one // page further down. Find the furthest item which still allows Result // and item to be on one page. if (Result <> nil) and (Result = Item) then begin TestPt := Point(0, Item.DisplayRect.Top + RectHeight(OwnerListview.ClientInViewportCoords) - 1); repeat Result := OwnerGroups.ItembyPoint(TestPt); Dec(TestPt.Y, CellSize.Height); until Result <> nil; // loop terminates at Item at the latest (which must be above) if Result = Item then Result := nil; // no adjacent page-down item found, Item was already the last one end; end else Result := inherited AdjacentItem(Item, Direction); end end end; procedure TEasyGridReportGroup.FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); begin end; function TEasyGridReportGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.Report end; { TEasyReportGroupGrid } procedure TEasyGridReportGroup.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); var i, Top, Bottom, Width, Left, Offset, TopMargin, BottomMargin, VisibleCount: Integer; Item: TEasyItem; begin AutoSizeCells; if CellSize.AutoSize and (OwnerListview.Header.Columns.Count > 0) then OwnerListview.Header.Columns[0].Width := CellSize.Width; if Assigned(PrevGroup) then Offset := PrevGroup.DisplayRect.Bottom else Offset := V_STRINGEDITORMARGIN; OwnerGroup.FDisplayRect := Rect(0, Offset, OwnerListview.Header.ViewWidth, Offset); // Prepare the VisibleList for the worse case, all are visible OwnerGroup.VisibleItems.Clear; OwnerGroup.VisibleItems.Capacity := OwnerGroup.Items.Count; Left := OwnerGroup.MarginLeft.RuntimeSize; if OwnerListview.Header.LastColumnByPosition <> nil then begin Width := OwnerListview.Header.LastColumnByPosition.DisplayRect.Right; Width := Width - OwnerGroup.MarginRight.RuntimeSize end else Width := 0; TopMargin := OwnerGroup.MarginTop.RuntimeSize; BottomMargin := OwnerGroup.MarginBottom.RuntimeSize; if OwnerGroup.Visible then begin if OwnerGroup.Expanded and (OwnerGroup.Items.Count > 0) then begin VisibleCount := 0; Top := Offset + TopMargin; Bottom := Offset + CellSize.Height + TopMargin; for i := 0 to OwnerGroup.Items.Count - 1 do begin Item := OwnerGroup.Items.List.List[i]; // Direct Access for Speed if Item.Visible then begin Item.FVisibleIndex := NextVisibleItemIndex; Item.FVisibleIndexInGroup := VisibleCount; Item.FDisplayRect := Rect(Left, Top, Width, Bottom); OwnerGroup.VisibleItems.Add(Item); Inc(Top, CellSize.Height); Inc(Bottom, CellSize.Height); Inc(VisibleCount); Inc(NextVisibleItemIndex); end else Item.FDisplayRect := Rect(Left, Top, Width, Top); OwnerGroup.FDisplayRect.Bottom := Item.FDisplayRect.Bottom + BottomMargin; if OwnerGroups.LastGroup = OwnerGroup then OwnerGroup.FDisplayRect.Bottom := Item.FDisplayRect.Bottom + V_STRINGEDITORMARGIN * 2; end end else OwnerGroup.FDisplayRect := Rect(0, Offset, OwnerListview.Header.ViewWidth, Offset + TopMargin + BottomMargin); end; // Column Count does not relate to Report view columns. It is a more primitive // and the Report columns are within the Grid Column FColumnCount := 1; end; procedure TEasyGridReportGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.Report.Assign(Value) end; constructor TEasyGridListGroup.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner, AnOwnerGroup); FLayout := eglHorz end; function TEasyGridListGroup.AdjacentItem(Item: TEasyItem; Direction: TEasyAdjacentCellDir): TEasyItem; function NextVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; // // Returns the first next group encountered when at least N items in it // var i: Integer; begin Result := nil; i := StartGroup.VisibleIndex + 1; while not Assigned(Result) and (i < OwnerGroups.VisibleCount) do begin if OwnerGroups.VisibleGroup[i].VisibleCount > N then Result := OwnerGroups.VisibleGroup[i]; Inc(i) end end; function PrevVisibleGroupWithNItems(StartGroup: TEasyGroup; N: Integer): TEasyGroup; // // Returns the first prev group encountered when at least N items in it // var i: Integer; begin Result := nil; i := StartGroup.VisibleIndex - 1; while not Assigned(Result) and (i >= 0) do begin if OwnerGroups.VisibleGroup[i].VisibleCount > N then Result := OwnerGroups.VisibleGroup[i]; Dec(i) end end; function LastItemInNRow(Group: TEasyGroup; N: Integer): TEasyItem; // // Finds the last item in the group in the specified column. It assumes // that the item does exist (N >= Group.ItemCount) // var ColumnPos: Integer; begin ColumnPos := Group.VisibleCount div Group.Grid.RowCount; if ColumnPos * RowCount + N >= Group.VisibleCount then Dec(ColumnPos); Result := Group.Items[ColumnPos * RowCount + N] end; function SearchForHitRight(ColumnPos: Integer; Pt: TPoint): TEasyItem; begin Result := nil; while not Assigned(Result) and (ColumnPos >= 0) do begin Result := OwnerGroups.ItembyPoint(Pt); Dec(Pt.X, CellSize.Width); Dec(ColumnPos) end; end; var RowPos, ItemIndex: Integer; AdjacentGroup: TEasyGroup; begin Result := nil; if Assigned(Item) then begin Assert(Item.Visible, 'Can not find TEasyGroups.AdjacentItem of an Invisible Item'); case Direction of acdUp: begin Result := Item; if Item.VisibleIndexInGroup > 0 then Result := OwnerGroup.VisibleItem[Item.VisibleIndexInGroup - 1] else begin AdjacentGroup := PrevVisibleGroupWithNItems(OwnerGroup, 0); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[AdjacentGroup.VisibleCount - 1] end end; acdDown: begin Result := Item; if Item.VisibleIndexInGroup < OwnerGroup.VisibleCount - 1 then Result := OwnerGroup.VisibleItem[Item.VisibleIndexInGroup + 1] else begin AdjacentGroup := NextVisibleGroupWithNItems(OwnerGroup, 0); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[0] end end; acdLeft: begin // First see if we can stay in the same group if Item.VisibleIndexInGroup - RowCount >= 0 then Result := OwnerGroup.VisibleItems[Item.VisibleIndexInGroup - RowCount] else begin RowPos := Item.RowPos; while not Assigned(Result) and (RowPos > -1) do begin AdjacentGroup := PrevVisibleGroupWithNItems(OwnerGroup, RowPos); if Assigned(AdjacentGroup) then Result := LastItemInNRow(AdjacentGroup, RowPos); Dec(RowPos) end end end; acdRight: begin // First see if we can stay in the same group if Item.VisibleIndexInGroup + RowCount < OwnerGroup.VisibleCount then Result := OwnerGroup.VisibleItems[Item.VisibleIndexInGroup + RowCount] else begin RowPos := Item.RowPos; while not Assigned(Result) and (RowPos > -1) do begin AdjacentGroup := NextVisibleGroupWithNItems(OwnerGroup, RowPos); if Assigned(AdjacentGroup) then Result := AdjacentGroup.VisibleItem[RowPos]; Dec(RowPos) end end end; acdPageUp: begin ItemIndex := Item.VisibleIndexInGroup; while (ItemIndex > 0) and (ItemIndex mod RowCount <> 0) do Dec(ItemIndex); Result := OwnerGroup.Items[ItemIndex] end; acdPageDown: begin ItemIndex := Item.VisibleIndexInGroup; while (ItemIndex < Item.OwnerGroup.Items.Count - 1) and (ItemIndex mod RowCount <> RowCount - 1) do Inc(ItemIndex); Result := OwnerGroup.Items[ItemIndex] end end end end; procedure TEasyGridListGroup.FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); begin end; function TEasyGridListGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.List end; { TEasyListGroupGrid } procedure TEasyGridListGroup.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); var ScrollSize, ClientHeight: Integer; TopLeft: TPoint; i, Offset, VisibleCount, Height: Integer; RectArray: TEasyRectArrayObject; TextSize: TSize; R: TRect; Item: TEasyItem; begin AutoSizeCells; VisibleCount := 0; // Always assume a scroll bar ScrollSize := GetSystemMetrics(SM_CXHSCROLL); ClientHeight := OwnerListview.ClientHeight; if Assigned(PrevGroup) then Offset := PrevGroup.DisplayRect.Right else Offset := 0; Height := ClientHeight - ScrollSize - OwnerListview.Header.RuntimeHeight; // May have to show a vertical scrollbar if the entire thing won't fit in the window if Height < OwnerGroup.MarginBottom.RuntimeSize + OwnerGroup.MarginTop.RuntimeSize + CellSize.Height then Height := OwnerGroup.MarginBottom.RuntimeSize + OwnerGroup.MarginTop.RuntimeSize + CellSize.Height; OwnerGroup.FDisplayRect := Rect(Offset, 0, Offset, Height); // Prepare the VisibleList for the worse case, all are visible OwnerGroup.VisibleItems.Clear; OwnerGroup.VisibleItems.Capacity := OwnerGroup.Items.Count; if OwnerGroup.Visible then begin if OwnerGroup.Expanded and (OwnerGroup.Items.Count > 0) then begin // First calculate the number of rows we can accommodate FRowCount := (Height - 1 - (OwnerGroup.MarginBottom.RuntimeSize + OwnerGroup.MarginTop.RuntimeSize)) div CellSize.Height; if FRowCount = 0 then Inc(FRowCount); FColumnCount := 1; TopLeft := Point(Offset + OwnerGroup.MarginLeft.RuntimeSize, OwnerGroup.MarginTop.RuntimeSize); for i := 0 to OwnerGroup.Items.Count - 1 do begin Item := OwnerGroup.Items[i]; if Item.Visible then begin Item.FVisibleIndex := NextVisibleItemIndex; Item.FVisibleIndexInGroup := VisibleCount; OwnerGroup.VisibleItems.Add(Item); R := Rect(TopLeft.X, TopLeft.Y, TopLeft.X + CellSize.Width, TopLeft.Y + CellSize.Height); Inc(TopLeft.Y, CellSize.Height); Inc(VisibleCount) end else R := Rect(TopLeft.X, TopLeft.Y, TopLeft.X, TopLeft.Y + CellSize.Height); if R.Bottom > Height - OwnerGroup.MarginBottom.RuntimeSize then begin OffsetRect(R, CellSize.Width, -(TopLeft.Y - CellSize.Height - OwnerGroup.MarginTop.RuntimeSize)); TopLeft.Y := OwnerGroup.MarginTop.RuntimeSize + CellSize.Height; Inc(TopLeft.X, CellSize.Width); Inc(FColumnCount); end; OwnerGroup.Items[i].FDisplayRect := R end; OwnerGroup.FDisplayRect.Right := TopLeft.X + CellSize.Width + OwnerGroup.MarginRight.RuntimeSize; end; // Special case if all the items are not visible if VisibleCount = 0 then begin TextSize := TextExtentW(OwnerGroup.Caption, OwnerListview.GroupFont); OwnerGroup.View.GroupRectArray(OwnerGroup, egmeTop, OwnerGroup.BoundsRectTopMargin, RectArray); FColumnCount := 0; FRowCount := 0; OwnerGroup.FDisplayRect.Right := OwnerGroup.MarginLeft.RuntimeSize + OwnerGroup.MarginRight.RuntimeSize + RectArray.IconRect.Right + OwnerGroup.CaptionIndent + TextSize.cx; end; end; end; procedure TEasyGridListGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.List.Assign(Value) end; { TEasyFooterMargin } constructor TCustomEasyFooterMargin.Create(AnOwner: TCustomEasyListview); begin inherited; FImageIndex := -1; FImageOverlayIndex := -1; FSize := 30; end; destructor TCustomEasyFooterMargin.Destroy; begin FreeAndNil(FPaintInfo); inherited; end; function TCustomEasyFooterMargin.GetAlignment: TAlignment; begin Result := PaintInfo.Alignment end; function TCustomEasyFooterMargin.GetCaptionIndent: Integer; begin Result := PaintInfo.CaptionIndent end; function TCustomEasyFooterMargin.GetCaptionLines: Integer; begin Result := PaintInfo.CaptionLines end; function TCustomEasyFooterMargin.GetImageIndent: Integer; begin Result := PaintInfo.ImageIndent end; function TCustomEasyFooterMargin.GetPaintInfo: TEasyPaintInfoBaseGroup; begin if not Assigned(FPaintInfo) then Result := OwnerListview.PaintInfoGroup.MarginBottom.FPaintInfo else Result := FPaintInfo end; function TCustomEasyFooterMargin.GetVAlignment: TCommonVAlignment; begin Result := PaintInfo.VAlignment end; procedure TCustomEasyFooterMargin.Assign(Source: TPersistent); var Temp: TCustomEasyFooterMargin; begin inherited Assign(Source); if Source is TCustomEasyFooterMargin then begin Temp := TCustomEasyFooterMargin(Source); FCaption := Temp.Caption; end end; procedure TCustomEasyFooterMargin.SetAlignment(Value: TAlignment); begin if Alignment <> Value then begin PaintInfo.Alignment := Value; OwnerListview.Groups.Rebuild end; end; procedure TCustomEasyFooterMargin.SetCaption(Value: WideString); begin if FCaption <> Value then begin FCaption := Value; OwnerListview.Groups.Rebuild end; end; procedure TCustomEasyFooterMargin.SetCaptionIndent(Value: Integer); begin if CaptionIndent <> Value then begin PaintInfo.CaptionIndent := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TCustomEasyFooterMargin.SetCaptionLines(Value: Integer); begin if CaptionLines <> Value then begin PaintInfo.CaptionLines := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TCustomEasyFooterMargin.SetImageIndent(Value: Integer); begin if ImageIndent <> Value then begin PaintInfo.ImageIndent := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TCustomEasyFooterMargin.SetImageIndex(const Value: TCommonImageIndexInteger); begin if FImageIndex <> Value then begin FImageIndex := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TCustomEasyFooterMargin.SetImageOveralyIndex(const Value: TCommonImageIndexInteger); begin if FImageOverlayIndex <> Value then begin FImageOverlayIndex := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TCustomEasyFooterMargin.SetPaintInfo(const Value: TEasyPaintInfoBaseGroup); begin if not Assigned(FPaintInfo) then OwnerListview.PaintInfoGroup.Assign(Value) else FPaintInfo.Assign(Value) end; procedure TCustomEasyFooterMargin.SetVAlignment( Value: TCommonVAlignment); begin if VAlignment <> Value then begin PaintInfo.VAlignment := Value; OwnerListview.SafeInvalidateRect(nil, False) end; end; { TEasyBasicItemPaintInfo } constructor TEasyPaintInfoBasic.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FImageIndent := 2; FCaptionIndent := 4; FCaptionLines := 1; FBorder := 4; FBorderColor := clHighlight; FCheckIndent := 2; FChecksize := 12; FVAlignment := cvaCenter; FShowBorder := True; end; procedure TEasyPaintInfoBasic.Assign(Source: TPersistent); var Temp: TEasyPaintInfoBasic; begin if Source is TEasyPaintInfoBasic then begin Temp := TEasyPaintInfoBasic(Source); FAlignment := Temp.Alignment; FBorder := Temp.Border; FBorderColor := Temp.BorderColor; FCaptionIndent := Temp.CaptionIndent; FCaptionLines := Temp.CaptionLines; FCheckFlat := Temp.CheckFlat; FCheckIndent := Temp.CheckIndent; FChecksize := Temp.Checksize; FCheckType := Temp.CheckType; FImageIndent := Temp.ImageIndent; FVAlignment := Temp.VAlignment; end end; procedure TEasyPaintInfoBasic.Invalidate(ImmediateUpdate: Boolean); begin OwnerListview.SafeInvalidateRect(nil, ImmediateUpdate) end; procedure TEasyPaintInfoBasic.SetAlignment(Value: TAlignment); begin if Value <> FAlignment then begin FAlignment := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetBorder(Value: Integer); begin if Value <> FBorder then begin FBorder := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetBorderColor(Value: TColor); begin if Value <> FBorderColor then begin FBorderColor := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetCaptionIndent(Value: Integer); begin if Value <> FCaptionIndent then begin FCaptionIndent := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetCaptionLines(Value: Integer); begin if Value <> FCaptionLines then begin FCaptionLines := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetCheckFlat(Value: Boolean); begin if Value <> FCheckFlat then begin FCheckFlat := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetCheckIndent(Value: Integer); begin if Value <> FCheckIndent then begin FCheckIndent := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetChecksize(Value: Integer); begin if Value <> FChecksize then begin FChecksize := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetCheckType(Value: TEasyCheckType); begin if Value <> FCheckType then begin FCheckType := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetImageIndent(Value: Integer); begin if Value <> FImageIndent then begin FImageIndent := Value; Invalidate(False) end end; procedure TEasyPaintInfoBasic.SetShowBorder(const Value: Boolean); begin FShowBorder := Value; end; procedure TEasyPaintInfoBasic.SetVAlignment(Value: TCommonVAlignment); begin if Value <> FVAlignment then begin FVAlignment := Value; Invalidate(False) end end; { TEasyBasicGroupPaintInfo } constructor TEasyPaintInfoBaseGroup.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FBandBlended := True; FBandColor := clBlue; FBandColorFade := clWindow; FBandEnabled := True; FBandLength := 300; FBandMargin := 2; FBandRadius := 4; FBandThickness := 3; FExpandable := True; FExpanded := True; FExpandImageIndent := 4; FMarginBottom := TEasyFooterMargin.Create(AnOwner); FMarginLeft := TEasyMargin.Create(AnOwner); FMarginRight := TEasyMargin.Create(AnOwner); FMarginTop := TEasyHeaderMargin.Create(AnOwner); end; destructor TEasyPaintInfoBaseGroup.Destroy; begin inherited; FreeAndNil(FMarginBottom); FreeAndNil(FMarginLeft); FreeAndNil(FMarginRight); FreeAndNil(FMarginTop); end; function TEasyPaintInfoBaseGroup.GetMarginBottom: TCustomEasyFooterMargin; begin Result := FMarginBottom end; function TEasyPaintInfoBaseGroup.GetMarginLeft: TEasyMargin; begin Result := FMarginLeft end; function TEasyPaintInfoBaseGroup.GetMarginRight: TEasyMargin; begin Result := FMarginRight end; function TEasyPaintInfoBaseGroup.GetMarginTop: TEasyHeaderMargin; begin Result := FMarginTop end; procedure TEasyPaintInfoBaseGroup.Assign(Source: TPersistent); var Temp: TEasyPaintInfoBaseGroup; begin inherited Assign(Source); if Source is TEasyPaintInfoBaseGroup then begin Temp := TEasyPaintInfoBaseGroup(Source); FBandBlended := Temp.BandBlended; FBandColor := Temp.BandColor; FBandColorFade := Temp.BandColorFade; FBandEnabled := Temp.BandEnabled; FBandFullWidth := Temp.BandFullWidth; FBandIndent := Temp.BandIndent; FBandLength := Temp.BandLength; FBandMargin := Temp.BandMargin; FBandRadius := Temp.BandRadius; FBandThickness := Temp.BandThickness; FExpandable := Temp.Expandable; FExpandImageIndent := Temp.ExpandImageIndent; MarginBottom.Assign(Temp.MarginBottom); MarginLeft.Assign(Temp.MarginLeft); MarginRight.Assign(Temp.MarginRight); MarginTop.Assign(Temp.MarginTop); end end; procedure TEasyPaintInfoBaseGroup.SetBandBlended(Value: Boolean); begin if Value <> FBandBlended then begin FBandBlended := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandColor(Value: TColor); begin if Value <> FBandColor then begin FBandColor := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandColorFade(Value: TColor); begin if Value <> FBandColorFade then begin FBandColorFade := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandEnabled(Value: Boolean); begin if Value <> FBandEnabled then begin FBandEnabled := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandFullWidth(Value: Boolean); begin if Value <> FBandFullWidth then begin FBandFullWidth := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandIndent(Value: Integer); begin if Value <> FBandIndent then begin FBandIndent := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandLength(Value: Integer); begin if Value <> FBandLength then begin FBandLength := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandMargin(Value: Integer); begin if Value <> FBandMargin then begin FBandMargin := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandRadius(Value: Byte); begin if Value <> FBandRadius then begin FBandRadius := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetBandThickness(Value: Integer); begin if Value <> FBandThickness then begin FBandThickness := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetExpandable(Value: Boolean); begin if Value <> FExpandable then begin FExpandable := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetExpandImageIndent(Value: Integer); begin if Value <> FExpandImageIndent then begin FExpandImageIndent := Value; Invalidate(False) end end; procedure TEasyPaintInfoBaseGroup.SetMarginBottom( Value: TCustomEasyFooterMargin); begin if Value <> FMarginBottom then begin FreeAndNil(FMarginBottom); FMarginBottom := Value end end; procedure TEasyPaintInfoBaseGroup.SetMarginLeft(Value: TEasyMargin); begin if Value <> FMarginLeft then begin FreeAndNil(FMarginLeft); FMarginLeft := Value end end; procedure TEasyPaintInfoBaseGroup.SetMarginRight(Value: TEasyMargin); begin if Value <> FMarginRight then begin FreeAndNil(FMarginRight); FMarginRight := Value end end; procedure TEasyPaintInfoBaseGroup.SetMarginTop(Value: TEasyHeaderMargin); begin if Value <> FMarginTop then begin FreeAndNil(FMarginTop); FMarginTop := Value end end; { TEasyHotTrackManager} constructor TEasyHotTrackManager.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FColor := clHighlight; FUnderLine := True; FCursor := crHandPoint; FGroupTrack := [htgIcon, htgText]; FItemTrack := [htiIcon, htiText]; FColumnTrack := [htcIcon, htcText] end; function TEasyHotTrackManager.GetPendingObject(MousePos: TPoint): TEasyCollectionItem; begin Result := FPendingObject end; procedure TEasyHotTrackManager.SetPendingObject(MousePos: TPoint; Value: TEasyCollectionItem); var TempOldItem: TEasyCollectionItem; OldCapture: HWnd; begin if FPendingObject <> Value then begin TempOldItem := FPendingObject; FPendingObject := nil; if Enabled or (Value = nil) then begin if Assigned(OwnerListview) and OwnerListview.HandleAllocated then begin // Make sure the hot track will end if Assigned(Value) then Mouse.Capture := OwnerListview.Handle else if Mouse.Capture = OwnerListview.Handle then Mouse.Capture := 0; // Cursor only works if no Window is captured OldCapture := Mouse.Capture; Mouse.Capture := 0; if Assigned(Value) then OwnerListview.Cursor := Cursor else OwnerListview.Cursor := crDefault; Mouse.Capture := OldCapture; end end; // PendingObject must be nil when this is executed // Always fire the event for custom hottracking if Assigned(TempOldItem) then TempOldItem.HotTracking[MousePos] := False; FPendingObject := Value; if Assigned(FPendingObject) then FPendingObject.HotTracking[MousePos] := True; end end; procedure TEasyHotTrackManager.SetPendingObjectCheck(const Value: TEasyCollectionItem); begin if Value <> FPendingObjectCheck then begin if Assigned(FPendingObjectCheck) then FPendingObjectCheck.CheckHovering := False; FPendingObjectCheck := Value; if Assigned(FPendingObjectCheck) then FPendingObjectCheck.CheckHovering := True; end end; { TEasyPaintInfoBaseColumn } constructor TEasyPaintInfoBaseColumn.Create(AnOwner: TCustomEasyListview); begin inherited; FColor := clBtnFace; FSortGlyphAlign := esgaRight; FSortGlyphIndent := 2; FHotTrack := True; FStyle := ehbsThick; FImagePosition := ehpLeft; FHilightFocusedColor := $00F7F7F7; end; procedure TEasyPaintInfoBaseColumn.SetColor(Value: TColor); begin if Value <> FColor then begin FColor := Value; OwnerListview.Header.Invalidate(False); end end; procedure TEasyPaintInfoBaseColumn.SetHilightFocused(const Value: Boolean); begin if FHilightFocused <> Value then begin FHilightFocused := Value; if Assigned(OwnerListview) then OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyPaintInfoBaseColumn.SetHilightFocusedColor(const Value: TColor); begin if FHilightFocusedColor <> Value then begin FHilightFocusedColor := Value; if Assigned(OwnerListview) then OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyPaintInfoBaseColumn.SetImagePosition(Value: TEasyHeaderImagePosition); begin if Value <> FImagePosition then begin FImagePosition := Value; OwnerListview.Header.Invalidate(False); end end; procedure TEasyPaintInfoBaseColumn.SetSortGlpyhAlign(Value: TEasySortGlyphAlign); begin if Value <> FSortGlyphAlign then begin FSortGlyphAlign := Value; OwnerListview.Header.Invalidate(False); end end; procedure TEasyPaintInfoBaseColumn.SetSortGlyphIndent(Value: Integer); begin if Value <> FSortGlyphIndent then begin FSortGlyphIndent := Value; OwnerListview.Header.Invalidate(False) end end; procedure TEasyPaintInfoBaseColumn.SetStyle(Value: TEasyHeaderButtonStyle); begin if Value <> FStyle then begin FStyle := Value; OwnerListview.Header.Invalidate(False) end end; { TEasyViewReportItem} function TEasyViewReportItem.AllowDrag(Item: TEasyItem; ViewportPoint: TPoint): Boolean; var RectArray: TEasyRectArrayObject; R: TRect; begin if FullRowSelect then begin ItemRectArray(Item, nil, OwnerListview.ScratchCanvas, Item.Caption, RectArray); UnionRect(R, RectArray.TextRect, RectArray.IconRect); if Item.Selected and Windows.PtInRect(R, ViewportPoint) then Result := True else Result := False end else Result := inherited AllowDrag(Item, ViewportPoint); end; function TEasyViewReportItem.CalculateDisplayRect(Item: TEasyItem; Column: TEasyColumn): TRect; begin Result := Item.DisplayRect; if Assigned(Column) then begin Result.Left := Column.DisplayRect.Left; Result.Right := Column.DisplayRect.Right; if Column.Position = 0 then Result.Left := Item.OwnerGroup.MarginLeft.RuntimeSize; if Column.Position = Column.OwnerColumns.Count - 1 then Result.Right := Result.Right - Item.OwnerGroup.MarginRight.RuntimeSize end end; function TEasyViewReportItem.ExpandTextR(Item: TEasyItem; RectArray: TEasyRectArrayObject; SelectType: TEasySelectHitType): TRect; begin Result := inherited ExpandTextR(Item, RectArray, SelectType); // If dragging and dropping only concider the basic ReportView item as the drop target. if FullRowSelect and not Assigned(OwnerListview.DragManager.DragItem) {and (SelectType = eshtClickselect)} then begin Result.Left := Item.OwnerGroup.MarginLeft.RunTimeSize; Result.Right := Item.DisplayRect.Right; end end; function TEasyViewReportItem.FullRowSelect: Boolean; begin Result := False; if Assigned(OwnerListview) then Result := OwnerListview.Selection.FullRowSelect end; function TEasyViewReportItem.PaintStateImage: Boolean; begin Result := True end; function TEasyViewReportItem.SelectionHit(Item: TEasyItem; SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; var R: TRect; RectArray: TEasyRectArrayObject; begin Result := False; if Item.Enabled and not IsRectEmpty(SelectViewportRect) then begin // Selection is always based on the first column ItemRectArray(Item, OwnerListview.Header.FirstColumn, OwnerListview.ScratchCanvas, '', RectArray); Result := IntersectRect(R, SelectViewportRect, ExpandTextR(Item, RectArray, SelectType)) or IntersectRect(R, SelectViewportRect, ExpandIconR(Item, RectArray, SelectType)) end end; function TEasyViewReportItem.SelectionHitPt(Item: TEasyItem; ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; var RectArray: TEasyRectArrayObject; begin Result := False; if Item.Enabled then begin // Selection is always based on the first column ItemRectArray(Item, OwnerListview.Header.FirstColumn, OwnerListview.ScratchCanvas, '', RectArray); Result := Windows.PtInRect(ExpandTextR(Item, RectArray, SelectType), ViewportPoint) or Windows.PtInRect(ExpandIconR(Item, RectArray, SelectType), ViewportPoint) end end; { TEasyHintWindow } constructor TEasyHintWindow.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.Create'); {$ENDIF GXDEBUG_HINT} end; destructor TEasyHintWindow.Destroy; begin {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.Destroy'); {$ENDIF GXDEBUG_HINT} inherited Destroy; end; procedure TEasyHintWindow.ActivateHint(ARect: TRect; const AHint: string); begin {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.ActivateHint'); {$ENDIF GXDEBUG_HINT} inherited; end; procedure TEasyHintWindow.ActivateHintData(ARect: TRect; const AHint: string; AData: Pointer); begin {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.ActivateHintData'); {$ENDIF GXDEBUG_HINT} inherited; end; function TEasyHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; var TextFlags: TCommonDrawTextWFlags; begin {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.CalcHintRect'); {$ENDIF GXDEBUG_HINT} // We passed in our HintInfo through the AData parameter HintInfo := PEasyHintInfoRec(AData); EasyHintInfo := HintInfo.Listview.HintInfo; EasyHintInfo.FCanvas := Canvas; EasyHintInfo.FHintType := HintInfo.HintType; EasyHintInfo.FText := HintInfo.HintStr; EasyHintInfo.FColor := HintInfo.HintColor; EasyHintInfo.FCursorPos := HintInfo.CursorPos; EasyHintInfo.FHideTimeout := HintInfo.HideTimeout; EasyHintInfo.FMaxWidth := HintInfo.HintMaxWidth; EasyHintInfo.FReshowTimeout := HintInfo.ReshowTimeout; EasyHintInfo.FWindowPos := HintInfo.HintPos; EasyHintInfo.FBounds := Rect(0, 0, MaxWidth, 0); HintInfo.Listview.DoHintCustomInfo(HintInfo.TargetObj, EasyHintInfo); HintInfo.HintStr := FEasyHintInfo.Text; HintInfo.HintType := EasyHintInfo.FHintType; HintInfo.HintColor := EasyHintInfo.FColor; HintInfo.CursorPos := EasyHintInfo.FCursorPos; HintInfo.HideTimeout := EasyHintInfo.FHideTimeout; HintInfo.HintMaxWidth := EasyHintInfo.FMaxWidth; HintInfo.ReshowTimeout := EasyHintInfo.FReshowTimeout; HintInfo.HintPos := EasyHintInfo.FWindowPos; if (HintInfo.HintType = ehtText) or (HintInfo.HintType = ehtToolTip) then begin case PEasyHintInfoRec( HintInfo)^.Listview.HintAlignment of taLeftJustify: TextFlags := [dtLeft, dtCalcRect, dtCalcRectAdjR, dtWordBreak]; taRightJustify: TextFlags := [dtRight, dtCalcRect, dtCalcRectAdjR, dtWordBreak]; taCenter: TextFlags := [dtCenter, dtCalcRect, dtCalcRectAdjR, dtWordBreak]; end; DrawTextWEx(Canvas.Handle, HintInfo.HintStr, EasyHintInfo.FBounds, TextFlags, -1); Inc(EasyHintInfo.FBounds.Right, 6); Inc(EasyHintInfo.FBounds.Bottom, 2) end; Result := EasyHintInfo.FBounds; end; function TEasyHintWindow.IsHintMsg(var Msg: TMsg): Boolean; begin {$IFDEF GXDEBUG_HINT} // SendDebug('TEasyHintWindow.IsHintMsg'); {$ENDIF GXDEBUG_HINT} Result := inherited IsHintMsg(Msg) end; procedure TEasyHintWindow.Paint; var TextFlags: TCommonDrawTextWFlags; R: TRect; begin {$IFDEF GXDEBUG_HINT} SendDebug('TEasyHintWindow.IsHintMsg'); {$ENDIF GXDEBUG_HINT} if HintInfo.HintType <> ehtCustomDraw then begin case PEasyHintInfoRec( HintInfo)^.Listview.HintAlignment of taLeftJustify: TextFlags := [dtLeft, dtVCenter]; taRightJustify: TextFlags := [dtRight, dtVCenter]; taCenter: TextFlags := [dtCenter, dtVCenter]; end; R := FEasyHintInfo.Bounds; InflateRect(R, -2, -2); DrawTextWEx(Canvas.Handle, HintInfo.HintStr, R, TextFlags, -1); end else begin R := ClientRect; InflateRect(R, -2, -2); HintInfo.Listview.DoHintCustomDraw(HintInfo.TargetObj, FEasyHintInfo) end end; { TEasySortManager } constructor TEasySortManager.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FAlgorithm := esaMergeSort; FSorter := TEasyMergeSort.Create(Self); end; destructor TEasySortManager.Destroy; begin FreeAndNil(FSorter); inherited Destroy; end; function TEasySortManager.CollectionSupportsInterfaceSorting(Collection: TEasyCollection): Boolean; var i: Integer; begin Result := True; i := 0; while (i < Collection.Count) and Result do begin Result := CommonSupports(Collection[i].DataInf, IEasyCompare); Inc(i) end end; procedure TEasySortManager.BeginUpdate; begin InterlockedIncrement(FUpdateCount); end; procedure TEasySortManager.EndUpdate; begin InterlockedDecrement(FUpdateCount); if (UpdateCount <= 0) and AutoSort then begin UpdateCount := 0; SortAll end end; procedure TEasySortManager.GroupItem(Item: TEasyItem; ColumnIndex: Integer; Key: LongWord); // // WARNING: Do not access the items OwnerListview property as it is an orphaned // item when it is passed to this method (the collection property is nil) // var i: Integer; Done, DefaultAction: Boolean; Groups: TEasyGroups; Group: TEasyGroup; begin i := 0; Done := False; Groups := OwnerListview.Groups; while not Done and (i < Groups.Count) do begin if Key = Groups[i].Key then begin Groups[i].Items.List.Add(Item); Item.FCollection := Groups[i].Items; Done := True; end; Inc(i) end; if not Done then begin Group := nil; DefaultAction := True; OwnerListview.DoAutoSortGroupCreate(Item, ColumnIndex, Groups, Group, DefaultAction); if DefaultAction then begin if Key > 0 then Group.Caption := UpperCase( WideChar(Key)) end; Group.Key := Key; Group.Items.List.Add(Item); Item.FCollection := Groups[i].Items; end end; procedure TEasySortManager.ReGroup(Column: TEasyColumn); var Groups: TEasyGroups; Item: TEasyItem; i, j, ColumnIndex, Index: Integer; Key: Integer; Caption: WideString; begin OwnerListview.BeginUpdate; try if Assigned(Column) then ColumnIndex := Column.Index else ColumnIndex := 0; // Move the items into a temporary storage structure Groups := OwnerListview.Groups; SetLength(FSortList, Groups.ItemCount); Index := 0; for i := 0 to Groups.Count - 1 do for j := 0 to Groups[i].ItemCount - 1 do begin Item := Groups[i][j]; if OwnerListview.Sort.AutoRegroup then begin SortList[Index].Key := $FFFF; OwnerListview.DoAutoGroupGetKey(Item, ColumnIndex, Groups, SortList[Index].Key); if SortList[Index].Key = $FFFF then begin Caption := Item.Caption; if Length(Caption) = 0 then SortList[Index].Key := 0 else SortList[Index].Key := Ord(WideLowerCase(Caption)[1]) end else Item.GroupKey[ColumnIndex] := SortList[Index].Key; end; SortList[Index].Item := Item; Item.FCollection := nil; // Orphan the item from the collection Groups[i].Item[j] := nil; Inc(Index) end; for i := 0 to Groups.Count - 1 do Groups[i].FItems.FList.Pack; // Clear the control of items Groups.Clear; for i := 0 to Length(SortList) - 1 do begin Item := TEasyItem( SortList[i].Item); Key := SortList[i].Key; GroupItem(Item, ColumnIndex, Key); end; OwnerListview.Sort.SortAll; finally // done with SortList SetLength(FSortList, 0); OwnerListview.EndUpdate(True) end end; procedure TEasySortManager.SetAlgorithm(Value: TEasySortAlgorithm); begin if FAlgorithm <> Value then begin FreeAndNil(FSorter); case Value of esaQuicksort: FSorter := TEasyQuicksort.Create(Self); esaBubbleSort: FSorter := TEasyBubbleSort.Create(Self); esaMergeSort: FSorter := TEasyMergeSort.Create(Self); end; FAlgorithm := Value end end; procedure TEasySortManager.SetAutoRegroup(Value: Boolean); begin if Value <> FAutoRegroup then begin OwnerListview.BeginUpdate; try OwnerListview.ShowGroupMargins := Value; FAutoRegroup := Value; ReGroup(OwnerListview.Selection.FocusedColumn); finally OwnerListview.EndUpdate(True); end end end; procedure TEasySortManager.SetAutoSort(Value: Boolean); begin if Value <> FAutoSort then begin FAutoSort := Value; if not Assigned(OwnerListview.Selection.FocusedColumn) then OwnerListview.Selection.FocusedColumn := OwnerListview.Header.FirstColumn; if Value then SortAll end end; procedure TEasySortManager.SortAll(Force: Boolean = False); var i: Integer; SupportsInterfaces: Boolean; begin if Assigned(Sorter) and Assigned(OwnerListview) and (({(OwnerListview.UpdateCount = 0) and} (UpdateCount = 0) and not LockoutSort) or Force) then begin SupportsInterfaces := CollectionSupportsInterfaceSorting(OwnerListview.Groups); Sorter.Sort(nil, OwnerListview.Groups, 0, OwnerListview.Groups.Count - 1, OwnerListview.DoGroupCompare, nil, SupportsInterfaces); for i := 0 to OwnerListview.Groups.Count - 1 do begin SupportsInterfaces := CollectionSupportsInterfaceSorting(OwnerListview.Groups[i].Items); Sorter.Sort(OwnerListview.GetSortColumn, OwnerListview.Groups[i].Items, 0, OwnerListview.Groups[i].ItemCount - 1, nil, OwnerListview.DoItemCompare, SupportsInterfaces); end; if not (egsRebuilding in OwnerListview.Groups.GroupsState) then OwnerListview.Groups.Rebuild(True) end end; { TEasyQuicksort} procedure TEasyQuicksort.Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); var I, J: Integer; P, Temp: TEasyCollectionItem; begin // Quicksort is not Stable, i.e. duplicate items may not be in the same // order with each pass of the sort. if Max > Collection.Count - 1 then Max := Collection.Count - 1; if Max > Min then begin repeat I := Min; J := Max; P := Collection.Items[(Min + Max) shr 1]; repeat if UseInterfaces then begin while (P.DataInf as IEasyCompare).Compare(Collection.Items[I].DataInf, Column) < 0 do Inc(I); while (P.DataInf as IEasyCompare).Compare(Collection.Items[J].DataInf, Column) > 0 do Dec(J); end else if Assigned(GroupCompare) then begin while GroupCompare(Column, TEasyGroup(Collection.Items[I]), TEasyGroup(P)) < 0 do Inc(I); while GroupCompare(Column, TEasyGroup(Collection.Items[J]), TEasyGroup(P)) > 0 do Dec(J); end else if Assigned(ItemCompare) then begin while ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[I]), TEasyItem(P)) < 0 do Inc(I); while ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[J]), TEasyItem(P)) > 0 do Dec(J); end else begin while DefaultSort(Column, Collection.Items[I], P) < 0 do Inc(I); while DefaultSort(Column, Collection.Items[J], P) > 0 do Dec(J); end; if I <= J then begin Temp := Collection.Items[I]; Collection.Items[I] := Collection.Items[J]; Collection.Items[J] := Temp; Inc(I); Dec(J); end; until I > J; if Min < J then Sort(Column, Collection, Min, J, GroupCompare, ItemCompare, UseInterfaces); Min := I; until I >= Max; end end; { TEasyBubbleSort} procedure TEasyBubbleSort.Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); var LastSwap, i, j, SortResult : Integer; Tmp: TEasyCollectionItem; begin // During this loop, min and max are the smallest and largest // indexes of items that might still be out of order. // Repeat until we are done. while (Min < Max) do begin // Bubble up. LastSwap := Min - 1; // for i := min + 1 to max i := min + 1; while (i <= Max) do begin // Find a bubble. if UseInterfaces then SortResult := (Collection.Items[i].DataInf as IEasyCompare).Compare(Collection.Items[i - 1].DataInf, Column) else if Assigned(GroupCompare) then SortResult := GroupCompare(Column, TEasyGroup(Collection.Items[i - 1]), TEasyGroup(Collection.Items[i])) else if Assigned(ItemCompare) then SortResult := ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[i - 1]), TEasyItem(Collection.Items[i])) else SortResult := DefaultSort(Column, Collection.Items[i - 1], Collection.Items[i]); if SortResult > 0 then begin // See where to drop the bubble. Tmp := Collection.Items[i - 1]; j := i; repeat Collection.Items[j - 1] := Collection.Items[j]; j := j + 1; if (j > max) then Break; if UseInterfaces then SortResult := (Tmp.DataInf as IEasyCompare).Compare(Collection.Items[j].DataInf, Column) else if Assigned(GroupCompare) then SortResult := GroupCompare(Column, TEasyGroup(Collection.Items[j]), TEasyGroup(Tmp)) else if Assigned(ItemCompare) then SortResult := ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[j]), TEasyItem(Tmp)) else SortResult := DefaultSort(Column, Collection.Items[j], Tmp); until SortResult >= 0; Collection.Items[j - 1] := Tmp; LastSwap := j - 1; i := j + 1; end else i := i + 1; end; // End bubbling up. // Update max. Max := LastSwap - 1; // Bubble down. LastSwap := Max + 1; // for i := max - 1 downto min i := Max - 1; while (i >= Min) do begin // Find a bubble. if UseInterfaces then SortResult := (Collection.Items[i].DataInf as IEasyCompare).Compare(Collection.Items[i + 1].DataInf, Column) else if Assigned(GroupCompare) then SortResult := GroupCompare(Column, TEasyGroup(Collection.Items[i + 1]), TEasyGroup(Collection.Items[i])) else if Assigned(ItemCompare) then SortResult := ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[i + 1]), TEasyItem(Collection.Items[i])) else SortResult := DefaultSort(Column, Collection.Items[i + 1], Collection.Items[i]); if SortResult < 0 then begin // See where to drop the bubble. Tmp := Collection.Items[i + 1]; j := i; repeat Collection.Items[j + 1] := Collection.Items[j]; j := j - 1; if j < Min then Break; if UseInterfaces then SortResult := (Tmp.DataInf as IEasyCompare).Compare(Collection.Items[j].DataInf, Column) else if Assigned(GroupCompare) then SortResult := GroupCompare(Column, TEasyGroup(Collection.Items[j]), TEasyGroup(Tmp)) else if Assigned(ItemCompare) then SortResult := ItemCompare(Column, TEasyItems(Collection).OwnerGroup, TEasyItem(Collection.Items[j]), TEasyItem(Tmp)) else SortResult := DefaultSort(Column, Collection.Items[j], Tmp); until SortResult <= 0; Collection.Items[j + 1] := Tmp; LastSwap := j + 1; i := j - 1; end else i := i - 1; end; // End bubbling down. // Update min. Min := LastSwap + 1; end; end; { TEasyMergeSort } function TEasyMergeSort.CompareDefault(i1, i2: TEasyCollectionItem): Boolean; begin Result := DefaultSort(Column, i1, i2) <= 0; end; function TEasyMergeSort.CompareGroup(i1, i2: TEasyCollectionItem): Boolean; begin Result := GroupCompareFunc(Column, TEasyGroup(i1), TEasyGroup(i2)) <= 0; end; function TEasyMergeSort.CompareInterfaces(i1, i2: TEasyCollectionItem): Boolean; begin Result:=(i2.DataInf as IEasyCompare).Compare(i1.DataInf, Column) <= 0; end; function TEasyMergeSort.CompareItem(i1, i2: TEasyCollectionItem): Boolean; begin Result := ItemCompareFunc(Column, OwnerGroup, TEasyItem(i1), TEasyItem(i2)) <= 0; end; procedure TEasyMergeSort.Sort(Column: TEasyColumn; Collection: TEasyCollection; Min, Max: Integer; GroupCompare: TEasyDoGroupCompare; ItemCompare: TEasyDoItemCompare; UseInterfaces: Boolean); type TEasyMergeSortCompare=function (i1, i2: TEasyCollectionItem): Boolean of object; var CompareFunc: TEasyMergeSortCompare; procedure subMerge(dst: TEasyCollection; ld, md, hd: Integer; src: TEasyCollection; ls, ms: Integer); { dst src hd aa md ms xx bb bb+aa->xxaa ld ls } var i, j, d: Integer; begin i := ls; j := md; d := ld; while i< ms do begin if (j = hd) or (compareFunc(src[i], dst[j])) then begin dst[d] := src[i]; Inc(i); end else begin dst[d] := dst[j]; Inc(j); end; Inc(d); end; end; procedure subSortM(dst: TEasyCollection; ld, hd: Integer; src: TEasyCollection; ls, hs: Integer); forward; procedure subSortI(dst: TEasyCollection; ld, hd: Integer; tmp: TEasyCollection; lt, ht: Integer); var m2: Integer; //I for Inplace x3: Pointer; { - hd | A inplace AA->AA m2 A ht move bbb->ccc b c merge ccc+AA->bbbAA b c ld b lt c ht-lt>=hd-m2-ld ! } begin if (hd >= ld + 3) then begin m2 := (hd - ld) div 2; subSortI(dst, hd-m2, hd, tmp, lt, lt + m2); //sort random AA->sorted AA, using cc as scratchpad subSortM(tmp, lt, lt+(hd-ld-m2), dst, ld, hd -m2); //sort random bbb->sorted ccc subMerge(dst, ld, hd - m2, hd, tmp, lt, lt + (hd - ld - m2)); //merge sorted ccc+sorted AA->bbbAA end else if (hd = ld + 2) then begin if not compareFunc(dst[ld], dst[ld + 1]) then begin x3 := dst[ld]; dst[ld] := dst[ld + 1]; dst[ld + 1] := x3; end; end; end; procedure subSortM(dst: TEasyCollection; ld, hd: Integer; src: TEasyCollection; ls, hs: Integer); var m2: Integer; //M for Move { hd hs hd hs c A c b c A c b m2 c a m2 c A d b d a ld d ls b ld d ls a } begin if (hs >= ls + 3) then begin m2 := (hs - ls) div 2; subSortM(dst, ld +m2, hd, src, ls + m2, hs); //sort random aAA->sorted ccc subSortI(src, ls, ls + m2, dst, ld, ld + m2); //sort random bb->sorted bb, using dd as scratchpad subMerge(dst, ld, ld + m2, hd, src, ls, ls + m2); //merge bb+ccc->ddccc end else if (hs = ls + 2) then begin if not compareFunc(src[ls], src[ls+1]) then begin dst[ld] := src[ls + 1]; dst[ld+1] := src[ls]; end else begin dst[ld] := src[ls]; dst[ld + 1] := src[ls + 1]; end end else if (hs = ls + 1) then dst[ld] := src[ls]; end; var m: Integer; TempList: TEasyCollection; begin if Max > Collection.Count - 1 then Max := Collection.Count - 1; if (Max <= Min) then Exit; Self.Column := Column; OwnerGroup := TEasyItems(Collection).OwnerGroup; GroupCompareFunc := GroupCompare; ItemCompareFunc := ItemCompare; TempList := TEasyCollection.Create(nil); m:=(Max - Min + 2) div 2; TempList.List.Capacity := m; TempList.List.Count := m; if (UseInterfaces) then CompareFunc := CompareInterfaces else if Assigned(GroupCompareFunc) then CompareFunc := CompareGroup else if Assigned(ItemCompareFunc) then CompareFunc := CompareItem else CompareFunc := CompareDefault; subSortI(Collection, Min, Max + 1, TempList, Min, (Min + Max + 2) div 2); TempList.List.Count := 0; TempList.List.Capacity := 0; FreeAndNil(TempList); end; { TEasyStringEditor } function TEasyBaseEditor.AcceptEdit: Boolean; var WS: Variant; begin Result := True; WS := GetText; Listview.DoItemEdited(Item, WS, Result); if Result then begin if Assigned(EditColumn) then Item.Captions[EditColumn.Index] := WS else Item.Caption := WS; Listview.EditManager.EndEdit end end; function TEasyBaseEditor.GetEditor: TWinControl; begin Result := FEditor; end; function TEasyBaseEditor.GetEditorColor: TColor; begin Result := Listview.EditManager.Color end; function TEasyBaseEditor.GetHandle: HWnd; begin if Assigned(FEditor) and (FEditor.HandleAllocated) then Result := FEditor.Handle else Result := 0; end; function TEasyBaseEditor.GetListview: TCustomEasyListview; begin Result := nil; if Assigned(Item) then Result := Item.OwnerListview end; function TEasyBaseEditor.GetModified: Boolean; begin Result := Modified end; function TEasyBaseEditor.PtInEditControl(WindowPt: TPoint): Boolean; begin Result := PtInRect(Editor.BoundsRect, WindowPt) end; procedure TEasyBaseEditor.ControlWndHookProc(var Message: TMessage); // // Window procedure hook for the Edit box, allows autosizing of edit during user // input // var Menu: TPopupMenu; begin case Message.Msg of WM_EDITORRESIZE: begin ResizeEditor; end; WM_CHAR: begin if Message.WParam = VK_TAB then Message.WParam := Ord(' '); end; WM_CONTEXTMENU: begin Menu := nil; Listview.DoItemGetEditMenu(Self, Menu); if Assigned(Menu) then Menu.Popup(LOWORD(Message.LParam), HIWORD(Message.LParam)) else // Don't let the VCL hook the parent window background menu to the editor CallWindowProc(TWinControlHack(Editor).DefWndProc, Editor.Handle, Message.Msg, Message.wParam, Message.lParam); Message.Result := 1; end; end; FOldWndProc(Message) end; function TEasyBaseEditor.EditText(Item: TEasyItem; Column: TEasyColumn): WideString; begin Result := ''; Item.OwnerListview.DoItemGetEditCaption(Item, Column, Result); if Result = '' then begin if Assigned(Column) then Result := Item.Captions[Column.Index] else Result := Item.Caption end end; procedure TEasyBaseEditor.Finalize; begin EditColumn := nil; // Only unhook if it is our hook if EqualWndMethod(Editor.WindowProc, ControlWndHookProc) then Editor.WindowProc := OldWndProc; FreeAndNil(FEditor) end; procedure TEasyBaseEditor.Hide; begin Editor.Visible := False end; procedure TEasyBaseEditor.Initialize(AnItem: TEasyItem; Column: TEasyColumn); begin FItem := AnItem; FEditColumn := Column; CreateEditor(FEditor, Column, Listview); Editor.Visible := False; OldWndProc := Editor.WindowProc; Editor.WindowProc := ControlWndHookProc; Editor.DoubleBuffered := True; TWinControlHack( Editor).Color := GetEditorColor; GetEditorFont.Assign(Listview.EditManager.Font); Item.ItemRectArray(Column, AnItem.OwnerListview.ScratchCanvas, FRectArray); ResizeEditor; SetWindowLong(Editor.Handle, GWL_EXSTYLE, GetWindowLong(Editor.Handle, GWL_EXSTYLE) or WS_EX_TOPMOST); end; procedure TEasyBaseEditor.ResizeEditor; var R: TRect; begin CalculateEditorRect(GetText, R); Editor.SetBounds(R.Left, R.Top, RectWidth(R), RectHeight(R)); end; procedure TEasyBaseEditor.SetEditor(const Value: TWinControl); begin FEditor := Value; end; procedure TEasyBaseEditor.SetEditorFocus; begin Editor.SetFocus; end; procedure TEasyBaseEditor.Show; begin Editor.Visible := True; end; { TEasySelectionGroupList } constructor TEasySelectionGroupList.Create; begin FList := TList.Create end; destructor TEasySelectionGroupList.Destroy; begin FreeAndNil(FList); inherited end; function TEasySelectionGroupList.Count: Integer; begin Result := List.Count end; function TEasySelectionGroupList.GetItems(Index: Integer): TEasyItem; begin Result := TEasyItem( List.Items[Index]) end; procedure TEasySelectionGroupList.Add(Item: TEasyItem); begin List.Add(Item) end; procedure TEasySelectionGroupList.Clear; begin List.Clear end; procedure TEasySelectionGroupList.DecRef; begin Dec(FRefCount); if FRefCount = 0 then Destroy end; procedure TEasySelectionGroupList.IncRef; begin Inc(FRefCount) end; procedure TEasySelectionGroupList.SetItems(Index: Integer; Value: TEasyItem); begin List.Items[Index] := Value end; function TEasyGridIconGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.Icon end; procedure TEasyGridIconGroup.AutoSizeCells; begin // Do nothing end; procedure TEasyGridIconGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.Icon.Assign(Value) end; function TEasyGridSmallIconGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.SmallIcon end; procedure TEasyGridSmallIconGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.SmallIcon.Assign(Value) end; function TEasyGridThumbnailGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.Thumbnail end; procedure TEasyGridThumbnailGroup.AutoSizeCells; begin // Do nothing end; procedure TEasyGridThumbnailGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.Thumbnail.Assign(Value) end; { TEasyGridTileGroup} procedure TEasyGridTileGroup.FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); begin end; function TEasyGridTileGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.Tile end; procedure TEasyGridTileGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.Tile.Assign(Value) end; { TEasyItemInterfaced} function TEasyItemInterfaced.ExtractObject: TObject; begin if Supports(DataInf, ICommonExtractObj) then Result := (DataInf as ICommonExtractObj).Obj else Result := nil end; function TEasyItemInterfaced.GetCaptions(Column: Integer): Widestring; var CaptionInf: IEasyCaptions; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptions, CaptionInf) then Result := CaptionInf.Captions[Column] end; function TEasyItemInterfaced.GetChecked: Boolean; var Checks: IEasyChecks; begin Result := False; Checks := nil; if Supports(DataInf, IEasyChecks, Checks) then Result := Checks.GetChecked(0) end; function TEasyItemInterfaced.GetCommonImageIndex(Column: Integer; Kind: TEasyImageKind): TCommonImageIndexInteger; var ImageInf: IEasyImages; begin Result := -1; ImageInf := nil; if Supports(DataInf, IEasyImages, ImageInf) then Result := ImageInf.ImageIndexes[Column, Kind] end; function TEasyItemInterfaced.GetDetailCount: Integer; var TileInf: IEasyDetails; begin Result := 1; TileInf := nil; if Supports(DataInf, IEasyDetails, TileInf) then Result := TileInf.GetDetailCount end; function TEasyItemInterfaced.GetDetails(Line: Integer): Integer; var TileInf: IEasyDetails; begin Result := 0; TileInf := nil; if Supports(DataInf, IEasyDetails, TileInf) then Result := TileInf.Detail[Line] end; function TEasyItemInterfaced.GetGroupKey(FocusedColumn: Integer): LongWord; var KeyInf: IEasyGroupKey; begin Result := 0; KeyInf := nil; if Supports(DataInf, IEasyGroupKey, KeyInf) then Result := KeyInf.Key[FocusedColumn] end; function TEasyItemInterfaced.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := GetCommonImageIndex(Column, eikNormal); end; function TEasyItemInterfaced.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; var ImageList: IEasyImageList; begin Result := nil; if Supports(DataInf, IEasyImageList, ImageList) then Result := ImageList.ImageList[Column, IconSize]; if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyItemInterfaced.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := GetCommonImageIndex(Column, eikOverlay); end; function TEasyItemInterfaced.GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := GetCommonImageIndex(Column, eikState); end; function TEasyItemInterfaced.GetStateImageList(Column: Integer): TCustomImageList; var ImageList: IEasyStateImageList; begin Result := nil; if Supports(DataInf, IEasyStateImageList, ImageList) then Result := ImageList.ImageList[Column]; if not Assigned(Result) then Result := DefaultStateImageList end; procedure TEasyItemInterfaced.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.DrawImage(Column, ACanvas, RectArray, AlphaBlender) end; procedure TEasyItemInterfaced.ImageDrawGetSize(Column: TEasyColumn; var ImageW, ImageH: Integer); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.GetSize(Column, ImageW, ImageH) end; procedure TEasyItemInterfaced.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); var ImageInf: IEasyCustomImage; begin IsCustom := False; if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.CustomDrawn(Column, IsCustom) end; procedure TEasyItemInterfaced.SetCaptions(Column: Integer; Value: Widestring); var CaptionInf: IEasyCaptionsEditable; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptionsEditable, CaptionInf) then begin CaptionInf.SetCaption(Column, Value); Invalidate(False) end end; procedure TEasyItemInterfaced.SetChecked(Value: Boolean); var Checks: IEasyChecks; begin Checks := nil; if Supports(DataInf, IEasyChecks, Checks) then begin Checks.SetChecked(0, Value); Invalidate(False) end end; procedure TEasyItemInterfaced.SetCommonImageIndex(Column: Integer; Kind: TEasyImageKind; Value: TCommonImageIndexInteger); var ImageInf: IEasyImagesEditable; begin ImageInf := nil; if Supports(DataInf, IEasyImagesEditable, ImageInf) then ImageInf.SetImageIndex(Column, Kind, Value) end; procedure TEasyItemInterfaced.SetDetailCount(Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.DetailCount := Value; Invalidate(False) end end; procedure TEasyItemInterfaced.SetDetails(Line: Integer; Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.Detail[Line] := Value; Invalidate(False) end end; procedure TEasyItemInterfaced.SetGroupKey(FocusedColumn: Integer; Value: LongWord); var KeyInf: IEasyGroupKeyEditable; begin KeyInf := nil; if Supports(DataInf, IEasyGroupKeyEditable, KeyInf) then KeyInf.Key[FocusedColumn] := Value; end; procedure TEasyItemInterfaced.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin SetCommonImageIndex(Column, eikNormal, Value) end; procedure TEasyItemInterfaced.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin SetCommonImageIndex(Column, eikOverlay, Value) end; procedure TEasyItemInterfaced.SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin SetCommonImageIndex(Column, eikState, Value) end; procedure TEasyItemInterfaced.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); var ThumbInf: IEasyThumbnail; begin if Supports(DataInf, IEasyThumbnail, ThumbInf) then ThumbInf.ThumbnailDraw(ACanvas, ARect, AlphaBlender, DoDefault) end; { TEasyItem } constructor TEasyItem.Create(ACollection: TEasyCollection); begin inherited Create(ACollection); FVisibleIndexInGroup := -1; end; destructor TEasyItem.Destroy; begin SetDestroyFlags; if Assigned(OwnerListview) then begin if OwnerListview.DragManager.DropTarget = Self then OwnerListview.DragManager.FDropTarget := nil; if OwnerListview.EditManager.TabMoveFocusItem = Self then OwnerListview.EditManager.TabMoveFocusItem := nil; if OwnerListview.Selection.AnchorItem = Self then OwnerListview.Selection.AnchorItem := nil; if OwnerListview.Selection.FocusedItem = Self then OwnerListview.Selection.FocusedItem := nil; if OwnerListview.IncrementalSearch.SearchItem = Self then OwnerListview.IncrementalSearch.SearchItem := nil; if OwnerListview.IncrementalSearch.NextSearchItem = Self then OwnerListview.IncrementalSearch.NextSearchItem := nil; end; Visible := False; // will UnSelect and UnFocus if necessary inherited; ReleaseSelectionGroup; FreeAndNil(FView); end; function TEasyItem.AllowDrag(ViewportPt: TPoint): Boolean; begin Result := View.AllowDrag(Self, ViewportPt) end; function TEasyItem.CanChangeBold(NewValue: Boolean): Boolean; begin Result := True end; function TEasyItem.CanChangeCheck(NewValue: Boolean): Boolean; begin if Enabled then begin Result := True; OwnerListview.DoItemCheckChanging(Self, Result); end else Result := False; end; function TEasyItem.CanChangeEnable(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoItemEnableChanging(Self, Result) end; function TEasyItem.CanChangeFocus(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoItemFocusChanging(Self, Result) end; function TEasyItem.CanChangeHotTracking(NewValue: Boolean): Boolean; begin Result := True end; function TEasyItem.CanChangeSelection(NewValue: Boolean): Boolean; begin Result := True; OwnerListview.DoItemSelectionChanging(Self, Result) end; function TEasyItem.CanChangeVisibility(NewValue: Boolean): Boolean; begin if OwnerGroup.Visible or not NewValue then begin Result := True; OwnerListview.DoItemVisibilityChanging(Self, Result); end else Result := False end; function TEasyItem.DefaultStateImageList: TCustomImageList; begin Result := OwnerListview.ImagesState end; function TEasyItem.EditAreaHitPt(ViewportPoint: TPoint): Boolean; // Returns true if the passed point is in an area where the Item conciders it a // place where inplace editing can be activated. // begin Result := View.EditAreaHitPt(Self, ViewportPoint) end; function TEasyItem.GetColumnPos: Integer; // // Returns the current column that the item is in within the grid or -1 if it // is not visible // begin Result := -1; if Visible then Result := VisibleIndexInGroup mod OwnerGroup.Grid.ColumnCount end; function TEasyItem.GetDefaultViewClass: TEasyViewItemClass; begin Result := TEasyViewItem; if Assigned(OwnerListview) then begin case OwnerListview.View of elsIcon: Result := TEasyViewIconItem; elsSmallIcon: Result := TEasyViewSmallIconItem; elsList: Result := TEasyViewListItem; elsReport: Result := TEasyViewReportItem; elsThumbnail: Result := TEasyViewThumbnailItem; elsTile: Result := TEasyViewTileItem; elsFilmStrip: Result := TEasyViewFilmStripItem; elsGrid: Result := TEasyViewGridItem; end end end; function TEasyItem.GetGroupKey(FocusedColumn: Integer): LongWord; begin Result := 0 end; function TEasyItem.GetIndex: Integer; begin Result := FIndex end; function TEasyItem.GetOwnerGroup: TEasyGroup; begin Result := OwnerItems.OwnerGroup end; function TEasyItem.GetOwnerItems: TEasyItems; begin Result := TEasyItems(Collection) end; function TEasyItem.GetPaintInfo: TEasyPaintInfoItem; begin Result := TEasyPaintInfoItem( inherited PaintInfo) end; function TEasyItem.GetRowPos: Integer; // // Returns the current column that the item is in within the grid or -1 if it // is not visible // begin Result := -1; if Visible then Result := VisibleIndexInGroup mod OwnerGroup.Grid.RowCount end; function TEasyItem.GetStateImageIndex: TCommonImageIndexInteger; begin Result := GetStateImageIndexes(0) end; function TEasyItem.GetView: TEasyViewItem; begin if Assigned(FView) then begin if FView.ClassType <> ViewClass then FreeAndNil(FView); end; if not Assigned(FView) then FView := ViewClass.Create(OwnerGroup); Result := FView end; function TEasyItem.GetViewClass: TEasyViewItemClass; begin Result := nil; if Assigned(OwnerListview) then OwnerListview.DoItemCustomView(Self, OwnerListview.View, Result); if not Assigned(Result) then Result := GetDefaultViewClass; end; function TEasyItem.HitTestAt(ViewportPoint: TPoint; var HitInfo: TEasyItemHitTestInfoSet): Boolean; var RectArray: TEasyRectArrayObject; R: TRect; begin HitInfo := []; ItemRectArray(OwnerListview.Header.FirstColumn, OwnerListview.ScratchCanvas, RectArray); R := RectArray.IconRect; // Make the blank area between the image and text part of the image if OwnerListview.IsVertView then R.Bottom := R.Bottom + OwnerListview.PaintInfoItem.CaptionIndent else R.Right := R.Right + OwnerListview.PaintInfoItem.CaptionIndent; if PtInRect(R, ViewportPoint) then Include(HitInfo, ehtOnIcon); if PtInRect(RectArray.CheckRect, ViewportPoint) then Include(HitInfo, ehtOnCheck); if PtInRect(RectArray.FullFocusSelRect, ViewportPoint) then Include(HitInfo, ehtOnText); if PtInRect(RectArray.LabelRect, ViewportPoint) then Include(HitInfo, ehtOnLabel); if PtInRect(RectArray.ClickselectBoundsRect, ViewportPoint) then Include(HitInfo, ehtOnClickselectBounds); if PtInRect(RectArray.DragSelectBoundsRect, ViewportPoint) then Include(HitInfo, ehtOnDragSelectBounds); if PtInRect(RectArray.DragSelectBoundsRect, ViewportPoint) then Include(HitInfo, ehtOnDragSelectBounds); if PtInRect(RectArray.StateRect, ViewportPoint) then Include(HitInfo, ehtStateIcon); Result := HitInfo <> []; end; function TEasyItem.LocalPaintInfo: TEasyPaintInfoBasic; begin Result := OwnerListview.PaintInfoItem end; function TEasyItem.SelectionHit(SelectViewportRect: TRect; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHit(Self, SelectViewportRect, SelectType) end; function TEasyItem.SelectionHitPt(ViewportPoint: TPoint; SelectType: TEasySelectHitType): Boolean; begin Result := View.SelectionHitPt(Self, ViewportPoint, SelectType) end; procedure TEasyItem.Edit(Column: TEasyColumn = nil); begin OwnerListview.EditManager.BeginEdit(Self, Column) end; procedure TEasyItem.Freeing; begin OwnerListview.DoItemFreeing(Self) end; procedure TEasyItem.GainingBold; begin Invalidate(False) end; procedure TEasyItem.GainingCheck; begin Inc(OwnerListview.CheckManager.FCount); OwnerListview.DoItemCheckChanged(Self); Invalidate(False); end; procedure TEasyItem.GainingEnable; begin OwnerListview.DoItemEnableChanged(Self); Invalidate(False); end; procedure TEasyItem.GainingFocus; begin OwnerListview.DoItemFocusChanged(Self); OwnerListview.Selection.FocusedItem := Self; Invalidate(False); if OwnerListview.Selection.GroupSelections then begin OwnerListview.Selection.BuildSelectionGroupings(False); OwnerListview.SafeInvalidateRect(nil, False); end end; procedure TEasyItem.GainingGhosted; begin // OwnerListview.DoItemCheckChanged(Self); if State * [esosDestroying] = [] then Invalidate(False); end; procedure TEasyItem.GainingHilight; begin Invalidate(True); end; procedure TEasyItem.GainingHotTracking(MousePos: TPoint); begin OwnerListview.DoItemHotTrack(Self, ehsEnable, MousePos); Invalidate(True) end; procedure TEasyItem.GainingSelection; begin OwnerListview.Selection.GainingSelection(Self); OwnerListview.DoItemSelectionChanged(Self); if OwnerListview.Selection.GroupSelections then begin OwnerListview.Selection.BuildSelectionGroupings(False); OwnerListview.SafeInvalidateRect(nil, False); end else Invalidate(False); end; procedure TEasyItem.GainingVisibility; begin // Inc(OwnerGroup.FVisibleCount); OwnerListview.Groups.Rebuild; OwnerListview.DoItemVisibilityChanged(Self); end; procedure TEasyItem.Initialize; begin OwnerListview.DoItemInitialize(Self); Include(FState, esosInitialized); end; procedure TEasyItem.Invalidate(ImmediateUpdate: Boolean); var RectArray: TEasyRectArrayObject; R: TRect; Listview: TCustomEasyListview; begin Listview := TEasyCollection( Collection).FOwnerListview; if Listview.HandleAllocated then begin R := Listview.Scrollbars.MapWindowRectToViewRect(Listview.ClientRect, True); // This is a bit odd as a long text caption is scrolled off the top of the window if IntersectRect(R, R, DisplayRect) then begin View.ItemRectArray(Self, nil, OwnerListview.ScratchCanvas, '', RectArray); UnionRect(R, RectArray.FocusChangeInvalidRect, DisplayRect); R := Listview.Scrollbars.MapViewRectToWindowRect(R, True); Listview.SafeInvalidateRect(@R, ImmediateUpdate); end end end; procedure TEasyItem.ItemRectArray(Column: TEasyColumn; ACanvas: TCanvas; var RectArray: TEasyRectArrayObject); begin if Assigned(View) then View.ItemRectArray(Self, Column, ACanvas, '', RectArray) else FillChar(RectArray, SizeOf(RectArray), #0) end; procedure TEasyItem.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); OwnerListview.DoItemLoadFromStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyItem.LosingBold; begin Invalidate(False) end; procedure TEasyItem.LosingCheck; begin Dec(OwnerListview.CheckManager.FCount); OwnerListview.DoItemCheckChanged(Self); if State * [esosDestroying] = [] then Invalidate(False); end; procedure TEasyItem.LosingEnable; begin ReleaseSelectionGroup; OwnerListview.DoItemEnableChanged(Self); if State * [esosDestroying] = [] then Invalidate(False); end; procedure TEasyItem.LosingFocus; begin if OwnerListview.Selection.FocusedItem = Self then OwnerListview.Selection.FocusedItem := nil; OwnerListview.DoItemFocusChanged(Self); // Need to repaint before Losing the focus if State * [esosDestroying] = [] then begin Include(FState, esosFocused); Invalidate(False); Exclude(FState, esosFocused); if OwnerListview.Selection.GroupSelections then OwnerListview.SafeInvalidateRect(nil, False); end; end; procedure TEasyItem.LosingGhosted; begin // OwnerListview.DoItemCheckChanged(Self); if State * [esosDestroying] = [] then Invalidate(False); end; procedure TEasyItem.LosingHilight; begin Invalidate(True); end; procedure TEasyItem.LosingHotTracking; begin OwnerListview.DoItemHotTrack(Self, ehsDisable, Point(0, 0)); Invalidate(True) end; procedure TEasyItem.LosingSelection; begin OwnerListview.Selection.LosingSelection(Self); OwnerListview.DoItemSelectionChanged(Self); // Need to repaint before Losing the focus if State * [esosDestroying] = [] then begin if OwnerListview.Selection.GroupSelections then begin OwnerListview.Selection.BuildSelectionGroupings(False); OwnerListview.SafeInvalidateRect(nil, False); end else Invalidate(False); end end; procedure TEasyItem.LosingVisibility; begin // Dec(OwnerGroup.FVisibleCount); ReleaseSelectionGroup; OwnerListview.Groups.Rebuild; OwnerListview.DoItemVisibilityChanged(Self); end; procedure TEasyItem.MakeVisible(Position: TEasyMakeVisiblePos); var RectArray: TEasyRectArrayObject; R: TRect; begin if Visible then begin View.ItemRectArray(Self, OwnerListview.Header.FirstVisibleColumn, OwnerListview.ScratchCanvas, '', RectArray); R := RectArray.BoundsRect; // UnionRect(R, RectArray.FullFocusSelRect, RectArray.IconRect); // WL, 01/10/05: bottom line of focus rect was missing if item was made visible at the bottom of the window // InflateRect(R, H_STRINGEDITORMARGIN div 2, V_STRINGEDITORMARGIN div 2); if not ContainsRect(OwnerListview.ClientInViewportCoords, R) then begin case Position of emvTop: begin OwnerListview.Scrollbars.OffsetY := R.Top; OwnerListview.Scrollbars.OffsetX := R.Left; end; emvMiddle: begin OwnerListview.Scrollbars.OffsetY := R.Top + OwnerListview.ClientHeight div 2; OwnerListview.Scrollbars.OffsetX := R.Left + OwnerListview.ClientWidth div 2; end; emvBottom: begin OwnerListview.Scrollbars.OffsetY := R.Bottom - OwnerListview.ClientHeight + OwnerListview.Header.RuntimeHeight; OwnerListview.Scrollbars.OffsetX := R.Right - OwnerListview.ClientWidth; end; emvAuto: begin if R.Bottom > OwnerListview.ClientInViewportCoords.Bottom then OwnerListview.Scrollbars.OffsetY := R.Bottom - OwnerListview.ClientHeight + OwnerListview.Header.RuntimeHeight else if R.Top < OwnerListview.ClientInViewportCoords.Top then OwnerListview.Scrollbars.OffsetY := R.Top; if R.Right > OwnerListview.ClientInViewportCoords.Right then OwnerListview.Scrollbars.OffsetX := R.Left else if R.Left < OwnerListview.ClientInViewportCoords.Left then OwnerListview.Scrollbars.OffsetX := R.Left; end end end end end; procedure TEasyItem.Paint(ACanvas: TCanvas; ViewportClipRect: TRect; Column: TEasyColumn; ForceSelectionRectDraw: Boolean); begin View.Paint(Self, Column, ACanvas, ViewportClipRect, ForceSelectionRectDraw) end; procedure TEasyItem.ReleaseSelectionGroup; var Temp: TEasySelectionGroupList; begin if Assigned(FSelectionGroup) then begin Temp := FSelectionGroup; FSelectionGroup := nil; Temp.DecRef end end; procedure TEasyItem.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); OwnerListview.DoItemSaveToStream(Self, S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyItem.SetGroupKey(FocusedColumn: Integer; Value: LongWord); begin end; procedure TEasyItem.SetPaintInfo(const Value: TEasyPaintInfoItem); begin inherited PaintInfo := Value end; procedure TEasyItem.SetSelectionGroup(Value: TEasySelectionGroupList); begin if Value <> FSelectionGroup then begin if Assigned(FSelectionGroup) then FSelectionGroup.DecRef; FSelectionGroup := Value end end; procedure TEasyItem.SetStateImageIndex(const Value: TCommonImageIndexInteger); begin SetStateImageIndexes(0, Value) end; { TEasyItemVirtual} function TEasyItemVirtual.GetCaptions(Column: Integer): Widestring; begin Result := ''; OwnerListview.DoItemGetCaption(Self, Column, Result) end; function TEasyItemVirtual.GetDetailCount: Integer; begin Result := 0; OwnerListview.DoItemGetTileDetailCount(Self, Result) end; function TEasyItemVirtual.GetDetails(Line: Integer): Integer; begin Result := 0; OwnerListview.DoItemGetTileDetail(Self, Line, Result) end; function TEasyItemVirtual.GetGroupKey(FocusedColumn: Integer): LongWord; begin Result := 0; OwnerListview.DoItemGetGroupKey(Self, FocusedColumn, Result) end; function TEasyItemVirtual.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoItemGetImageIndex(Self, Column, eikNormal, Result) end; function TEasyItemVirtual.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := nil; OwnerListview.DoItemGetImageList(Self, Column, Result); if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyItemVirtual.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoItemGetImageIndex(Self, Column, eikOverlay, Result) end; function TEasyItemVirtual.GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoItemGetImageIndex(Self, Column, eikState, Result) end; function TEasyItemVirtual.GetStateImageList(Column: Integer): TCustomImageList; begin Result := nil; OwnerListview.DoItemGetStateImageList(Self, Column, Result); if not Assigned(Result) then Result := DefaultStateImageList end; procedure TEasyItemVirtual.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoItemImageDrawIsCustom(Column, Self, IsCustom) end; procedure TEasyItemVirtual.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoItemImageDraw(Self, Column, ACanvas, RectArray, AlphaBlender) end; procedure TEasyItemVirtual.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoItemImageGetSize(Self, Column, ImageW, ImageH) end; procedure TEasyItemVirtual.SetCaptions(Column: Integer; Value: Widestring); begin OwnerListview.DoItemSetCaption(Self, Column, Value); Invalidate(False) end; procedure TEasyItemVirtual.SetDetailCount(Value: Integer); begin OwnerListview.DoItemSetTileDetailCount(Self, Value); Invalidate(False) end; procedure TEasyItemVirtual.SetDetails(Line: Integer; Value: Integer); begin OwnerListview.DoItemSetTileDetail(Self, Line, Value); Invalidate(False) end; procedure TEasyItemVirtual.SetGroupKey(FocusedColumn: Integer; Value: LongWord); begin OwnerListview.DoItemSetGroupKey(Self, FocusedColumn, Value); end; procedure TEasyItemVirtual.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoItemSetImageIndex(Self, Column, eikNormal, Value); Invalidate(False) end; procedure TEasyItemVirtual.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoItemSetImageIndex(Self, Column, eikOverlay, Value); Invalidate(False) end; procedure TEasyItemVirtual.SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoItemSetImageIndex(Self, Column, eikState, Value); Invalidate(False) end; procedure TEasyItemVirtual.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin OwnerListview.DoItemThumbnailDraw(Self, ACanvas, ARect, AlphaBlender, DoDefault) end; { TEasyItemStored } constructor TEasyItemStored.Create(ACollection: TEasyCollection); begin inherited Create(ACollection); FDataHelper := TEasyItemDynamicDataHelper.Create; end; destructor TEasyItemStored.Destroy; begin SetDestroyFlags; inherited Destroy; FreeAndNil(FDataHelper); end; function TEasyItemStored.GetCaptions(Column: Integer): Widestring; begin Result := ''; if Assigned(DataHelper) then Result := DataHelper.Captions[Column] end; function TEasyItemStored.GetDetailCount: Integer; begin Result := OwnerListview.PaintInfoItem.TileDetailCount end; function TEasyItemStored.GetDetails(Line: Integer): Integer; begin Result := 0; if Assigned(DataHelper) then Result := DataHelper.Details[Line] end; function TEasyItemStored.GetGroupKey(FocusedColumn: Integer): LongWord; begin Result := 0; if Assigned(DataHelper) then Result := DataHelper.GroupKey[FocusedColumn] end; function TEasyItemStored.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; if Assigned(DataHelper) then Result := DataHelper.ImageIndexes[Column] end; function TEasyItemStored.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := DefaultImageList(IconSize) end; function TEasyItemStored.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; if Assigned(DataHelper) then Result := DataHelper.ImageOverlayIndexes[Column] end; function TEasyItemStored.GetStateImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; if Assigned(DataHelper) then Result := DataHelper.StateImageIndexes[Column] end; function TEasyItemStored.GetStateImageList(Column: Integer): TCustomImageList; begin Result := DefaultStateImageList end; procedure TEasyItemStored.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoItemImageDraw(Self, Column, ACanvas, RectArray, AlphaBlender) end; procedure TEasyItemStored.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoItemImageGetSize(Self, Column, ImageW, ImageH) end; procedure TEasyItemStored.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoItemImageDrawIsCustom(Column, Self, IsCustom) end; procedure TEasyItemStored.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); if Assigned(DataHelper) then DataHelper.LoadFromStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyItemStored.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); if Assigned(DataHelper) then DataHelper.SaveToStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyItemStored.SetCaptions(Column: Integer; Value: Widestring); begin if Assigned(DataHelper) then begin DataHelper.Captions[Column] := Value; Invalidate(False); end; end; procedure TEasyItemStored.SetDetailCount(Value: Integer); begin OwnerListview.PaintInfoItem.TileDetailCount := Value end; procedure TEasyItemStored.SetDetails(Column: Integer; Value: Integer); begin if Assigned(DataHelper) then begin DataHelper.Details[Column] := Value; Invalidate(False); end; end; procedure TEasyItemStored.SetGroupKey(FocusedColumn: Integer; Value: LongWord); begin if Assigned(DataHelper) then DataHelper.GroupKey[FocusedColumn] := Value; end; procedure TEasyItemStored.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin if Assigned(DataHelper) then begin DataHelper.ImageIndexes[Column] := Value; Invalidate(False); end; end; procedure TEasyItemStored.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin if Assigned(DataHelper) then begin DataHelper.ImageOverlayIndexes[Column] := Value; Invalidate(False); end; end; procedure TEasyItemStored.SetStateImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin if Assigned(DataHelper) then begin DataHelper.StateImageIndexes[Column] := Value; Invalidate(False); end; end; procedure TEasyItemStored.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin OwnerListview.DoItemThumbnailDraw(Self, ACanvas, ARect, AlphaBlender, DoDefault) end; { TEasyDynamicDataHelper} function TEasyDynamicDataHelper.GetCaptions(Index: Integer): Widestring; begin if Index < Length(CaptionArray) then Result := CaptionArray[Index] else Result := '' end; function TEasyDynamicDataHelper.GetDetails(Index: Integer): Integer; begin if Index < Length(DetailArray) then Result := DetailArray[Index] else Result := 0 end; function TEasyDynamicDataHelper.GetImageIndexes(Index: Integer): Integer; begin if Index < Length(ImageIndexArray) then Result := ImageIndexArray[Index] else Result := -1 end; function TEasyDynamicDataHelper.GetImageOverlayIndexes(Index: Integer): Integer; begin if Index < Length(OverlayIndexArray) then Result := OverlayIndexArray[Index] else Result := -1 end; procedure TEasyDynamicDataHelper.Clear; begin SetLength(FCaptionArray, 0); SetLength(FDetailArray, 0); SetLength(FImageIndexArray, 0); SetLength(FOverlayIndexArray, 0); end; procedure TEasyDynamicDataHelper.LoadFromStream(S: TStream; Version: Integer); begin LoadWideStrArrayFromStream(S, FCaptionArray); LoadIntArrayFromStream(S, FDetailArray); LoadIntArrayFromStream(S, FImageIndexArray); LoadIntArrayFromStream(S, FOverlayIndexArray); end; procedure TEasyDynamicDataHelper.LoadIntArrayFromStream(S: TStream; var AnArray: TCommonIntegerDynArray); var Len, i: Integer; begin Setlength(AnArray, 0); S.ReadBuffer(Len, SizeOf(Len)); Setlength(AnArray, Len); for i := 0 to Len - 1 do S.ReadBuffer(AnArray[i], SizeOf(Integer)) end; procedure TEasyDynamicDataHelper.LoadWideStrArrayFromStream(S: TStream; var AnArray: TCommonWideStringDynArray); var Len, Count, i: Integer; begin Setlength(AnArray, 0); S.ReadBuffer(Len, SizeOf(Len)); Setlength(AnArray, Len); for i := 0 to Len - 1 do begin S.ReadBuffer(Count, SizeOf(Count)); SetLength(AnArray[i], Count); S.ReadBuffer(PWideChar(AnArray[i])^, Count * 2); end end; procedure TEasyDynamicDataHelper.SaveIntArrayToStream(S: TStream; var AnArray: TCommonIntegerDynArray); var Len, i: Integer; begin Len := Length(AnArray); S.WriteBuffer(Len, SizeOf(Len)); for i := 0 to Len - 1 do S.WriteBuffer(AnArray[i], SizeOf(Integer)) end; procedure TEasyDynamicDataHelper.SaveWideStrArrayToStream(S: TStream; var AnArray: TCommonWideStringDynArray); var Len, i, Count: Integer; begin Len := Length(AnArray); S.WriteBuffer(Len, SizeOf(Len)); for i := 0 to Len - 1 do begin Count := Length(AnArray[i]); S.WriteBuffer(Count, SizeOf(Count)); S.WriteBuffer(PWideChar(AnArray[i])^, Count * 2); end end; procedure TEasyDynamicDataHelper.SaveToStream(S: TStream; Version: Integer); begin SaveWideStrArrayToStream(S, FCaptionArray); SaveIntArrayToStream(S, FDetailArray); SaveIntArrayToStream(S, FImageIndexArray); SaveIntArrayToStream(S, FOverlayIndexArray); end; procedure TEasyDynamicDataHelper.SetCaptions(Index: Integer; Value: Widestring); var OldLen, i: Integer; begin if Index >= Length(CaptionArray) then begin OldLen := Length(CaptionArray); SetLength(FCaptionArray, Index + 1); for i := OldLen to Length(CaptionArray) - 1 do CaptionArray[i] := '' end; CaptionArray[Index] := Value end; procedure TEasyDynamicDataHelper.SetDetails(Index: Integer; Value: Integer); var OldLen, i: Integer; begin if Index >= Length(DetailArray) then begin OldLen := Length(DetailArray); SetLength(FDetailArray, Index + 1); for i := OldLen to Length(DetailArray) - 1 do DetailArray[i] := 0 end; DetailArray[Index] := Value end; procedure TEasyDynamicDataHelper.SetImageIndexes(Index: Integer; Value: Integer); var OldLen, i: Integer; begin if Index >= Length(ImageIndexArray) then begin OldLen := Length(ImageIndexArray); SetLength(FImageIndexArray, Index + 1); for i := OldLen to Length(ImageIndexArray) - 1 do ImageIndexArray[i] := -1 end; ImageIndexArray[Index] := Value end; procedure TEasyDynamicDataHelper.SetImageOverlayIndexes(Index: Integer; Value: Integer); var OldLen, i: Integer; begin if Index >= Length(OverlayIndexArray) then begin OldLen := Length(OverlayIndexArray); SetLength(FOverlayIndexArray, Index + 1); for i := OldLen to Length(OverlayIndexArray) - 1 do OverlayIndexArray[i] := -1 end; OverlayIndexArray[Index] := Value end; { TEasyGroupStored } constructor TEasyBaseGroupStored.Create(ACollection: TEasyCollection); begin inherited Create(ACollection); FDataHelper := TEasyDynamicDataHelper.Create; end; destructor TEasyBaseGroupStored.Destroy; begin SetDestroyFlags; inherited Destroy; FreeAndNil(FDataHelper); end; function TEasyBaseGroupStored.GetCaptions(Line: Integer): Widestring; begin Result := DataHelper.Captions[Line] end; function TEasyBaseGroupStored.GetDetailCount: Integer; begin Result := OwnerListview.PaintInfoGroup.CaptionLines end; function TEasyBaseGroupStored.GetDetails(Line: Integer): Integer; begin Result := DataHelper.Details[Line] end; function TEasyBaseGroupStored.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := DataHelper.ImageIndexes[Column] end; function TEasyBaseGroupStored.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := DefaultImageList(IconSize) end; function TEasyBaseGroupStored.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := DataHelper.ImageOverlayIndexes[Column] end; procedure TEasyBaseGroupStored.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoGroupImageDraw(Self, ACanvas, RectArray, AlphaBlender) end; procedure TEasyBaseGroupStored.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoGroupImageGetSize(Self, ImageW, ImageH) end; procedure TEasyBaseGroupStored.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoGroupImageDrawIsCustom(Self, IsCustom) end; procedure TEasyBaseGroupStored.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); DataHelper.LoadFromStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyBaseGroupStored.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); DataHelper.SaveToStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyBaseGroupStored.SetCaptions(Column: Integer; Value: Widestring); begin DataHelper.Captions[Column] := Value; Invalidate(False) end; procedure TEasyBaseGroupStored.SetDetailCount(Value: Integer); begin OwnerListview.PaintInfoGroup.CaptionLines := Value end; procedure TEasyBaseGroupStored.SetDetails(Line: Integer; Value: Integer); begin DataHelper.Details[Line] := Value; Invalidate(False) end; procedure TEasyBaseGroupStored.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin DataHelper.ImageIndexes[Column] := Value; Invalidate(False) end; procedure TEasyBaseGroupStored.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin DataHelper.ImageOverlayIndexes[Column] := Value; Invalidate(False) end; procedure TEasyBaseGroupStored.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not implemented end; { TEasyGroupVirtual} function TEasyGroupVirtual.GetCaptions(Line: Integer): Widestring; begin Result := ''; OwnerListview.DoGroupGetCaption(Self, Result) end; function TEasyGroupVirtual.GetDetailCount: Integer; begin Result := 0; OwnerListview.DoGroupGetDetailCount(Self, Result) end; function TEasyGroupVirtual.GetDetails(Line: Integer): Integer; begin Result := 0; OwnerListview.DoGroupGetDetail(Self, Line, Result) end; function TEasyGroupVirtual.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoGroupGetImageIndex(Self, eikNormal, Result) end; function TEasyGroupVirtual.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := nil; OwnerListview.DoGroupGetImageList(Self, Result); if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyGroupVirtual.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin OwnerListview.DoGroupGetImageIndex(Self, eikOverlay, Result) end; procedure TEasyGroupVirtual.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoGroupImageDraw(Self, ACanvas, RectArray, AlphaBlender) end; procedure TEasyGroupVirtual.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoGroupImageGetSize(Self, ImageW, ImageH) end; procedure TEasyGroupVirtual.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoGroupImageDrawIsCustom(Self, IsCustom) end; procedure TEasyGroupVirtual.SetCaptions(Column: Integer; Value: Widestring); begin OwnerListview.DoGroupSetCaption(Self, Value); Invalidate(False) end; procedure TEasyGroupVirtual.SetDetailCount(Value: Integer); begin OwnerListview.DoGroupSetDetailCount(Self, Value); Invalidate(False) end; procedure TEasyGroupVirtual.SetDetails(Line: Integer; Value: Integer); begin OwnerListview.DoGroupSetDetail(Self, Line, Value); Invalidate(False) end; procedure TEasyGroupVirtual.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoGroupSetImageIndex(Self, eikNormal, Value); Invalidate(False) end; procedure TEasyGroupVirtual.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoGroupSetImageIndex(Self, eikOverlay, Value); Invalidate(False) end; procedure TEasyGroupVirtual.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not Implemented end; { TEasyGroupInterfaced} function TEasyGroupInterfaced.GetCaptions(Line: Integer): Widestring; var CaptionInf: IEasyCaptions; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptions, CaptionInf) then Result := CaptionInf.Captions[Line] end; function TEasyGroupInterfaced.GetDetailCount: Integer; var DetailInf: IEasyDetails; begin Result := 0; DetailInf := nil; if Supports(DataInf, IEasyDetails, DetailInf) then Result := DetailInf.GetDetailCount end; function TEasyGroupInterfaced.GetDetails(Line: Integer): Integer; var DetailInf: IEasyDetails; begin Result := 0; DetailInf := nil; if Supports(DataInf, IEasyDetails, DetailInf) then Result := DetailInf.Detail[Line] end; function TEasyGroupInterfaced.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; var ImageInf: IEasyImages; begin Result := -1; ImageInf := nil; if Supports(DataInf, IEasyImages, ImageInf) then Result := ImageInf.ImageIndexes[Column, eikNormal] end; function TEasyGroupInterfaced.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; var ImageList: IEasyImageList; begin Result := nil; if Supports(DataInf, IEasyImageList, ImageList) then Result := ImageList.ImageList[Column, IconSize]; if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyGroupInterfaced.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; var ImageInf: IEasyImages; begin Result := -1; ImageInf := nil; if Supports(DataInf, IEasyImages, ImageInf) then Result := ImageInf.ImageIndexes[Column, eikOverlay] end; procedure TEasyGroupInterfaced.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.DrawImage(Column, ACanvas, RectArray, AlphaBlender) end; procedure TEasyGroupInterfaced.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.GetSize(Column, ImageW, ImageH) end; procedure TEasyGroupInterfaced.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); var ImageInf: IEasyCustomImage; begin IsCustom := False; if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.CustomDrawn(Column, IsCustom) end; procedure TEasyGroupInterfaced.SetCaptions(Column: Integer; Value: Widestring); var CaptionInf: IEasyCaptionsEditable; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptionsEditable, CaptionInf) then begin CaptionInf.SetCaption(Column, Value); Invalidate(False) end end; procedure TEasyGroupInterfaced.SetDetailCount(Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.DetailCount := Value; Invalidate(False) end end; procedure TEasyGroupInterfaced.SetDetails(Line: Integer; Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.Detail[Line] := Value; Invalidate(False) end end; procedure TEasyGroupInterfaced.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); var ImageInf: IEasyImagesEditable; begin ImageInf := nil; if Supports(DataInf, IEasyImagesEditable, ImageInf) then begin ImageInf.ImageIndexes[Column, eikNormal] := Value; Invalidate(False) end end; procedure TEasyGroupInterfaced.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); var ImageInf: IEasyImagesEditable; begin ImageInf := nil; if Supports(DataInf, IEasyImagesEditable, ImageInf) then begin ImageInf.ImageIndexes[Column, eikOverlay] := Value; Invalidate(False) end end; procedure TEasyGroupInterfaced.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not supported end; { TEasyColumnStored } constructor TEasyColumnStored.Create(ACollection: TEasyCollection); begin inherited Create(ACollection); FDataHelper := TEasyDynamicDataHelper.Create; end; destructor TEasyColumnStored.Destroy; begin SetDestroyFlags; inherited Destroy; FreeAndNil(FDataHelper); end; function TEasyColumnStored.GetCaptions(Line: Integer): Widestring; begin Result := DataHelper.Captions[Line] end; function TEasyColumnStored.GetDetailCount: Integer; begin Result := OwnerListview.PaintInfoColumn.CaptionLines end; function TEasyColumnStored.GetDetails(Line: Integer): Integer; begin Result := DataHelper.Details[Index] end; function TEasyColumnStored.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := DataHelper.ImageIndexes[Column] end; function TEasyColumnStored.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := DefaultImageList(IconSize) end; function TEasyColumnStored.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := DataHelper.ImageOverlayIndexes[Column] end; procedure TEasyColumnStored.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoColumnImageDraw(Self, ACanvas, RectArray, AlphaBlender) end; procedure TEasyColumnStored.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoColumnImageGetSize(Self, ImageW, ImageH) end; procedure TEasyColumnStored.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoColumnImageDrawIsCustom(Self, IsCustom) end; procedure TEasyColumnStored.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); DataHelper.LoadFromStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyColumnStored.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); DataHelper.SaveToStream(S, Version); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyColumnStored.SetCaptions(Column: Integer; Value: Widestring); begin DataHelper.Captions[Column] := Value; Invalidate(False) end; procedure TEasyColumnStored.SetDetailCount(Value: Integer); begin OwnerListview.PaintInfoColumn.CaptionLines := Value; end; procedure TEasyColumnStored.SetDetails(Line: Integer; Value: Integer); begin DataHelper.Details[Line] := Value; Invalidate(False) end; procedure TEasyColumnStored.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin DataHelper.ImageIndexes[Column] := Value; Invalidate(False) end; procedure TEasyColumnStored.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin DataHelper.ImageOverlayIndexes[Column] := Value; Invalidate(False) end; procedure TEasyColumnStored.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not implemented end; function TEasyColumnInterfaced.GetCaptions(Line: Integer): Widestring; var CaptionInf: IEasyCaptions; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptions, CaptionInf) then Result := CaptionInf.Captions[Line] end; function TEasyColumnInterfaced.GetDetailCount: Integer; var DetailInf: IEasyDetails; begin Result := 0; DetailInf := nil; if Supports(DataInf, IEasyDetails, DetailInf) then Result := DetailInf.GetDetailCount end; function TEasyColumnInterfaced.GetDetails(Line: Integer): Integer; var DetailInf: IEasyDetails; begin Result := 0; DetailInf := nil; if Supports(DataInf, IEasyDetails, DetailInf) then Result := DetailInf.Detail[Line] end; function TEasyColumnInterfaced.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; var ImageInf: IEasyImages; begin Result := -1; ImageInf := nil; if Supports(DataInf, IEasyImages, ImageInf) then Result := ImageInf.ImageIndexes[Column, eikNormal] end; function TEasyColumnInterfaced.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; var ImageList: IEasyImageList; begin Result := nil; if Supports(DataInf, IEasyImageList, ImageList) then Result := ImageList.ImageList[Column, IconSize]; if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyColumnInterfaced.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; var ImageInf: IEasyImages; begin Result := -1; ImageInf := nil; if Supports(DataInf, IEasyImages, ImageInf) then Result := ImageInf.ImageIndexes[Column, eikOverlay] end; procedure TEasyColumnInterfaced.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.DrawImage(Column, ACanvas, RectArray, AlphaBlender) end; procedure TEasyColumnInterfaced.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); var ImageInf: IEasyCustomImage; begin if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.GetSize(Column, ImageW, ImageH) end; procedure TEasyColumnInterfaced.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); var ImageInf: IEasyCustomImage; begin IsCustom := False; if Supports(DataInf, IEasyCustomImage, ImageInf) then ImageInf.CustomDrawn(Column, IsCustom) end; procedure TEasyColumnInterfaced.SetCaptions(Column: Integer; Value: Widestring); var CaptionInf: IEasyCaptionsEditable; begin CaptionInf := nil; if Supports(DataInf, IEasyCaptionsEditable, CaptionInf) then CaptionInf.SetCaption(Column, Value); Invalidate(False); end; procedure TEasyColumnInterfaced.SetDetailCount(Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.DetailCount := Value; Invalidate(False) end end; procedure TEasyColumnInterfaced.SetDetails(Line: Integer; Value: Integer); var DetailsInf: IEasyDetailsEditable; begin DetailsInf := nil; if Supports(DataInf, IEasyDetailsEditable, DetailsInf) then begin DetailsInf.Detail[Line] := Value; Invalidate(False) end end; procedure TEasyColumnInterfaced.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); var ImageInf: IEasyImagesEditable; begin ImageInf := nil; if Supports(DataInf, IEasyImagesEditable, ImageInf) then begin ImageInf.ImageIndexes[Column, eikNormal] := Value; Invalidate(False) end end; procedure TEasyColumnInterfaced.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); var ImageInf: IEasyImagesEditable; begin ImageInf := nil; if Supports(DataInf, IEasyImagesEditable, ImageInf) then begin ImageInf.ImageIndexes[Column, eikOverlay] := Value; Invalidate(False) end end; procedure TEasyColumnInterfaced.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not implemented end; { TEasyColumnVirtual} function TEasyColumnVirtual.GetCaptions(Line: Integer): Widestring; begin Result := ''; OwnerListview.DoColumnGetCaption(Self, Line, Result) end; function TEasyColumnVirtual.GetDetailCount: Integer; begin Result := 0; OwnerListview.DoColumnGetDetailCount(Self, Result) end; function TEasyColumnVirtual.GetDetails(Line: Integer): Integer; begin Result := 0; OwnerListview.DoColumnGetDetail(Self, Line, Result) end; function TEasyColumnVirtual.GetImageIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoColumnGetImageIndex(Self, eikNormal, Result) end; function TEasyColumnVirtual.GetImageList(Column: Integer; IconSize: TEasyImageSize): TCustomImageList; begin Result := nil; OwnerListview.DoColumnGetImageList(Self, Result); if not Assigned(Result) then Result := DefaultImageList(IconSize) end; function TEasyColumnVirtual.GetImageOverlayIndexes(Column: Integer): TCommonImageIndexInteger; begin Result := -1; OwnerListview.DoColumnGetImageIndex(Self, eikOverlay, Result) end; procedure TEasyColumnVirtual.ImageDraw(Column: TEasyColumn; ACanvas: TCanvas; const RectArray: TEasyRectArrayObject; AlphaBlender: TEasyAlphaBlender); begin OwnerListview.DoColumnImageDraw(Self, ACanvas, RectArray, AlphaBlender) end; procedure TEasyColumnVirtual.ImageDrawGetSize(Column: TEasyColumn; var ImageW: Integer; var ImageH: Integer); begin OwnerListview.DoColumnImageGetSize(Self, ImageW, ImageH) end; procedure TEasyColumnVirtual.ImageDrawIsCustom(Column: TEasyColumn; var IsCustom: Boolean); begin IsCustom := False; OwnerListview.DoColumnImageDrawIsCustom(Self, IsCustom) end; procedure TEasyColumnVirtual.SetCaptions(Column: Integer; Value: Widestring); begin OwnerListview.DoColumnSetCaption(Self, Value); Invalidate(False) end; procedure TEasyColumnVirtual.SetDetailCount(Value: Integer); begin OwnerListview.DoColumnSetDetailCount(Self, Value); Invalidate(False) end; procedure TEasyColumnVirtual.SetDetails(Line: Integer; Value: Integer); begin OwnerListview.DoColumnSetDetail(Self, Line, Value); Invalidate(False) end; procedure TEasyColumnVirtual.SetImageIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoColumnSetImageIndex(Self, eikNormal, Value); Invalidate(False) end; procedure TEasyColumnVirtual.SetImageOverlayIndexes(Column: Integer; Value: TCommonImageIndexInteger); begin OwnerListview.DoColumnSetImageIndex(Self, eikOverlay, Value); Invalidate(False) end; procedure TEasyColumnVirtual.ThumbnailDraw(ACanvas: TCanvas; ARect: TRect; AlphaBlender: TEasyAlphaBlender; var DoDefault: Boolean); begin // not Implemented end; { TEasyPaintInfoBaseItem } constructor TEasyPaintInfoBaseItem.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FTileDetailCount := 1; FGridLineColor := clBtnFace; end; procedure TEasyPaintInfoBaseItem.SetGridLineColor(const Value: TColor); begin if FGridLineColor <> Value then begin FGridLineColor := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyPaintInfoBaseItem.SetGridLines(const Value: Boolean); begin if FGridLines <> Value then begin FGridLines := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyPaintInfoBaseItem.SetHideCaption(const Value: Boolean); begin if FHideCaption <> Value then begin FHideCaption := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; procedure TEasyPaintInfoBaseItem.SetTileDetailCount(Value: Integer); begin if Value <> FTileDetailCount then begin FTileDetailCount := Value; OwnerListview.SafeInvalidateRect(nil, False) end end; { TColumnPos } function TColumnPos.Get(Index: Integer): TEasyColumn; begin Result := inherited Get(Index) end; procedure TColumnPos.Put(Index: Integer; Item: TEasyColumn); begin inherited Put(Index, Item) end; { TEasyHeaderDragManager } constructor TEasyHeaderDragManager.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FEnableDragImage := True; FDragImageWidth := 200; FDragImageHeight := 300; FEnabled := False; DefaultImageEvent := DefaultImage; DragMode := dmManual; DragCursor := crDrag end; function TEasyHeaderDragManager.DoPtInAutoScrollDownRegion(WindowPoint: TPoint): Boolean; begin Result := False end; function TEasyHeaderDragManager.DoPtInAutoScrollLeftRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.X < AutoScrollMargin) and (OwnerListview.View = elsReport) end; function TEasyHeaderDragManager.DoPtInAutoScrollRightRegion(WindowPoint: TPoint): Boolean; begin Result := (WindowPoint.X > (OwnerListview.ClientWidth - AutoScrollMargin)) and (OwnerListview.View = elsReport) end; function TEasyHeaderDragManager.DoPtInAutoScrollUpRegion(WindowPoint: TPoint): Boolean; begin Result := False end; function TEasyHeaderDragManager.GetDragCursor: TCursor; begin Result := OwnerListview.DragCursor end; function TEasyHeaderDragManager.GetDragMode: TDragMode; begin Result := FDragMode; end; procedure TEasyHeaderDragManager.DefaultImage(Sender: TCustomEasyListview; Image: TBitmap; DragStartPt: TPoint; var HotSpot: TPoint; var TransparentColor: TColor; var Handled: Boolean); // Generates the drag image for the dragging items from the Easy Control var R, ViewR: TRect; Pt: TPoint; begin if Assigned(Image) then begin TransparentColor := OwnerListview.Color; Image.Canvas.Brush.Color := Header.Color; Image.Canvas.FillRect(Rect(0, 0, Image.Width, Image.Height)); R := Column.DisplayRect; HotSpot.X := DragStartPt.X - Column.DisplayRect.Left; HotSpot.Y := DragStartPt.Y - Column.DisplayRect.Top; if R.Left < 0 then HotSpot.X := HotSpot.X + R.Left; if R.Top < 0 then HotSpot.Y := HotSpot.Y + R.Top; ViewR := OwnerListview.ClientRect; OffsetRect(ViewR, OwnerListview.Scrollbars.OffsetX, 0); IntersectRect(R, R, ViewR); SetViewPortOrgEx(Image.Canvas.Handle, -R.Left, 0, @Pt); Header.PaintTo(Image.Canvas, R); SetViewPortOrgEx(Image.Canvas.Handle, Pt.X, Pt.Y, nil); Handled := True; end end; procedure TEasyHeaderDragManager.DoDrag(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); var Temp: TEasyColumn; begin Effects := cdeNone; if AllowDrop then begin if WindowPoint.Y < Header.Height then begin Effects := cdeMove; if OwnerListview.ScrollHeaderHorz then Inc(WindowPoint.X, OwnerListview.Scrollbars.OffsetX); Temp := Header.Columns.ColumnByPoint(WindowPoint); if Temp <> TargetColumn then begin if Assigned(TargetColumn) then begin Exclude(TargetColumn.FState, esosDropTarget); TargetColumn.Invalidate(True); end; TargetColumn := Temp; if Assigned(TargetColumn) then begin Include(TargetColumn.FState, esosDropTarget); TargetColumn.Invalidate(True); end end end else begin if Assigned(TargetColumn) then begin Exclude(TargetColumn.FState, esosDropTarget); TargetColumn.Invalidate(True); TargetColumn := nil; end; end end end; procedure TEasyHeaderDragManager.DoDragBegin(WindowPoint: TPoint; KeyStates: TCommonKeyStates); var DropSource: IDropSource; DataObject: TEasyDataObjectManager; DataObjInf: ICommonExtractObj; Image: TBitmap; TransparentColor: TColor; dwEffect, ImageWidth, ImageHeight: Integer; AvailableEffects: TCommonDropEffects; DragResultEffect: TCommonOLEDragResult; AllowDrag, Handled: Boolean; DragResult: HRESULT; HotPtOffset: TPoint; DataObjectInf: IDataObject; begin if Enabled then begin inherited; if DragType = edtOLE then begin DataObjectInf := nil; DataObject := nil; AvailableEffects := [cdeNone]; dwEffect := 0; AllowDrag := False; if Self is TEasyOLEDragManager then OwnerListview.DoOLEGetDataObject(DataObjectInf); if not Assigned(DataObjectInf) then begin DataObject := TEasyDataObjectManager.Create; // Get a reference right away so it won't be freed from under us DataObjectInf := DataObject as IDataObject; DataObject.Listview := OwnerListview; end; DoOLEDragStart(DataObjectInf, AvailableEffects, AllowDrag); if AllowDrag then begin if (DataObjectInf.QueryInterface(ICommonExtractObj, DataObjInf) = S_OK) then DataObject := DataObjInf.GetObj as TEasyDataObjectManager; if EnableDragImage and Assigned(DataObject) and OwnerListview.UseInternalDragImage then begin Image := TBitmap.Create; try ImageWidth := 0; ImageHeight := 0; ImageSize(ImageWidth, ImageHeight); Image.Width := ImageWidth; Image.Height := ImageHeight; Image.PixelFormat := pf32Bit; TransparentColor := clWindow; Handled := False; DoGetDragImage(Image, WindowPoint, HotPtOffset, TransparentColor, Handled); if not Handled and Assigned(DefaultImageEvent) then DefaultImageEvent(OwnerListview, Image, WindowPoint, HotPtOffset, TransparentColor, Handled); if Handled then DataObject.AssignDragImage(Image, HotPtOffset, TransparentColor); finally Image.Free end end; DropSource := TEasyDropSourceManager.Create(OwnerListview); DragResult := OwnerListview.ExecuteDragDrop(AvailableEffects, DataObjectInf, DropSource, dwEffect); if DragResult = DRAGDROP_S_DROP then DragResultEffect := cdrDrop else if DragResult = DRAGDROP_S_CANCEL then DragResultEffect := cdrCancel else DragResultEffect := cdrError; // Set it back to the default drag manager to be ready for a drop DoOLEDragEnd(DataObjectInf, DragResultEffect, DropEffectToDropEffectStates(dwEffect), KeyStates); DataObject.Listview := nil; end end else VCLDragStart end; DataObjectInf := nil end; procedure TEasyHeaderDragManager.DoDragDrop(WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); begin if Assigned(TargetColumn) then Column.Position := TargetColumn.Position; DoDragEnd(nil, WindowPoint, KeyState); end; procedure TEasyHeaderDragManager.DoDragEnd(Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates); begin if Assigned(TargetColumn) then begin Exclude(TargetColumn.FState, esosDropTarget); TargetColumn.Invalidate(True); end; TargetColumn := nil; end; procedure TEasyHeaderDragManager.DoDragEnter(const DataObject: IDataObject; Canvas: TCanvas; WindowPoint: TPoint; KeyState: TCommonKeyStates; var Effects: TCommonDropEffect); var Medium: TStgMedium; DataPtr: PHeaderClipData; begin AllowDrop := False; Effects := cdeNone; if Succeeded(DataObject.GetData(HeaderClipFormat, Medium)) then begin DataPtr := GlobalLock(Medium.hGlobal); try AllowDrop := (DataPtr^.Thread = GetCurrentThread) and (DataPtr^.Listview = OwnerListview) finally GlobalUnlock(Medium.hGlobal); ReleaseStgMedium(Medium) end end; end; procedure TEasyHeaderDragManager.DoOLEDragEnd(const ADataObject: IDataObject; DragResult: TCommonOLEDragResult; ResultEffect: TCommonDropEffects; KeyStates: TCommonKeyStates); begin Header.ClearStates end; procedure TEasyHeaderDragManager.DoOLEDragStart(const ADataObject: IDataObject; var AvailableEffects: TCommonDropEffects; var AllowDrag: Boolean); var Medium: TStgMedium; DataPtr: PHeaderClipData; begin AllowDrag := Enabled; AvailableEffects := [cdeMove]; FillChar(Medium, SizeOf(Medium), #0); Medium.tymed := TYMED_HGLOBAL; Medium.hGlobal := GlobalAlloc(GHND, SizeOf(THeaderClipData)); try DataPtr := GlobalLock(Medium.hGlobal); DataPtr^.Column := Column; DataPtr^.Listview := Header.OwnerListview; DataPtr^.Thread := GetCurrentThread; finally GlobalUnLock(Medium.hGlobal) end; // Give the block to the IDataObject to dispose of ADataObject.SetData(HeaderClipFormat, Medium, True); end; procedure TEasyHeaderDragManager.ImageSize(var Width, Height: Integer); begin Width := Column.Width; Height := OwnerListview.Header.Height end; procedure TEasyHeaderDragManager.SetDragCursor(Value: TCursor); begin OwnerListview.DragCursor := Value end; procedure TEasyHeaderDragManager.SetDragMode(Value: TDragMode); begin FDragMode := Value end; procedure TEasyHeaderDragManager.SetDragType(Value: TEasyDragType); begin if FDragType <> Value then begin if Value = edtVCL then Registered := False; FDragType := Value; end end; { TEasyItemDynamicDataHelper } function TEasyItemDynamicDataHelper.GetGroupKey(Index: Integer): LongWord; begin if Index < Length(GroupKeyArray) then Result := GroupKeyArray[Index] else Result := EGT_FIRSTLETTER end; function TEasyItemDynamicDataHelper.GetStateImageIndexes(Index: Integer): TCommonImageIndexInteger; begin if Index < Length(StateImageArray) then Result := StateImageArray[Index] else Result := -1 end; procedure TEasyItemDynamicDataHelper.LoadFromStream(S: TStream; Version: Integer); begin inherited LoadFromStream(S, Version); LoadIntArrayFromStream(S, FGroupKeyArray); if Version > 2 then begin LoadIntArrayFromStream(S, FStateImageArray); end end; procedure TEasyItemDynamicDataHelper.SaveToStream(S: TStream; Version: Integer); begin inherited SaveToStream(S, Version); SaveIntArrayToStream(S, FGroupKeyArray); SaveIntArrayToStream(S, FStateImageArray); end; procedure TEasyItemDynamicDataHelper.SetGroupKey(Index: Integer; Value: LongWord); var OldLen, i: Integer; begin if Index >= Length(GroupKeyArray) then begin OldLen := Length(GroupKeyArray); SetLength(FGroupKeyArray, Index + 1); for i := OldLen to Length(GroupKeyArray) - 1 do GroupKeyArray[i] := EGT_FIRSTLETTER end; GroupKeyArray[Index] := Value end; procedure TEasyItemDynamicDataHelper.SetStateImageIndexes(Index: Integer; Value: TCommonImageIndexInteger); var OldLen, i: Integer; begin if Index >= Length(StateImageArray) then begin OldLen := Length(StateImageArray); SetLength(FStateImageArray, Index + 1); for i := OldLen to Length(StateImageArray) - 1 do StateImageArray[i] := -1 end; StateImageArray[Index] := Value end; { TEasySorter} constructor TEasySorter.Create(AnOwner: TEasySortManager); begin inherited Create; FOwner := AnOwner; end; destructor TEasyOwnedPersistentView.Destroy; begin FreeAndNil(FCanvasStore); inherited Destroy; end; function TEasyOwnedPersistentView.GetCanvasStore: TEasyCanvasStore; begin if not Assigned(FCanvasStore) then FCanvasStore := TEasyCanvasStore.Create; Result := FCanvasStore end; procedure TEasyOwnedPersistentView.PaintCheckboxCore(CheckType: TEasyCheckType; OwnerListView: TCustomEasyListView; ACanvas: TCanvas; ARect: TRect; IsEnabled, IsChecked, IsHot, IsFlat, IsHovering, IsPending: Boolean; Obj: TEasyCollectionItem; Size: Integer); var {$IFDEF SpTBX} CheckState: TCheckBoxState; {$ENDIF} {$IFDEF USETHEMES} uState: Longword; Part: BUTTONPARTS; {$ENDIF} Pt: TPoint; begin {$IFDEF SpTBX} if not ((CheckType = ectNone) or (CheckType = ettNoneWithSpace)) then begin if CurrentTheme.Name <> 'Default' then begin if IsChecked then CheckState := cbChecked else CheckState := cbUnChecked; InflateRect(ARect, -1, -1); SpDrawXPCheckBoxGlyph(ACanvas, ARect, IsEnabled, CheckState, IsHovering, IsPending, True, thtTBX); Exit; end end; {$ENDIF} {$IFDEF USETHEMES} if OwnerListview.DrawWithThemes then begin uState := 0; Part := 0; case CheckType of ectBox: begin Part := BP_CHECKBOX; if IsEnabled then begin if IsHovering then begin if IsChecked then uState := CBS_CHECKEDHOT else uState := CBS_UNCHECKEDHOT end else if IsPending then begin if IsChecked then uState := CBS_CHECKEDPRESSED else uState := CBS_UNCHECKEDPRESSED end else begin if IsChecked then uState := CBS_CHECKEDNORMAL else uState := CBS_UNCHECKEDNORMAL end end else begin if IsChecked then uState := CBS_CHECKEDDISABLED else uState := CBS_UNCHECKEDDISABLED end end; ectRadio: begin Part := BP_RADIOBUTTON; if IsEnabled then begin if IsHovering then begin if IsChecked then uState := RBS_CHECKEDHOT else uState := RBS_UNCHECKEDHOT end else if IsPending then begin if IsChecked then uState := RBS_CHECKEDPRESSED else uState := RBS_UNCHECKEDPRESSED end else begin if IsChecked then uState := RBS_CHECKEDNORMAL else uState := RBS_UNCHECKEDNORMAL end end else begin if IsChecked then uState := RBS_CHECKEDDISABLED else uState := RBS_UNCHECKEDDISABLED end end end; DrawThemeBackground(OwnerListview.Themes.ButtonTheme, ACanvas.Handle, Part, uState, ARect, nil); Exit; end; {$ENDIF} case CheckType of ectBox: begin Pt := ARect.TopLeft; if IsEnabled then begin if IsFlat then DrawCheckBox(ACanvas, Pt, Size, clWhite, clBtnFace, clBlack, clBlack, clBlack, clBlack, IsChecked, IsEnabled, IsHot) else DrawCheckBox(ACanvas, Pt, Size, clWhite, clBtnFace, clBtnShadow, clBtnHighlight, cl3DDkShadow, cl3DLight, IsChecked, IsEnabled, IsHot) end else begin if IsFlat then DrawCheckBox(ACanvas, Pt, Size, clBtnFace, clBtnFace, clBtnShadow, clBtnShadow, clBtnShadow, clBtnShadow, IsChecked, IsEnabled, IsHot) else DrawCheckBox(ACanvas, Pt, Size, clBtnFace, clBtnFace, clBtnShadow, clBtnHighlight, cl3DDkShadow, cl3DLight, IsChecked, IsEnabled, IsHot) end; end; ectRadio: begin Pt :=ARect.TopLeft; if IsEnabled then begin if IsFlat then DrawRadioButton(ACanvas, Pt, Size, clWhite, clBtnFace, clBlack, clBlack, clBlack, clBlack, IsChecked, IsEnabled, IsHot) else DrawRadioButton(ACanvas, Pt, Size, clWhite, clBtnFace, clBtnShadow, clBtnHighlight, cl3DDkShadow, cl3DLight, IsChecked, IsEnabled, IsHot) end else begin if IsFlat then DrawRadioButton(ACanvas, Pt, Size, clBtnFace, clBtnFace, clBtnShadow, clBtnShadow, clBtnShadow, clBtnShadow, IsChecked, IsEnabled, IsHot) else DrawRadioButton(ACanvas, Pt, Size, clBtnFace, clBtnFace, clBtnShadow, clBtnHighlight, cl3DDkShadow, cl3DLight, IsChecked, IsEnabled, IsHot) end; end end end; constructor TEasyIncrementalSearchManager.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FItemType := eisiVisible; FResetTime := 2000; end; destructor TEasyIncrementalSearchManager.Destroy; begin EndTimer; inherited end; function TEasyIncrementalSearchManager.IsSearching: Boolean; // // Returns true if the manager is in within a search sequence // begin Result := eissSearching in State end; procedure TEasyIncrementalSearchManager.ClearSearch; // // Clears the search item and does any necessary clean up begin FSearchItem := nil; FNextSearchItem := nil; end; procedure TEasyIncrementalSearchManager.EndTimer; // // Kills and destroys the Timer // begin if eissTimerRunning in State then begin if KillTimer(0, hTimer) then begin hTimer := 0; Exclude(FState, eissTimerRunning); DisposeStub(FTimerStub); end else Exception.Create('Can not Destroy Incremental Search Timer'); end end; procedure TEasyIncrementalSearchManager.HandleWMChar(var Msg: TWMChar); // // The WM_CHAR message is passed to the manager to handle the incremental // search // function CodePageFromLocale(Language: LCID): Integer; var Buf: array[0..6] of Char; begin // Determines the code page for a given locale. // Unfortunately there is no easier way than this, currently. GetLocaleInfo(Language, LOCALE_IDEFAULTANSICODEPAGE, Buf, 6); Result := StrToIntDef(Buf, GetACP); end; function KeyUnicode(C: Char): WideChar; // Converts the given character into its corresponding Unicode character // depending on the active keyboard layout. begin MultiByteToWideChar(CodePageFromLocale(GetKeyboardLayout(0) and $FFFF), MB_USEGLYPHCHARS, @C, 1, @Result, 1); end; procedure WrapToListStart(First, Last: TItemEnumFirstLast; var SearchItem: TEasyItem); begin case Direction of eisdForward: SearchItem := First; eisdBackward: SearchItem := Last; end; end; procedure SearchToListEnd(Next, Prev :TItemNextEnum; var SearchItem: TEasyItem); var CompareResult: Integer; begin CompareResult := -1; while (CompareResult <> 0) and Assigned(SearchItem) do begin if Assigned(SearchItem) and (SearchBuffer <> #13) then OwnerListview.DoIncrementalSearch(SearchItem, SearchBuffer, CompareResult); if CompareResult <> 0 then begin case Direction of eisdForward: SearchItem := Next(SearchItem); eisdBackward: SearchItem := Prev(SearchItem); end; end end; end; procedure SearchToItem(Next, Prev :TItemNextEnum; TargetItem: TEasyItem; var SearchItem: TEasyItem); var CompareResult: Integer; begin CompareResult := -1; while (CompareResult <> 0) and (SearchItem <> TargetItem) do begin if Assigned(SearchItem) and (SearchBuffer <> #13) then OwnerListview.DoIncrementalSearch(SearchItem, SearchBuffer, CompareResult); if CompareResult <> 0 then begin case Direction of eisdForward: SearchItem := OwnerListview.Groups.NextItem(SearchItem); eisdBackward: SearchItem := OwnerListview.Groups.PrevItem(SearchItem); end end end; if CompareResult <> 0 then SearchItem := nil end; procedure SearchList(Next, Prev :TItemNextEnum; First, Last: TItemEnumFirstLast; var SearchItem: TEasyItem); var StartItem: TEasyItem; begin StartItem := SearchItem; SearchToListEnd(Next, Prev, SearchItem); // Keep wrapping if not found if not Assigned(SearchItem) then begin WrapToListStart(First, Last, SearchItem); SearchToItem(Next, Prev, StartItem, SearchItem); end end; var CompareResult: Integer; Shift: TShiftState; begin if Enabled and IsSearching then begin ResetTimer; Shift := KeyDataToShiftState(Msg.KeyData); if ((Shift * [ssAlt, ssCtrl]) = []) and (Msg.CharCode > 31) then begin CompareResult := 0; SearchBuffer := SearchBuffer + KeyUnicode(Char( Msg.CharCode)); if not Assigned(NextSearchItem) then LoadFutureItem; // Mimic how Explorer works if Length(SearchBuffer) >= 2 then begin if SearchBuffer[1] = SearchBuffer[2] then begin SearchBuffer := SearchBuffer[1]; if (StartType <> eissStartOver) and Assigned(NextSearchItem) then SearchItem := NextSearchItem end end else begin if (Length(SearchBuffer) = 1) and (StartType <> eissStartOver) and Assigned(NextSearchItem) then SearchItem := NextSearchItem end; if Assigned(SearchItem) then begin if SearchBuffer <> #13 then OwnerListview.DoIncrementalSearch(SearchItem, SearchBuffer, CompareResult); ResetTimer; if CompareResult <> 0 then begin case ItemType of eisiAll: // Search All items in list begin SearchList(OwnerListview.Groups.NextItem, OwnerListview.Groups.PrevItem, OwnerListview.Groups.FirstItem, OwnerListview.Groups.LastItem, FSearchItem); end; eisiInitializedOnly: // Search only initialized items begin SearchList(OwnerListview.Groups.NextInitializedItem, OwnerListview.Groups.PrevInitializedItem, OwnerListview.Groups.FirstInitializedItem, OwnerListview.Groups.LastInitializedItem, FSearchItem); end; eisiVisible: // Search only visible items begin SearchList(OwnerListview.Groups.NextVisibleItem, OwnerListview.Groups.PrevVisibleItem, OwnerListview.Groups.FirstVisibleItem, OwnerListview.Groups.LastVisibleItem, FSearchItem); end end end; if Assigned(SearchItem) then begin // Found the item OwnerListview.Selection.ClearAll; OwnerListview.Selection.FocusedItem := SearchItem; if Assigned(SearchItem) then begin SearchItem.Selected := True; SearchItem.MakeVisible(emvAuto) end; if StartType <> eissStartOver then LoadFutureItem; end end end else ClearSearch end end; procedure TEasyIncrementalSearchManager.HandleWMKeyDown(var Msg: TWMKeyDown); // // The WM_KEYDOWN message is passed to the manager to handle the incremental // search // var Shift: TShiftState; begin if Enabled then begin Shift := KeyDataToShiftState(Msg.KeyData); // if (Shift * [ssCtrl, ssAlt] = []) and ((Msg.CharCode > VK_HELP) and (Msg.CharCode < VK_LWIN)) or ((Msg.CharCode > VK_APPS) and (Msg.CharCode < VK_F1) ) then StartSearch end end; procedure TEasyIncrementalSearchManager.LoadFutureItem; begin NextSearchItem := SearchItem; case ItemType of eisiAll: begin SearchPreloadItem(OwnerListview.Groups.NextItem, OwnerListview.Groups.PrevItem, OwnerListview.Groups.FirstItem, OwnerListview.Groups.LastItem, FNextSearchItem); end; eisiInitializedOnly: // Search only initialized items begin SearchPreloadItem(OwnerListview.Groups.NextInitializedItem, OwnerListview.Groups.PrevInitializedItem, OwnerListview.Groups.FirstInitializedItem, OwnerListview.Groups.LastInitializedItem, FNextSearchItem); end; eisiVisible: // Search only visible items begin SearchPreloadItem(OwnerListview.Groups.NextVisibleItem, OwnerListview.Groups.PrevVisibleItem, OwnerListview.Groups.FirstVisibleItem, OwnerListview.Groups.LastVisibleItem, FNextSearchItem); end; end; end; procedure TEasyIncrementalSearchManager.ResetSearch; // // Ends and resets all search criteria // begin SearchBuffer := ''; if StartType <> eissLastHit then ClearSearch; Exclude(FState, eissSearching); EndTimer; end; procedure TEasyIncrementalSearchManager.ResetTimer; // // Resets the timer to another FResetTime interval without stopping the current // search process // begin EndTimer; StartTimer; end; procedure TEasyIncrementalSearchManager.SearchPreloadItem(Next, Prev: TItemNextEnum; First, Last: TItemEnumFirstLast; var SearchItem: TEasyItem); begin case Direction of eisdForward: SearchItem := Next(SearchItem); eisdBackward: SearchItem := Prev(SearchItem); end; if not Assigned(SearchItem) then begin case Direction of eisdForward: SearchItem := First; eisdBackward: SearchItem := Last; end; end end; procedure TEasyIncrementalSearchManager.SetSearchItem(Value: TEasyItem); begin if Value <> FSearchItem then begin ClearSearch; FSearchItem := Value end end; procedure TEasyIncrementalSearchManager.StartSearch; procedure SetupStartOver; begin case ItemType of eisiAll: // Search All items in list begin if Direction = eisdForward then SearchItem := OwnerListview.Groups.FirstItem else SearchItem := OwnerListview.Groups.LastItem end; eisiInitializedOnly: // Search only initialized items begin if Direction = eisdForward then SearchItem := OwnerListview.Groups.FirstInitializedItem else SearchItem := OwnerListview.Groups.LastInitializedItem end; eisiVisible: // Search only visible items begin if Direction = eisdForward then SearchItem := OwnerListview.Groups.FirstVisibleItem else SearchItem := OwnerListview.Groups.LastVisibleItem end; end end; // // Initializes the search called on WMKEYDOWN // begin // Only call once during a Search Sequence if not (eissSearching in State) then begin case StartType of eissStartOver: begin SetupStartOver; end; eissLastHit: begin // The Search Item is already set up, or not if not Assigned(SearchItem) then SetupStartOver; LoadFutureItem; end; eissFocusedNode: begin // By definition the Focused Item is Visible and Initalized so // no other checks are necessary if Assigned(OwnerListview.Selection.FocusedItem) then begin SearchItem := OwnerListview.Selection.FocusedItem; LoadFutureItem; end else SetupStartOver; end; end; StartTimer; // JDK 5.3.05 Include(FState, eissSearching); end; end; procedure TEasyIncrementalSearchManager.StartTimer; // // Starts the Timer for the search // begin if Enabled and not(eissTimerRunning in State) then begin TimerStub := CreateStub(Self, @TEasyIncrementalSearchManager.TimerProc); hTimer := SetTimer(0, 0, ResetTime, TimerStub); Include(FState, eissTimerRunning); end end; procedure TEasyIncrementalSearchManager.TimerProc(Window: HWnd; uMsg: UINT; idEvent: UINT; dwTime: DWORD); // // The callback for the Timer. A callback is not effected by any blocked message // handler taking their sweet time. // begin ResetSearch; end; { TEasyGridFilmStripGroup } function TEasyGridFilmStripGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.FilmStrip end; procedure TEasyGridFilmStripGroup.AutoSizeCells; begin // Do nothing end; procedure TEasyGridFilmStripGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.FilmStrip.Assign(Value) end; { TEasyPersistent } constructor TEasyPersistent.Create; begin inherited Create; end; destructor TEasyPersistent.Destroy; begin inherited Destroy; end; procedure TEasyPersistent.Assign(Source: TPersistent); begin inherited Assign(Source); end; { TEasyGridGridGroup } constructor TEasyGridGridGroup.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner, AnOwnerGroup); FLayout := eglGrid end; function TEasyGridGridGroup.GetCellSize: TEasyCellSize; begin Result := OwnerListview.CellSizes.Grid end; procedure TEasyGridGridGroup.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); var i, Top, Bottom, Left, Offset, TopMargin, BottomMargin, VisibleCount, ColumnIndex, ColumnLeft: Integer; Item: TEasyItem; Columns: TEasyColumns; begin AutoSizeCells; if Assigned(PrevGroup) then Offset := PrevGroup.DisplayRect.Bottom else Offset := 0; ColumnIndex := 0; Columns := OwnerListview.Header.Columns; OwnerGroup.FDisplayRect := Rect(0, Offset, OwnerListview.Header.ViewWidth, Offset); // Prepare the VisibleList for the worse case, all are visible OwnerGroup.VisibleItems.Clear; OwnerGroup.VisibleItems.Capacity := OwnerGroup.Items.Count; Left := OwnerGroup.MarginLeft.RuntimeSize; TopMargin := OwnerGroup.MarginTop.RuntimeSize; BottomMargin := OwnerGroup.MarginBottom.RuntimeSize; if OwnerGroup.Visible then begin if OwnerGroup.Expanded and (OwnerGroup.Items.Count > 0) then begin VisibleCount := 0; Top := Offset + TopMargin; Bottom := Offset + CellSize.Height + TopMargin; for i := 0 to OwnerGroup.Items.Count - 1 do begin Item := OwnerGroup.Items.List.List[i]; // Direct Access for Speed if Item.Visible then begin Item.FVisibleIndex := NextVisibleItemIndex; Item.FVisibleIndexInGroup := VisibleCount; ColumnLeft := Columns[ColumnIndex].DisplayRect.Left; Item.FDisplayRect := Rect(Left + ColumnLeft, Top, Left + ColumnLeft + Columns[ColumnIndex].Width, Bottom); OwnerGroup.VisibleItems.Add(Item); Inc(ColumnIndex); if ColumnIndex >= Columns.Count then begin ColumnIndex := 0; Inc(Top, CellSize.Height); Inc(Bottom, CellSize.Height); end; Inc(VisibleCount); Inc(NextVisibleItemIndex); end else Item.FDisplayRect := Rect(Left, Top, Left, Top); OwnerGroup.FDisplayRect.Bottom := Item.FDisplayRect.Bottom + BottomMargin; end end else OwnerGroup.FDisplayRect := Rect(0, Offset, OwnerListview.Header.ViewWidth, Offset + TopMargin + BottomMargin); end; // Column Count does not relate to Report view columns. It is a more primitive // and the Report columns are within the Grid Column FColumnCount := Columns.Count; if FColumnCount > 0 then begin FRowCount := OwnerGroup.VisibleItems.Count div FColumnCount; if OwnerGroup.VisibleItems.Count mod FColumnCount > 0 then Inc(FRowCount) end else FRowCount := 0 end; procedure TEasyGridGridGroup.SetCellSize(Value: TEasyCellSize); begin OwnerListview.CellSizes.Grid := Value end; { TEasyAlphaBlender} destructor TEasyAlphaBlender.Destroy; begin inherited Destroy; end; procedure TEasyAlphaBlender.BasicBlend(Listview: TCustomEasyListview; ACanvas: TCanvas; ViewportRect: TRect; Color: TColor; Alpha: Byte = 128; UseScrollPostion: Boolean = True); var R: TRect; Obj: THandle; Bits: Windows.BITMAP; begin if Assigned(ACanvas) and Assigned(Listview) and not IsRectEmpty(ViewportRect) then begin Obj := GetCurrentObject(ACanvas.Handle, OBJ_BITMAP); if Obj <> 0 then if GetObject(Obj, SizeOf(Windows.BITMAP), @Bits) > 0 then begin if UseScrollPostion then begin R := Listview.Scrollbars.MapWindowRectToViewRect(Rect(0, 0, Bits.bmWidth, Bits.bmHeight)); IntersectRect(R, ViewportRect, R); R := Listview.Scrollbars.MapViewRectToWindowRect(R); AlphaBlend(0, ACanvas.Handle, R, Point(0, 0), cbmConstantAlphaAndColor, Alpha, ColorToRGB(Color)) end else begin IntersectRect(R, ViewportRect, Listview.ClientRect); AlphaBlend(0, ACanvas.Handle, R, Point(0, 0), cbmConstantAlphaAndColor, Alpha, ColorToRGB(Color)) end end end end; procedure TEasyAlphaBlender.Blend(Listview: TCustomEasyListview; Obj: TEasyCollectionItem; ACanvas: TCanvas; ViewportRect: TRect; Image: TBitmap); var BlendColor: TColor; BlendAlpha: Byte; Scratch: TBitmap; DoBlend: Boolean; begin if not IsRectEmpty(ViewportRect) then begin GetBlendParams(Listview, Obj, BlendAlpha, BlendColor, DoBlend); if DoBlend and HasMMX then begin Scratch := TBitmap.Create; try Scratch.Width := Image.Width; Scratch.Height := Image.Height; Scratch.Assign(Image); Scratch.PixelFormat := pf32Bit; Scratch.TransparentMode := Image.TransparentMode; Scratch.TransparentColor := Image.TransparentColor; Scratch.Transparent := True; // Now force the bitmap to create a mask based on the transparent color Scratch.MaskHandle; // The AlphaBlend function is low level so TBitmap does not know anything happened to it AlphaBlend(0, Scratch.Canvas.Handle, Rect(0, 0, Scratch.Width, Scratch.Height), Point(0, 0), cbmConstantAlphaAndColor, BlendAlpha, ColorToRGB(BlendColor)); // Since we got the mask before the AlphaBlend occured the original mask is // used and all is correct. ACanvas.Draw(ViewportRect.Left + (RectWidth(ViewportRect) - Scratch.Width) div 2, ViewportRect.Top + (RectHeight(ViewportRect) - Scratch.Height) div 2, Scratch); finally Scratch.Free end end else ACanvas.Draw(ViewportRect.Left + (RectWidth(ViewportRect) - Image.Width) div 2, ViewportRect.Top + (RectHeight(ViewportRect) - Image.Height) div 2, Image); end end; procedure TEasyAlphaBlender.GetBlendParams(Listview: TCustomEasyListview; Obj: TEasyCollectionItem; var BlendAlpha: Byte; var BlendColor: TColor; var DoBlend: Boolean); begin DoBlend := False; if Assigned(Listview) then begin if Listview.Focused then begin if Obj.Enabled then begin BlendAlpha := Listview.Selection.BlendAlphaImage; BlendColor := Listview.Selection.Color end else begin BlendAlpha := Listview.DisabledBlendAlpha; BlendColor := Listview.DisabledBlendColor; end end else begin BlendAlpha := Listview.DisabledBlendAlpha; BlendColor := Listview.Selection.InactiveColor; end; DoBlend := Obj.Selected or Obj.Hilighted or (not Obj.Enabled and Listview.Focused) end end; { TEasyBaseTaskBand } constructor TEasyBaseTaskBand.Create(AOwner: TComponent); begin inherited Create(AOwner); BackGround := TEasyTaskBandBackgroundManager.Create(Self); HotTrack.Enabled := True; PaintInfoGroup.CaptionIndent := 9; PaintInfoGroup.MarginBottom.Size := 3; PaintInfoGroup.MarginBottom.Visible := True; PaintInfoGroup.MarginLeft.Size := 11; PaintInfoGroup.MarginLeft.Visible := True; PaintInfoGroup.MarginRight.Size := 11; PaintInfoGroup.MarginRight.Visible := True; PaintInfoGroup.MarginTop.Size := 26; ShowGroupMargins := True; Selection.Enabled := False; HotTrack.GroupTrack := HotTrack.GroupTrack + [htgTopMargin] end; function TEasyBaseTaskBand.CreateColumnPaintInfo: TEasyPaintInfoBaseColumn; begin Result:= TEasyPaintInfoTaskBandColumn.Create(Self) end; function TEasyBaseTaskBand.CreateGroupPaintInfo: TEasyPaintInfoBaseGroup; begin Result := TEasyPaintInfoTaskBandGroup.Create(Self) end; function TEasyBaseTaskBand.CreateItemPaintInfo: TEasyPaintInfoBaseItem; begin Result:= TEasyPaintInfoTaskBandItem.Create(Self) end; function TEasyBaseTaskBand.GetPaintInfoColumn: TEasyPaintInfoTaskBandColumn; begin Result := inherited PaintInfoColumn as TEasyPaintInfoTaskbandColumn end; function TEasyBaseTaskBand.GetPaintInfoGroup: TEasyPaintInfoTaskbandGroup; begin Result := inherited PaintInfoGroup as TEasyPaintInfoTaskbandGroup end; function TEasyBaseTaskBand.GetPaintInfoItem: TEasyPaintInfoTaskBandItem; begin Result := inherited PaintInfoItem as TEasyPaintInfoTaskbandItem end; function TEasyBaseTaskBand.GroupTestExpand(HitInfo: TEasyGroupHitTestInfoSet): Boolean; begin Result:= egtOnHeader in HitInfo end; procedure TEasyBaseTaskBand.DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); begin if Assigned(OnCustomGrid) then OnCustomGrid(Self, Group, ViewStyle, Grid); if not Assigned(Grid) then Grid := TEasyGridTaskBandGroup end; procedure TEasyBaseTaskBand.DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); begin if Assigned(OnGroupCustomView) then OnGroupCustomView(Self, Group, ViewStyle, View); if not Assigned(View) then View := TEasyViewTaskBandGroup end; procedure TEasyBaseTaskBand.DoItemCustomView(Item: TEasyItem; ViewStyle: TEasyListStyle; var View: TEasyViewItemClass); begin if Assigned(OnItemCustomView) then OnItemCustomView(Self, Item, ViewStyle, View); if not Assigned(View) then View := TEasyViewTaskBandItem end; procedure TEasyBaseTaskBand.SetPaintInfoColumn(const Value: TEasyPaintInfoTaskBandColumn); begin inherited PaintInfoColumn := Value end; procedure TEasyBaseTaskBand.SetPaintInfoGroup(const Value: TEasyPaintInfoTaskbandGroup); begin inherited PaintInfoGroup := Value end; procedure TEasyBaseTaskBand.SetPaintInfoItem(const Value: TEasyPaintInfoTaskBandItem); begin inherited PaintInfoItem := Value end; { TGridTaskBandGroup } constructor TEasyGridTaskBandGroup.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner, AnOwnerGroup); CellSize := TEasyCellSize.Create(AnOwner) end; destructor TEasyGridTaskBandGroup.Destroy; begin inherited Destroy; FreeAndNil(FCellSize); end; function TEasyGridTaskBandGroup.GetCellSize: TEasyCellSize; begin FCellSize.FWidth := OwnerListview.ClientWidth - 1 - OwnerListview.PaintInfoGroup.MarginLeft.Size - OwnerListview.PaintInfoGroup.MarginRight.Size; // if OwnerListview.Scrollbars.VertBarVisible then // Dec(FCellSize.FWidth, GetSystemMetrics(SM_CXVSCROLL)); FCellSize.FHeight := 24; Result := FCellSize end; function TEasyGridTaskBandGroup.StaticTopItemMargin: Integer; begin Result := 10; end; function TEasyGridTaskBandGroup.StaticTopMargin: Integer; begin Result := 11; end; procedure TEasyGridTaskBandGroup.SetCellSize(Value: TEasyCellSize); begin end; procedure TEasyGridSingleColumn.AutoSizeCells; begin // Do nothing end; procedure TEasyGridSingleColumn.FindInsertPosition(ViewportPoint: TPoint; var Group: TEasyGroup; var Index: Integer); begin Group := nil; Index := -1 end; function TEasyGridSingleColumn.GetCellSize: TEasyCellSize; begin Result := nil end; { TGridSingleColumn } function TEasyGridSingleColumn.GetMaxColumns(Group: TEasyGroup; WindowWidth: Integer): Integer; begin Result := 1; end; procedure TEasyGridSingleColumn.SetCellSize(Value: TEasyCellSize); begin end; { TEasyViewTaskBandGroup} function TEasyViewTaskBandGroup.DrawThemed: Boolean; begin Result := True end; procedure TEasyViewTaskBandGroup.GetExpandImageSize(Group: TEasyGroup; var ImageW: Integer; var ImageH: Integer); {$IFDEF USETHEMES} var PartID, StateID: LongWord; R: TRect; {$ENDIF} begin ImageW := 0; ImageH := 0; if Group.Expandable then begin {$IFDEF USETHEMES} if Group.OwnerListview.DrawWithThemes then begin StateID := EBNGC_NORMAL; if Group.Expanded then PartID := EBP_NORMALGROUPCOLLAPSE else PartID := EBP_NORMALGROUPEXPAND; if Group.Hilighted then StateID := StateID or EBNGC_HOT; R := Rect(0, 0, 0, 0); // If too small it returns the negative rectangle of the ideal size if Succeeded(GetThemeBackgroundExtent(OwnerListview.Themes.ExplorerBarTheme, 0, PartID, StateID, R, R)) then begin ImageW := Abs(RectWidth(R)); ImageH := Abs(RectHeight(R)); end end else begin ImageW := 16; ImageH := 16; end; {$ELSE} ImageW := 16; ImageH := 16; {$ENDIF} end; end; procedure TEasyViewTaskBandGroup.GroupRectArray(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; var RectArray: TEasyRectArrayObject); // // Grabs all the rectangles for the items within a cell in one call // If PaintInfo is nil then the information is fetched automaticlly // var TextSize: TSize; HeaderBand, FooterBand: TRect; TempRectArray: TEasyRectArrayObject; ImageW, ImageH, ExpandImageW, ExpandImageH: Integer; begin Group.Initialized := True; FillChar(RectArray, SizeOf(RectArray), #0); RectArray.GroupRect := ObjRect; RectArray.BackGndRect := Group.BoundsRectBkGnd; GetExpandImageSize(Group, ExpandImageW, ExpandImageH); GetImageSize(Group, ImageW, ImageH); if MarginEdge in [egmeTop, egmeBottom] then begin // Calculate the Expansion button first for the Header only if Group.Expandable and (MarginEdge = egmeTop) then RectArray.ExpandButtonRect := Rect(RectArray.BackGndRect.Right - Group.ExpandImageIndent - ExpandImageW, RectArray.GroupRect.Top, RectArray.BackGndRect.Right, RectArray.GroupRect.Bottom) else // Make the ExpandButton R a width of 0 RectArray.ExpandButtonRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Top, RectArray.GroupRect.Left, RectArray.GroupRect.Bottom); if (Group.CheckType <> ectNone) and (MarginEdge in [egmeTop]) then begin RectArray.CheckRect := Checks.Bound[Group.Checksize]; OffsetRect(RectArray.CheckRect, RectArray.BackGndRect.Left + Group.CheckIndent, ObjRect.Top + (RectHeight(ObjRect) - RectHeight(RectArray.CheckRect)) div 2); end else begin // CheckRect is a 0 width RectArray.CheckRect := ObjRect; RectArray.CheckRect.Left := RectArray.BackGndRect.Left; RectArray.CheckRect.Right := RectArray.BackGndRect.Left; end; // Now Calculate the image for the header or the footer if Group.ImageIndex > -1 then RectArray.IconRect := Rect(RectArray.CheckRect.Right + Group.ImageIndent, RectArray.GroupRect.Top, RectArray.CheckRect.Right + ImageW + Group.ImageIndent, RectArray.GroupRect.Bottom) else // Make the IconR a width of 0 RectArray.IconRect := Rect(RectArray.CheckRect.Right, RectArray.CheckRect.Top, RectArray.CheckRect.Right, RectArray.CheckRect.Bottom); // Now the Label rect may be calculated for the header or footer RectArray.LabelRect := Rect(RectArray.IconRect.Right + Group.CaptionIndent, RectArray.ExpandButtonRect.Top, RectArray.ExpandButtonRect.Left, RectArray.ExpandButtonRect.Bottom); // Calculate the text size for the text based on the above font if Assigned(OwnerListview.ScratchCanvas) then begin LoadTextFont(Group, OwnerListview.ScratchCanvas); TextSize := TextExtentW(Group.Caption, OwnerListview.ScratchCanvas.Font); end else begin TextSize.cx := 0; TextSize.cy := 0 end; RectArray.TextRect := Rect(RectArray.LabelRect.Left, RectArray.LabelRect.Top, RectArray.LabelRect.Left + TextSize.cx, RectArray.LabelRect.Top + TextSize.cy); if RectArray.TextRect.Right > RectArray.LabelRect.Right then RectArray.TextRect.Right := RectArray.LabelRect.Right; if RectArray.TextRect.Bottom > RectArray.LabelRect.Bottom then RectArray.TextRect.Bottom := RectArray.LabelRect.Bottom; case Group.Alignment of taLeftJustify: OffsetRect(RectArray.TextRect, 0, 0); taRightJustify: OffsetRect(RectArray.TextRect, RectWidth(RectArray.LabelRect) - (RectWidth(RectArray.TextRect)), 0); taCenter: OffsetRect(RectArray.TextRect, (RectWidth(RectArray.LabelRect) - RectWidth(RectArray.TextRect)) div 2, 0); end; case Group.VAlignment of cvaBottom: OffsetRect(RectArray.TextRect, 0, RectHeight(RectArray.GroupRect) - (RectHeight(RectArray.TextRect) + Group.BandThickness + Group.BandMargin)); cvaCenter: OffsetRect(RectArray.TextRect, 0, (RectHeight(RectArray.GroupRect) - RectHeight(RectArray.TextRect)) div 2); end; // Use the calculated label rectangle to position where the text goes if Group.BandEnabled then begin if Group.BandFullWidth then RectArray.BandRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Bottom - Group.BandMargin - Group.BandThickness, RectArray.GroupRect.Right, RectArray.GroupRect.Bottom - Group.BandMargin) else RectArray.BandRect := Rect(RectArray.GroupRect.Left, RectArray.GroupRect.Bottom - Group.BandMargin - Group.BandThickness, RectArray.GroupRect.Left + Group.BandLength, RectArray.GroupRect.Bottom - Group.BandMargin); OffsetRect(RectArray.BandRect, Group.BandIndent, Group.BandMargin); end; end else begin // Calculate the margin rectangles // Need to send nil so the user attributes are fetched for the header GroupRectArray(Group, egmeTop, Group.BoundsRectTopMargin, TempRectArray); HeaderBand := TempRectArray.BandRect; // Need to send nil so the user attributes are fetched for the footer GroupRectArray(Group, egmeBottom, Group.BoundsRectBottomMargin, TempRectArray); FooterBand := TempRectArray.BandRect; if MarginEdge = egmeLeft then RectArray.BandRect := Rect(RectArray.GroupRect.Left + (RectWidth(RectArray.GroupRect) - Group.BandThickness) div 2, HeaderBand.Top, RectArray.GroupRect.Right, FooterBand.Bottom - 1); if MarginEdge = egmeRight then RectArray.BandRect := Rect(RectArray.GroupRect.Left, HeaderBand.Top, RectArray.GroupRect.Right - (RectWidth(RectArray.GroupRect) - Group.BandThickness) div 2, FooterBand.Bottom - 1) end; end; procedure TEasyViewTaskBandGroup.LoadTextFont(Group: TEasyGroup; ACanvas: TCanvas); begin {$IFDEF USETHEMES} inherited LoadTextFont(Group, ACanvas); if not(Group.OwnerListview.DrawWithThemes) then begin if Group.Bold then ACanvas.Font.Color := clHighlightText end; {$ELSE} inherited LoadTextFont(Group, ACanvas); if Group.Bold then ACanvas.Font.Color := clHighlightText {$ENDIF} end; procedure TEasyViewTaskBandGroup.PaintBackground(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); procedure DrawNonThemed; begin if Group.Bold then ACanvas.Brush.Color := clHighlight else ACanvas.Brush.Color := clBtnFace; case MarginEdge of egmeBackground: ACanvas.FrameRect(RectArray.BackGndRect); egmeTop: ACanvas.FillRect(RectArray.GroupRect); end end; {$IFDEF USETHEMES} var PartID, StateID: LongWord; R, HeaderR: TRect; {$ENDIF} begin {$IFDEF USETHEMES} if Group.OwnerListview.DrawWithThemes then begin case MarginEdge of egmeBackground: begin // Draw the group background R := RectArray.BackGndRect; if Group.Bold then PartID := EBP_SPECIALGROUPBACKGROUND else PartID := EBP_NORMALGROUPBACKGROUND; StateID := 0; DrawThemeBackground(OwnerListview.Themes.ExplorerBarTheme, ACanvas.Handle, PartID, StateID, R, nil); end; egmeTop: begin // Draw the group header HeaderR := RectArray.BackGndRect; HeaderR.Bottom := HeaderR.Top - 1; HeaderR.Top := HeaderR.Top - OwnerListview.PaintInfoGroup.MarginTop.RuntimeSize; if Group.Bold then PartID := EBP_SPECIALGROUPHEAD else PartID := EBP_NORMALGROUPHEAD; StateID := 0; DrawThemeBackground(OwnerListview.Themes.ExplorerBarTheme, ACanvas.Handle, PartID, StateID, HeaderR, nil); end end end else DrawNonThemed; Exit; {$ELSE} DrawNonThemed; {$ENDIF} end; procedure TEasyViewTaskBandGroup.PaintBand(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); begin // Don't do inherited end; procedure TEasyViewTaskBandGroup.PaintExpandButton(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); procedure DrawNonThemed; var RCenterX, RCenterY, RCenterY1, RCenterY2: Integer; ExpandW, ExpandH: Integer; R: TRect; begin GetExpandImageSize(Group, ExpandW, ExpandH); if Group.Bold then ACanvas.Pen.Color := clHighlightText else ACanvas.Pen.Color := clBlack; ACanvas.Pen.Width := 1; RCenterX := RectArray.ExpandButtonRect.Left + ExpandW div 2; RCenterY := RectArray.ExpandButtonRect.Top + ((RectHeight(RectArray.ExpandButtonRect)-ExpandH) div 2) + (ExpandH div 2); if Group.Expanded then begin RCenterY2 := RCenterY; RCenterY1 := RCenterY2 - 4; ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX - 4, RCenterY1 + 4); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX + 4, RCenterY1 + 4); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX - 4, RCenterY2 + 4); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX + 4, RCenterY2 + 4); Inc(RCenterY1); Inc(RCenterY2); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX - 3, RCenterY1 + 3); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX + 3, RCenterY1 + 3); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX - 3, RCenterY2 + 3); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX + 3, RCenterY2 + 3); end else begin RCenterY2 := RCenterY; RCenterY1 := RCenterY2 + 4; ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX - 4, RCenterY1 - 4); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX + 4, RCenterY1 - 4); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX - 4, RCenterY2 - 4); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX + 4, RCenterY2 - 4); Dec(RCenterY1); Dec(RCenterY2); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX - 3, RCenterY1 - 3); ACanvas.MoveTo(RCenterX, RCenterY1); ACanvas.LineTo(RCenterX + 3, RCenterY1 - 3); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX - 3, RCenterY2 - 3); ACanvas.MoveTo(RCenterX, RCenterY2); ACanvas.LineTo(RCenterX + 3, RCenterY2 - 3); end; if Group.Hilighted then begin R := Rect(RCenterX - ExpandW div 2, RCenterY - ExpandH div 2, RCenterX + ExpandW div 2, RCenterY + ExpandH div 2); DrawEdge(ACanvas.Handle, R, BDR_RAISEDOUTER, BF_RECT); end end; {$IFDEF USETHEMES} var PartID, StateID: LongWord; {$ENDIF} begin if (MarginEdge = egmeTop) and Group.Expandable then begin {$IFDEF USETHEMES} if Group.OwnerListview.DrawWithThemes then begin StateID := EBNGC_NORMAL; if Group.Bold then begin if Group.Expanded then PartID := EBP_SPECIALGROUPCOLLAPSE else PartID := EBP_SPECIALGROUPEXPAND; end else begin if Group.Expanded then PartID := EBP_NORMALGROUPCOLLAPSE else PartID := EBP_NORMALGROUPEXPAND; end; if Group.Hilighted then StateID := StateID or EBNGC_HOT; DrawThemeBackground(OwnerListview.Themes.ExplorerBarTheme, ACanvas.Handle, PartID, StateID, RectArray.ExpandButtonRect, nil); end else DrawNonThemed; {$ELSE} DrawNonThemed; {$ENDIF} end end; procedure TEasyViewTaskBandGroup.PaintText(Group: TEasyGroup; MarginEdge: TEasyGroupMarginEdge; ACanvas: TCanvas; ObjRect: TRect; RectArray: TEasyRectArrayObject); begin {$IFDEF USETHEMES} if DrawThemed and (MarginEdge = egmeTop) and Group.OwnerListview.DrawWithThemes then begin PaintTextTopThemed(ACanvas, Group, ObjRect, RectArray); end else inherited; {$ELSE} inherited; {$ENDIF} end; procedure TEasyViewTaskBandGroup.PaintTextTopThemed(ACanvas: TCanvas; Group: TEasyGroup; ObjRect: TRect; RectArray: TEasyRectArrayObject); {$IFDEF USETHEMES} var PartID, StateID: LongWord; Flags, Flags2: DWORD; {$ENDIF} begin {$IFDEF USETHEMES} if Group.Bold then PartID := EBP_SPECIALGROUPHEAD else PartID := EBP_NORMALGROUPHEAD; StateID := 0; Flags := 0; case Group.Alignment of taLeftJustify: Flags := Flags or DT_LEFT; taRightJustify: Flags := Flags or DT_RIGHT; taCenter: Flags := Flags or DT_CENTER; end; case Group.VAlignment of cvaTop: Flags := Flags or DT_TOP; cvaCenter: Flags := Flags or DT_VCENTER; cvaBottom: Flags := Flags or DT_BOTTOM; end; Flags := Flags or DT_SINGLELINE or DT_END_ELLIPSIS; if Group.Enabled then Flags2 := 0 else Flags2 := 1; DrawThemeText(OwnerListview.Themes.ExplorerBarTheme, ACanvas.Handle, PartID, StateID, PWideChar(Group.Caption), -1, Flags, Flags2, RectArray.LabelRect); {$ENDIF USETHEMES} end; { TEasyTaskBandBackgroundManager } procedure TEasyTaskBandBackgroundManager.PaintTo(ACanvas: TCanvas; ARect: TRect; PaintDefault: Boolean); {$IFDEF USETHEMES} var PartID, StateID: LongWord; R: TRect; Theme: HTheme; {$ENDIF} begin {$IFDEF USETHEMES} Theme := OwnerListview.Themes.ExplorerBarTheme; if OwnerListview.DrawWithThemes then begin // Draw the blue background R := OwnerListview.ClientRect; PartID := 0; StateID := 0; DrawThemeBackground(Theme, ACanvas.Handle, PartID, StateID, R, nil); end {$ENDIF} end; function TEasyListview.GetPaintInfoColumn: TEasyPaintInfoColumn; begin Result := inherited PaintInfoColumn as TEasyPaintInfoColumn end; function TEasyListview.GetPaintInfoGroup: TEasyPaintInfoGroup; begin Result := inherited PaintInfoGroup as TEasyPaintInfoGroup end; function TEasyListview.GetPaintInfoItem: TEasyPaintInfoItem; begin Result := inherited PaintInfoItem as TEasyPaintInfoItem end; procedure TEasyListview.SetPaintInfoColumn(const Value: TEasyPaintInfoColumn); begin inherited PaintInfoColumn := Value end; procedure TEasyListview.SetPaintInfoGroup(const Value: TEasyPaintInfoGroup); begin inherited PaintInfoGroup := Value end; procedure TEasyListview.SetPaintInfoItem(const Value: TEasyPaintInfoItem); begin inherited PaintInfoItem := Value end; { TCanvasStore } destructor TEasyCanvasStore.Destroy; begin FreeAndNil(FFont); FreeAndNil(FBrush); FreeAndNil(FPen); inherited Destroy; end; procedure TEasyCanvasStore.RestoreCanvasState(Canvas: TCanvas); begin Canvas.Pen.Assign(Pen); Canvas.Brush.Assign(Brush); Canvas.Font.Assign(Font); end; procedure TEasyCanvasStore.StoreCanvasState(Canvas: TCanvas); begin if not Assigned(Pen) then Pen := TPen.Create; if not Assigned(Brush) then Brush := TBrush.Create; if not Assigned(Font) then Font := TFont.Create; Pen.Assign(Canvas.Pen); Brush.Assign(Canvas.Brush); Font.Assign(Canvas.Font) end; procedure TEasyMemoEditor.CalculateEditorRect(NewText: WideString; var NewRect: TRect); var DrawFlags: TCommonDrawTextWFlags; DC: HDC; Font, OldFont: HFont; TextM: TTextMetric; begin OldFont := 0; if NewText = '' then NewText := ' '; Font := GetEditorFont.Handle; DrawFlags := [dtCalcRectAdjR, dtCalcRect, dtCalcRectAlign]; // Center horizontally for multi-line edits DrawFlags := DrawFlags + [dtCenter]; DC := GetDC(Editor.Handle); try OldFont := SelectObject(DC, Font); NewRect := RectArray.LabelRect; InflateRect(NewRect, -4, -2); NewRect := Listview.Scrollbars.MapViewRectToWindowRect(NewRect); DrawTextWEx(DC, NewText, NewRect, DrawFlags, -1); InflateRect(NewRect, H_STRINGEDITORMARGIN, V_STRINGEDITORMARGIN + 1); GetTextMetrics(DC, TextM); if NewRect.Right > Listview.ClientWidth - TextM.tmAveCharWidth + H_STRINGEDITORMARGIN then NewRect.Right := Listview.ClientWidth - TextM.tmAveCharWidth + H_STRINGEDITORMARGIN; if NewRect.Bottom > Listview.ClientHeight - V_STRINGEDITORMARGIN then NewRect.Bottom := Listview.ClientHeight - V_STRINGEDITORMARGIN; // Center horizontally for multi-line edits NewRect.Right := NewRect.Left + RectWidth(NewRect) finally if OldFont <> 0 then SelectObject(DC, OldFont); ReleaseDC(Editor.Handle, DC); end end; procedure TEasyMemoEditor.CreateEditor(var AnEditor: TWinControl; Column: TEasyColumn; Parent: TWinControl); var Memo: TEasyMemo; begin AnEditor := TEasyMemo.Create(nil); Memo := (AnEditor as TEasyMemo); Memo.Visible := False; Memo.Parent := Listview; // Do this first or it resets at least BorderStyle to True Memo.Alignment := taCenter; Memo.Text := EditText(Item, Column); Memo.OnKeyDown := OnEditKeyDown; {$IFDEF USETHEMES} if not Listview.Themed then {$ENDIF USETHEMES} begin Memo.Ctl3D := False; Memo.BorderStyle := bsSingle; {$IFDEF COMPILER_6_UP} Memo.BevelInner := bvNone; Memo.BevelOuter := bvNone; Memo.BevelKind := bkNone; {$ENDIF} end end; function TEasyMemoEditor.GetEditorFont: TFont; begin Result := (Editor as TEasyMemo).Font end; function TEasyMemoEditor.GetText: VAriant; begin Result := (Editor as TEasyMemo).Text end; procedure TEasyMemoEditor.DoEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState; var DoDefault: Boolean); begin end; procedure TEasyMemoEditor.OnEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); // // Check to see if the user is finished, if not test to see if the edit needs // to be resized to reflect the new text // var DoDefault: Boolean; begin DoDefault := True; DoEditKeyDown(Sender, Key, Shift, DoDefault); if DoDefault then begin if Key = VK_RETURN then begin Key := 0; AcceptEdit; end else if Key = VK_F2 then begin SelectAll end else PostMessage(Editor.Handle, WM_EDITORRESIZE, 0, 0); end; FModified := True; end; procedure TEasyMemoEditor.SelectAll; begin (Editor as TEasyMemo).SelectAll; end; procedure TEasyMemoEditor.SetEditorFocus; begin inherited SetEditorFocus; SelectAll; end; { TEasyStringEditor} procedure TEasyStringEditor.CalculateEditorRect(NewText: WideString; var NewRect: TRect); var DrawFlags: TCommonDrawTextWFlags; DC: HDC; Font, OldFont: HFont; TextM: TTextMetric; begin OldFont := 0; if NewText = '' then NewText := ' '; Font := GetEditorFont.Handle; DrawFlags := [dtCalcRectAdjR, dtCalcRect, dtCalcRectAlign]; DrawFlags := DrawFlags + [dtLeft, dtVCenter]; DC := GetDC(Editor.Handle); try OldFont := SelectObject(DC, Font); NewRect := RectArray.LabelRect; InflateRect(NewRect, -4, -2); NewRect := Listview.Scrollbars.MapViewRectToWindowRect(NewRect); DrawTextWEx(DC, NewText, NewRect, DrawFlags, 1); InflateRect(NewRect, H_STRINGEDITORMARGIN div 2, V_STRINGEDITORMARGIN); GetTextMetrics(DC, TextM); if NewRect.Right > Listview.ClientWidth - TextM.tmAveCharWidth + H_STRINGEDITORMARGIN then NewRect.Right := Listview.ClientWidth - TextM.tmAveCharWidth + H_STRINGEDITORMARGIN; if NewRect.Bottom > Listview.ClientHeight - V_STRINGEDITORMARGIN then NewRect.Bottom := Listview.ClientHeight - V_STRINGEDITORMARGIN; NewRect.Right := NewRect.Left + RectWidth(NewRect) + TextM.tmAveCharWidth; finally if OldFont <> 0 then SelectObject(DC, OldFont); ReleaseDC(Editor.Handle, DC); end end; procedure TEasyStringEditor.CreateEditor(var AnEditor: TWinControl; Column: TEasyColumn; Parent: TWinControl); var Edit: TEasyEdit; begin AnEditor := TEasyEdit.Create(nil); Edit := AnEditor as TEasyEdit; Edit.Visible := False; Edit.Parent := Listview; // Do this first or it resets at least BorderStyle to True Edit.Text := EditText(Item, Column); Edit.OnKeyDown := OnEditKeyDown; {$IFDEF USETHEMES} if not Listview.Themed then {$ENDIF USETHEMES} begin Edit.Ctl3D := False; Edit.BorderStyle := bsSingle; {$IFDEF COMPILER_6_UP} Edit.BevelInner := bvNone; Edit.BevelOuter := bvNone; Edit.BevelKind := bkNone; {$ENDIF} end end; function TEasyStringEditor.GetEditorFont: TFont; begin Result := (Editor as TEasyEdit).Font end; function TEasyStringEditor.GetText: Variant; begin Result := (Editor as TEasyEdit).Text end; procedure TEasyStringEditor.DoEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState; var DoDefault: Boolean); begin end; procedure TEasyStringEditor.OnEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); // // Check to see if the user is finished, if not test to see if the edit needs // to be resized to reflect the new text // var DoDefault: Boolean; begin DoDefault := True; DoEditKeyDown(Sender, Key, Shift, DoDefault); if DoDefault then begin if Key = VK_RETURN then begin Key := 0; AcceptEdit; end else if Key = VK_F2 then begin SelectAll end else PostMessage(Editor.Handle, WM_EDITORRESIZE, 0, 0); end; FModified := True; end; procedure TEasyStringEditor.SelectAll; begin (Editor as TEasyEdit).SelectAll; end; procedure TEasyStringEditor.SetEditorFocus; begin inherited SetEditorFocus; SelectAll; end; { TEasyTaskPanelBand } constructor TEasyTaskPanelBand.Create(AOwner: TComponent); begin inherited Create(AOwner); Groups.FItemClass := TEasyGroupTaskPanel; end; function TEasyTaskPanelBand.CreateGroups: TEasyGroups; begin Result := TEasyGroupsTaskPanel.Create(Self) end; function TEasyTaskPanelBand.GetGroups: TEasyGroupsTaskPanel; begin Result := inherited Groups as TEasyGroupsTaskPanel end; procedure TEasyTaskPanelBand.CMMouseWheel(var Msg: TCMMouseWheel); begin inherited; PositionPanels end; procedure TEasyTaskPanelBand.DoCustomGrid(Group: TEasyGroup; ViewStyle: TEasyListStyle; var Grid: TEasyGridGroupClass); begin if Assigned(OnCustomGrid) then OnCustomGrid(Self, Group, ViewStyle, Grid); if not Assigned(Grid) then Grid := TEasyGridGroupTaskPanel end; procedure TEasyTaskPanelBand.DoGroupCustomView(Group: TEasyGroup; ViewStyle: TEasyListStyle; var View: TEasyViewGroupClass); begin if Assigned(OnGroupCustomView) then OnGroupCustomView(Self, Group, ViewStyle, View); if not Assigned(View) then View := TEasyViewTaskPanelGroup end; procedure TEasyTaskPanelBand.DoGetTaskPanel(Sender: TEasyGroupTaskPanel; var TaskPanel: TEasyTaskPanelFormClass); begin if Assigned(OnGetTaskPanel) then OnGetTaskPanel(Self, Sender, TaskPanel) end; procedure TEasyTaskPanelBand.DoGroupExpand(Group: TEasyGroup); begin inherited DoGroupExpand(Group); PositionPanels; end; procedure TEasyTaskPanelBand.PositionPanels; var i: Integer; DeferHandle: THandle; TaskPanel: TEasyTaskPanelForm; MappedR: TRect; begin SendMessage(Handle, WM_SETREDRAW, 0, 0); try Groups.Rebuild(True); // MUST MAKE SURE NEVER TO MAKE THE PANELS NOT VISIBLE FOR THIS TO WORK DeferHandle := BeginDeferWindowPos(Groups.Count); for i := 0 to Groups.Count - 1 do begin if not (Groups[i] as TEasyGroupTaskPanel).TaskWindowCreated then (Groups[i] as TEasyGroupTaskPanel).CreateTaskWindow; TaskPanel := (Groups[i] as TEasyGroupTaskPanel).TaskPanel; MappedR := Scrollbars.MapViewRectToWindowRect(Groups[i].BoundsRectBkGnd, True); if (DeferHandle <> 0) and Assigned(TaskPanel) and not IsRectEmpty(MappedR) then begin if not TaskPanel.Themed then InflateRect(MappedR, -1, -1); // Make sure the frame shows TaskPanel.Visible := True; if (MappedR.Left <> TaskPanel.Left) or (MappedR.Top <> TaskPanel.Top) or (TaskPanel.Width <> RectWidth(MappedR)) or (TaskPanel.Height <> RectHeight(MappedR)) then begin DeferHandle := DeferWindowPos(DeferHandle, TaskPanel.Handle, 0, MappedR.Left, MappedR.Top, RectWidth(MappedR), RectHeight(MappedR), SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOZORDER); end end end; if (DeferHandle <> 0) then EndDeferWindowPos(DeferHandle) finally SendMessage(Handle, WM_SETREDRAW, 1, 0); RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_ERASENOW or RDW_UPDATENOW or RDW_ALLCHILDREN or RDW_FRAME); end end; procedure TEasyTaskPanelBand.SetGroups(const Value: TEasyGroupsTaskPanel); begin inherited Groups := Value end; procedure TEasyTaskPanelBand.WMHScroll(var Msg: TWMHScroll); begin inherited; PositionPanels; end; procedure TEasyTaskPanelBand.WMVScroll(var Msg: TWMVScroll); begin inherited; PositionPanels; end; procedure TEasyTaskPanelBand.WMWindowPosChanging(var Msg: TWMWindowPosChanging); begin inherited; PositionPanels end; { TEasyGroupsTaskPanel } constructor TEasyGroupsTaskPanel.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); end; function TEasyGroupsTaskPanel.GetGroup(Index: Integer): TEasyGroupTaskPanel; begin Result := inherited Groups[Index] as TEasyGroupTaskPanel end; procedure TEasyGroupsTaskPanel.SetGroup(Index: Integer; Value: TEasyGroupTaskPanel); begin inherited Groups[Index] := Value end; { TEasyGridGroupPanel } constructor TEasyGridGroupTaskPanel.Create(AnOwner: TCustomEasyListview; AnOwnerGroup: TEasyGroup); begin inherited Create(AnOwner, AnOwnerGroup); FCellSize := TEasyCellSize.Create(AnOwner); end; destructor TEasyGridGroupTaskPanel.Destroy; begin FreeAndNil(FCellSize); inherited Destroy; end; function TEasyGridGroupTaskPanel.GetCellSize: TEasyCellSize; begin Result := FCellSize end; function TEasyGridGroupTaskPanel.StaticTopMargin: Integer; begin Result := 10; end; procedure TEasyGridGroupTaskPanel.Rebuild(PrevGroup: TEasyGroup; var NextVisibleItemIndex: Integer); var Top: Integer; TaskGroup: TEasyGroupTaskPanel; begin AutoSizeCells; if Assigned(PrevGroup) then Top := PrevGroup.DisplayRect.Bottom else Top := StaticTopMargin; TaskGroup := FOwnerGroup as TEasyGroupTaskPanel; if FOwnerGroup.Expanded then TaskGroup.DisplayRect := Rect(0, Top, OwnerListview.ClientWidth, Top + TaskGroup.Height + TaskGroup.MarginBottom.Size + TaskGroup.MarginTop.Size) else FOwnerGroup.DisplayRect := Rect(0, Top, OwnerListview.ClientWidth, Top + TaskGroup.MarginTop.Size + TaskGroup.MarginBottom.Size); end; procedure TEasyGridGroupTaskPanel.SetCellSize(Value: TEasyCellSize); begin CellSize.Width := Value.Width; CellSize.Height := Value.Height end; { TEasyGroupTaskPanel } constructor TEasyGroupTaskPanel.Create(ACollection: TEasyCollection); begin inherited Create(ACollection); FHeight := 200; end; destructor TEasyGroupTaskPanel.Destroy; begin if Assigned(TaskPanel) then TaskPanel.Free; //Close; FTaskPanel := nil; inherited Destroy; end; function TEasyGroupTaskPanel.GetTaskWindowCreated: Boolean; begin Result := Assigned(FTaskPanel) end; procedure TEasyGroupTaskPanel.CreateTaskWindow; var TaskPanelClass: TEasyTaskPanelFormClass; begin if (not Assigned(TaskPanel)) and not (csDesigning in OwnerListview.ComponentState) then begin TaskPanelClass := nil; TEasyTaskPanelBand(OwnerListview).DoGetTaskPanel(Self, TaskPanelClass); if Assigned(TaskPanelClass) then begin FTaskPanel := TaskPanelClass.Create(nil); // the Group owns the panel TForm( TaskPanel).AutoScroll := (OwnerListview as TEasyTaskPanelBand).AutoScrollPanels; TaskPanel.Themed := OwnerListview.Themed; TaskPanel.Width := RectWidth(BoundsRectBkGnd); TaskPanel.Height := RectHeight(BoundsRectBkGnd); TaskPanel.Top := BoundsRectBkGnd.Top; TaskPanel.Left := BoundsRectBkGnd.Left; TaskPanel.Visible := False; TaskPanel.Parent := OwnerListview; // Make it visible when the grid is rebuilt so it won't flicker end end; end; procedure TEasyGroupTaskPanel.LoadFromStream(S: TStream; var Version: Integer); begin inherited LoadFromStream(S, Version); S.Read(FHeight, SizeOf(FHeight)); // For new objects test the stream version first // if Version > X then // begin // ReadStream.... // end end; procedure TEasyGroupTaskPanel.SaveToStream(S: TStream; Version: Integer = EASYLISTVIEW_STREAM_VERSION); begin inherited SaveToStream(S); S.Write(FHeight, SizeOf(FHeight)); // For new objects test the stream version first // if Version > X then // begin // WriteStream.... // end end; procedure TEasyGroupTaskPanel.SetExpanded(Value: Boolean); begin inherited SetExpanded(Value); if Assigned(TaskPanel) then begin if Expanded then TaskPanel.Height := Height else TaskPanel.Height := 0 end end; procedure TEasyGroupTaskPanel.SetHeight(const Value: Integer); begin if FHeight <> Value then begin FHeight := Value; OwnerGroups.Rebuild(True) end end; procedure TEasyGroupTaskPanel.SetInitialized(Value: Boolean); begin inherited SetInitialized(Value); end; { TEasyViewTaskPanelGroup } procedure TEasyViewTaskPanelGroup.PaintBefore(Group: TEasyGroup; ACanvas: TCanvas; MarginEdge: TEasyGroupMarginEdge; ObjRect: TRect; RectArray: TEasyRectArrayObject); begin inherited PaintBefore(Group, ACanvas, MarginEdge, ObjRect, RectArray); end; { TEasyTaskBand } procedure TEasyTaskBand.DoGroupCollapse(Group: TEasyGroup); begin // PositionPanels; inherited DoGroupCollapse(Group); end; procedure TEasyTaskBand.DoGroupExpand(Group: TEasyGroup); begin // PositionPanels; inherited DoGroupExpand(Group); end; { TEasyGestureManager } constructor TEasyGestureManager.Create(AnOwner: TCustomEasyListview); begin inherited Create(AnOwner); FTolerance := 3; FButton := [cmbRight] end; { TEasyColumnDropDownButton} constructor TEasyColumnDropDownButton.Create(AnOwner: TEasyColumn); begin inherited Create; FOwner := AnOwner; FEnabled := True end; procedure TEasyColumnDropDownButton.SetAlwaysShow(const Value: Boolean); begin if Value <> FAlwaysShow then begin FAlwaysShow := Value; Owner.Invalidate(False) end; end; procedure TEasyColumnDropDownButton.SetEnabled(const Value: Boolean); begin if Value <> FEnabled then begin FEnabled := Value; Owner.Invalidate(False) end; end; procedure TEasyColumnDropDownButton.SetVisible(const Value: Boolean); begin if Value <> FVisible then begin FVisible := Value; Owner.Invalidate(False) end; end; initialization OleInitialize(nil); Screen.Cursors[crVHeaderSplit] := LoadCursor(hInstance, CURSOR_VHEADERSPLIT); HeaderClipboardFormat := RegisterClipboardFormat(EASYLISTVIEW_HEADER_CLIPFORMAT); AlphaBlender := TEasyAlphaBlender.Create; RegisterClass(TEasyGroup); RegisterClass(TEasyGroupVirtual); RegisterClass(TEasyGroupInterfaced); RegisterClass(TEasyGroupStored); RegisterClass(TEasyGroupTaskPanel); RegisterClass(TEasyItem); RegisterClass(TEasyItemVirtual); RegisterClass(TEasyItemInterfaced); RegisterClass(TEasyItemStored); RegisterClass(TEasyColumn); RegisterClass(TEasyColumnVirtual); RegisterClass(TEasyColumnInterfaced); RegisterClass(TEasyColumnStored); finalization FreeAndNil(AlphaBlender); OleUnInitialize(); end.