Files
lazarus-ccr/components/jvcllaz/run/JvTimeFramework/jvtfdays.pas
2020-05-06 10:40:05 +00:00

14943 lines
409 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvTFDays.PAS, released on 2003-08-01.
The Initial Developer of the Original Code is Unlimited Intelligence Limited.
Portions created by Unlimited Intelligence Limited are Copyright (C) 1999-2002 Unlimited Intelligence Limited.
All Rights Reserved.
Contributor(s):
Mike Kolter (original code)
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.delphi-jedi.org
Known Issues:
This version of the source contains modifications which enable the use
of time blocks. These modifications can be found by doing a search for
"DEF Jv_TIMEBLOCKS". Previously, two versions were released; one which did
NOT support timeblocks and one which did support timeblocks. (Hence the
use of the compiler defines.)
These two versions are in the process of being integrated. The compiler
defines remain as an indicator of exactly what has been changed. All
lines that are NOT compiled ($IFNDEF Jv_TIMEBLOCKS and $ELSE) remain
as a reference during the transition, but have been commented out to
reduce confusion. Many of these lines are marked by a "// remove" comment.
The conditional defines and disabled code will be removed and this file
will be cleaned up after the time block code has been fully integrated
and tested.
Changes to JvTFDays by deanh:
============================
These changes peform the following functions.
1) The addition of a new time entry is aborted if the user presses escape.
2) New property for FancyHeader to only show the '00' minutes. This emulates outlook's behaviour.
3) Few changes to clean up the dithering of the background.
4) Hide the blank area that sometimes appears at the bottom of the Calendar when scrolling right down to the bottom.
5) Remove the focus rectangle when ShowFocus is false (the focus rect is not shown in Outlook).
-----------------------------------------------------------------------------}
// $Id$
unit JvTFDays;
{$mode objfpc}{$H+}
{$define Jv_TIMEBLOCKS}
interface
uses
LCLIntf, LCLType, LMessages, LCLVersion, Types,
SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ImgList,
JvTFManager, JvTFSparseMatrix, JvTFUtils;
const
SizingThreshold = 5;
gcUndef = -3;
gcGroupHdr = -2;
gcHdr = -1;
DEFAULT_APPT_BAR_WIDTH = 5;
DEFAULT_BLOCK_HDR_WIDTH = 50;
DEFAULT_COL_HDR_HEIGHT = 28;
DEFAULT_DEF_COL_WIDTH = 100;
DEFAULT_GRAB_HANDLES_HEIGHT = 6;
DEFAULT_GRANULARITY = 30;
DEFAULT_GROUP_HDR_HEIGHT = 28;
DEFAULT_MIN_COL_WIDTH = 5;
DEFAULT_MIN_ROW_HEIGHT = 12;
DEFAULT_PRIMETIME_COLOR = $00C4FFFF;
DEFAULT_ROW_HDR_WIDTH = 60;
DEFAULT_ROW_HEIGHT = 20;
PIC_DIST = 2;
type
EJvTFDaysError = class(Exception);
{$IFDEF Jv_TIMEBLOCKS}
// remove TTFDayOfWeek and TTFDaysOfWeek, they are found in JvTFUtils
//TTFDayOfWeek = (dowSunday, dowMonday, dowTuesday, dowWednesday,
// dowThursday, dowFriday, dowSaturday);
//TTFDaysOfWeek = set of TTFDayOfWeek;
EJvTFBlockGranError = class(EJvTFDaysError);
{$ENDIF Jv_TIMEBLOCKS}
// Forward declarations
TJvTFDays = class;
TJvTFDaysCols = class;
TJvTFDaysCol = class;
TJvTFDaysPrinter = class;
TJvTFDaysTemplate = class;
TJvTFDaysHdrAttr = class;
{$IFDEF Jv_TIMEBLOCKS}
// okay to leave
TJvTFDaysTimeBlocks = class;
TJvTFDaysTimeBlock = class;
{$ENDIF Jv_TIMEBLOCKS}
TJvTFDaysCoord = record
Col: Integer;
Row: Integer;
CellX: Integer;
CellY: Integer;
AbsX: Integer;
AbsY: Integer;
Schedule: TJvTFSched;
Appt: TJvTFAppt;
DragAccept: Boolean;
end;
TJvTFDrawPicInfo = class(TObject)
public
ImageList: TCustomImageList;
ImageIndex: Integer;
Glyph: TGraphic;
PicLeft: Integer;
PicTop: Integer;
end;
TJvTFDaysTemplates = (agtNone, agtLinear, agtComparative);
TJvTFListMoveEvent = procedure(Sender: TObject; CurIndex, NewIndex: Integer) of object;
TJvTFCompNamesList = class(TStringList)
private
FOnMove: TJvTFListMoveEvent;
public
procedure Move(CurIndex, NewIndex: Integer); override;
property OnMove: TJvTFListMoveEvent read FOnMove write FOnMove;
end;
TJvTFDaysTemplate = class(TPersistent)
private
FActiveTemplate: TJvTFDaysTemplates;
FCompDate: TDate;
FCompNames: TJvTFCompNamesList;
FLinearDayCount: Integer;
FLinearEndDate: TDate;
FLinearName: string;
FLinearStartDate: TDate;
FShortTitles: Boolean;
FUpdatingGrid: Boolean;
// Property Access Methods
function GetCompNames: TStrings;
procedure SetActiveTemplate(Value: TJvTFDaysTemplates);
procedure SetCompDate(Value: TDate);
procedure SetCompNames(Value: TStrings);
procedure SetLinearDayCount(Value: Integer);
procedure SetLinearEndDate(Value: TDate);
procedure SetLinearName(const Value: string);
procedure SetLinearStartDate(Value: TDate);
procedure SetShortTitles(Value: Boolean);
protected
FCompNamesChanged: Boolean;
FGrid: TJvTFDays;
FUpdatingCompNames: Boolean;
FIgnoreNav: Boolean;
procedure DoDateChangedEvent;
procedure DoDateChangingEvent(var NewDate: TDate);
procedure CompNamesChanged(Sender: TObject); virtual;
procedure CompNamesMoved(Sender: TObject; CurIndex, NewIndex: Integer); virtual;
procedure LinearDaysChanged; virtual;
procedure BeginGridUpdate;
procedure EndGridUpdate;
public
constructor Create(AApptGrid: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure BeginCompNamesUpdate;
procedure EndCompNamesUpdate;
procedure UpdateGrid;
property UpdatingGrid: Boolean read FUpdatingGrid;
property ApptGrid: TJvTFDays read FGrid;
published
property ActiveTemplate: TJvTFDaysTemplates read FActiveTemplate write SetActiveTemplate default agtNone;
property CompDate: TDate read FCompDate write SetCompDate;
property CompNames: TStrings read GetCompNames write SetCompNames;
property IgnoreNav: Boolean read FIgnoreNav write FIgnoreNav default False;
property LinearDayCount: Integer read FLinearDayCount write SetLinearDayCount;
property LinearEndDate: TDate read FLinearEndDate write SetLinearEndDate;
property LinearName: string read FLinearName write SetLinearName;
property LinearStartDate: TDate read FLinearStartDate write SetLinearStartDate;
property ShortTitles: Boolean read FShortTitles write SetShortTitles default True;
end;
TJvTFDaysPrimeTime = class(TPersistent)
private
FStartTime: TTime;
FEndTime: TTime;
FColor: TColor;
procedure SetStartTime(Value: TTime);
procedure SetEndTime(Value: TTime);
procedure SetColor(Value: TColor);
protected
FApptGrid: TJvTFDays;
FFillPic: TBitmap;
procedure Change;
procedure UpdateFillPic;
public
constructor Create(AApptGrid: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
published
property StartTime: TTime read FStartTime write SetStartTime;
property EndTime: TTime read FEndTime write SetEndTime;
property Color: TColor read FColor write SetColor default DEFAULT_PRIMETIME_COLOR;
end;
TJvTFCreateQuickEntryEvent = procedure(Sender: TObject; var ApptID: string;
var StartDate: TDate; var StartTime: TTime; var EndDate: TDate;
var EndTime: TTime; var Confirm: Boolean) of object;
TJvTFDropApptEvent = procedure(Appt: TJvTFAppt; SchedName: string;
NewStartDate: TDate; NewStartTime: TTime; NewEndDate: TDate;
NewEndTime: TTime; Share: Boolean; var Confirm: Boolean) of object;
TJvTFDragRowColEvent = procedure(Sender: TObject; Index: Integer;
var NewInfo: Integer; var Confirm: Boolean) of object;
TJvTFSizeApptEvent = procedure(Sender: TObject; Appt: TJvTFAppt;
var NewEndDT: TDateTime; var Confirm: Boolean) of object;
TJvTFSelecTJvTFApptEvent = procedure(Sender: TObject; OldSel, NewSel: TJvTFAppt) of object;
TJvTFDrawApptEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Appt: TJvTFAppt; Selected: Boolean) of object;
TJvTFDrawGrabHandleEvent = procedure(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Appt: TJvTFAppt; TopHandle: Boolean) of object;
TJvTFDrawDataCellEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Col, Row: Integer) of object;
TJvTFDaysCorner = (agcTopLeft, agcTopRight, agcBottomLeft, agcBottomRight);
TJvTFDrawCornerEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Corner: TJvTFDaysCorner) of object;
TJvTFDrawHdrEvent = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
Index: Integer; Selected: Boolean) of object;
TJvTFDrawApptBarEvent = procedure(Sender: TObject; ACanvas: TCanvas;
Appt: TJvTFAppt; Col: Integer; BarRect, TimeStampRect: TRect) of object;
TJvTFFailEditorEvent = procedure(Sender: TObject; Col: Integer; Appt: TJvTFAppt;
var EditorBounds: TRect; var Fail: Boolean) of object;
TJvTFDateChangingEvent = procedure(Sender: TObject; var NewDate: TDate) of object;
TJvTFGranChangingEvent = procedure(Sender: TObject; var NewGran: Integer) of object;
TJvTFShadeCellEvent = procedure(Sender: TObject; ColIndex, RowIndex: Integer;
var CellColor: TColor) of object;
TJvTFBeginEditEvent = procedure(Sender: TObject; Appt: TJvTFAppt;
var AllowEdit: Boolean) of object;
TJvTFInPlaceApptEditor = class(TMemo)
private
FLinkedAppt: TJvTFAppt;
FQuickCreate: Boolean;
protected
FCancelEdit: Boolean;
procedure DoExit; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
public
constructor Create(AOwner: TComponent); override;
property LinkedAppt: TJvTFAppt read FLinkedAppt write FLinkedAppt;
property QuickCreate: Boolean read FQuickCreate write FQuickCreate;
end;
TJvTFApptMap = class(TObject)
private
FData: TJvTFSparseMatrix;
function GetLocation(Row, Col: Integer): TJvTFAppt;
protected
FGridCol: TJvTFDaysCol;
procedure Add(Appt: TJvTFAppt);
procedure ProcessMapGroup(GroupStart, GroupEnd: Integer);
procedure UpdateMapGroups;
public
constructor Create(AGridCol: TJvTFDaysCol); virtual;
destructor Destroy; override;
procedure Clear;
function ColCount(Row: Integer): Integer;
procedure GetAppts(StartRow, EndRow: Integer; ApptList: TStringList);
function LocateMapCol(Appt: TJvTFAppt; MapSearchRow: Integer): Integer;
property Location[Row, Col: Integer]: TJvTFAppt read GetLocation;
procedure Refresh;
function HasAppt(Appt: TJvTFAppt): Boolean;
procedure Dump(AName: TFileName); // used for debugging only
end;
TJvTFDaysOption = (agoSizeCols, agoSizeRows, agoSizeColHdr, agoSizeRowHdr,
agoMoveCols, agoSizeAppt, agoMoveAppt, agoSnapMove,
agoSnapSize, agoEditing, agoShowPics, agoShowText,
agoShowApptHints, agoShowColHdrHints, agoShowSelHint,
agoEnforceMaxColWidth, agoQuickEntry, agoFormattedDesc);
TJvTFDaysOptions = set of TJvTFDaysOption;
TJvTFDaysState = (agsNormal, agsSizeCol, agsSizeRow, agsSizeColHdr,
agsSizeRowHdr, agsMoveCol, agsSizeAppt, agsMoveAppt);
{$IFDEF Jv_TIMEBLOCKS}
// ok
TJvTFColTitleStyle = (ctsSingleClip, ctsSingleEllipsis, ctsMultiClip,
ctsMultiEllipsis, ctsHide, ctsRotated);
{$ELSE}
// remove
//TJvTFColTitleStyle = (ctsSingleClip, ctsSingleEllipsis, ctsMultiClip,
// ctsMultiEllipsis, ctsHide);
{$ENDIF Jv_TIMEBLOCKS}
TJvTFDaysThresholds = class(TPersistent)
private
FDetailHeight: Integer;
FDetailWidth: Integer;
FEditHeight: Integer;
FEditWidth: Integer;
FTextHeight: Integer;
FTextWidth: Integer;
FDropTextFirst: Boolean;
FPicsAllOrNone: Boolean;
FWholePicsOnly: Boolean;
procedure SetDetailHeight(Value: Integer);
procedure SetDetailWidth(Value: Integer);
procedure SetEditHeight(Value: Integer);
procedure SetEditWidth(Value: Integer);
procedure SetTextHeight(Value: Integer);
procedure SetTextWidth(Value: Integer);
procedure SetDropTextFirst(Value: Boolean);
procedure SetPicsAllOrNone(Value: Boolean);
procedure SetWholePicsOnly(Value: Boolean);
protected
FApptGrid: TJvTFDays;
procedure Change; dynamic;
public
constructor Create(AOwner: TJvTFDays);
procedure Assign(Source: TPersistent); override;
published
property DetailHeight: Integer read FDetailHeight write SetDetailHeight default 10;
property DetailWidth: Integer read FDetailWidth write SetDetailWidth default 10;
property EditHeight: Integer read FEditHeight write SetEditHeight default 1;
property EditWidth: Integer read FEditWidth write SetEditWidth default 10;
property TextHeight: Integer read FTextHeight write SetTextHeight default 1;
property TextWidth: Integer read FTextWidth write SetTextWidth default 10;
property DropTextFirst: Boolean read FDropTextFirst write SetDropTextFirst default True;
property PicsAllOrNone: Boolean read FPicsAllOrNone write SetPicsAllOrNone default False;
property WholePicsOnly: Boolean read FWholePicsOnly write SetWholePicsOnly default True;
end;
TJvTFDaysScrollBar = class(TScrollBar)
protected
procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
procedure CreateWnd; override;
function GetLargeChange: Integer; virtual;
procedure SetLargeChange(Value: Integer); virtual;
procedure UpdateRange; virtual;
public
constructor Create(AOwner: TComponent); override;
published
property LargeChange: Integer read GetLargeChange write SetLargeChange default 1;
end;
//TJvTFUpdateTitleEvent = Procedure(Sender: TObject; Col: TJvTFDaysCol;
//var NewTitle: string) of object;
TJvTFUpdateTitlesEvent = procedure(Sender: TObject; Col: TJvTFDaysCol;
var NewGroupTitle, NewTitle: string) of object;
{$IFDEF Jv_TIMEBLOCKS}
// ok
TJvTFDaysTimeBlock = class(TCollectionItem)
private
FLength: Integer;
FTitle: string;
FName: string;
FAllowAppts: Boolean;
procedure SetLength(Value: Integer);
procedure SetTitle(const Value: string);
procedure SetName(const Value: string);
procedure SetAllowAppts(Value: Boolean);
function GetGridLength: Integer;
function GetBlockCollection: TJvTFDaysTimeBlocks;
protected
function GetDisplayName: string; override;
procedure Change;
public
constructor Create(ACollection: TCollection); override;
procedure Assign(Source: TPersistent); override;
property BlockCollection: TJvTFDaysTimeBlocks read GetBlockCollection;
published
property AllowAppts: Boolean read FAllowAppts write SetAllowAppts default True;
property GridLength: Integer read GetGridLength;
property Length: Integer read FLength write SetLength default 1;
property Name: string read FName write SetName;
property Title: string read FTitle write SetTitle;
end;
// ok
TJvTFDaysTimeBlocks = class(TCollection)
private
FDaysControl: TJvTFDays;
function GetItem(Index: Integer): TJvTFDaysTimeBlock;
procedure SetItem(Index: Integer; Value: TJvTFDaysTimeBlock);
protected
function GetOwner: TPersistent; override;
public
constructor Create(ADaysControl: TJvTFDays);
function Add: TJvTFDaysTimeBlock;
property DaysControl: TJvTFDays read FDaysControl;
procedure Assign(Source: TPersistent); override;
property Items[Index: Integer]: TJvTFDaysTimeBlock read GetItem
write SetItem; default;
function BlockByName(const BlockName: string): TJvTFDaysTimeBlock;
function FindBlock(const BlockName: string): TJvTFDaysTimeBlock;
end;
// ok
TJvTFDaysBlockProps = class(TPersistent)
private
FBlockGran: Integer;
FDayStart: TTime;
FDaysControl: TJvTFDays;
FBlockHdrAttr: TJvTFDaysHdrAttr;
FSelBlockHdrAttr: TJvTFDaysHdrAttr;
FBlockHdrWidth: Integer;
FOffTimeColor: TColor;
FDataDivColor: TColor;
FSnapMove: Boolean;
FDrawOffTime: Boolean;
function IsStoredBlockHdrWidth: Boolean;
procedure SetBlockGran(Value: Integer);
procedure SetDayStart(Value: TTime);
procedure SetBlockHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetSelBlockHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetBlockHdrWidth(Value: Integer);
procedure SetOffTimeColor(Value: TColor);
procedure SetDataDivColor(Value: TColor);
procedure SetDrawOffTime(Value: Boolean);
public
constructor Create(ADaysControl: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, {%H-}AYProportion: Double); virtual;
property DaysControl: TJvTFDays read FDaysControl;
procedure Change;
published
property BlockGran: Integer read FBlockGran write SetBlockGran default 60;
property BlockHdrAttr: TJvTFDaysHdrAttr read FBlockHdrAttr write SetBlockHdrAttr;
property BlockHdrWidth: Integer read FBlockHdrWidth write SetBlockHdrWidth stored IsStoredBlockHdrWidth;
property DataDivColor: TColor read FDataDivColor write SetDataDivColor default clBlack;
property DayStart: TTime read FDayStart write SetDayStart;
property DrawOffTime: Boolean read FDrawOffTime write SetDrawOffTime default True;
property OffTimeColor: TColor read FOffTimeColor write SetOffTimeColor default clGray;
property SelBlockHdrAttr: TJvTFDaysHdrAttr read FSelBlockHdrAttr write SetSelBlockHdrAttr;
property SnapMove: Boolean read FSnapMove write FSnapMove default True;
end;
{$ENDIF Jv_TIMEBLOCKS}
TJvTFDaysCol = class(TCollectionItem)
private
FMap: TJvTFApptMap;
FNullSchedDate: Boolean;
FSchedDate: TDate;
FSchedName: string;
FSchedule: TJvTFSched;
FGroupTitle: string;
FTitle: string;
FWidth: Integer;
function IsStoredWidth: Boolean;
procedure SetSchedDate(Value: TDate);
procedure SetSchedName(const Value: string);
procedure SetGroupTitle(const Value: string);
procedure SetTitle(const Value: string);
procedure SetWidth(Value: Integer);
protected
FDisconnecting: Boolean;
procedure CheckTemplate;
function GetDisplayName: string; override;
procedure SetIndex(Value: Integer); override;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); virtual;
function ColCollection: TJvTFDaysCols;
property Schedule: TJvTFSched read FSchedule;
function Connected: Boolean;
procedure Connect;
procedure Disconnect;
procedure SetSchedule(const NewSchedName: string; NewSchedDate: TDate);
function LocateMapCol(Appt: TJvTFAppt; MapSearchRow: Integer): Integer;
function MapColCount(Row: Integer): Integer;
function MapLocation(Col, Row: Integer): TJvTFAppt;
procedure RefreshMap;
procedure CalcStartEndRows(Appt: TJvTFAppt; var StartRow, EndRow: Integer);
//procedure UpdateTitle;
procedure UpdateTitles;
function GetFirstAppt: TJvTFAppt;
function GetPrevAppt(RefAppt: TJvTFAppt): TJvTFAppt;
function GetNextAppt(RefAppt: TJvTFAppt): TJvTFAppt;
function GetLastAppt: TJvTFAppt;
procedure DumpMap;
function ApptInCol(Appt: TJvTFAppt): Boolean;
published
property SchedDate: TDate read FSchedDate write SetSchedDate;
property SchedName: string read FSchedName write SetSchedName;
property GroupTitle: string read FGroupTitle write SetGroupTitle;
property Title: string read FTitle write SetTitle;
property Width: Integer read FWidth write SetWidth;
end;
TJvTFDaysCols = class(TCollection)
private
FApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
FOldCount: Integer;
function GetItem(Index: Integer): TJvTFDaysCol;
procedure SetItem(Index: Integer; Value: TJvTFDaysCol);
protected
FAddingCol: Boolean;
FSizingCols: Boolean;
FUpdating: Boolean;
procedure EnsureCol(Index: Integer);
function GetOwner: TPersistent; override;
procedure SizeCols; virtual;
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AApptGrid: TJvTFDays);
constructor CreateForPrinter(APrinter: TJvTFDaysPrinter);
property ApptGrid: TJvTFDays read FApptGrid;
property Printer: TJvTFDaysPrinter read FPrinter;
function Add: TJvTFDaysCol;
property AddingCol: Boolean read FAddingCol;
property Updating: Boolean read FUpdating;
procedure EnsureMinColWidth;
procedure EnsureMaxColWidth;
procedure ResizeCols;
property SizingCols: Boolean read FSizingCols;
procedure MoveCol(SourceIndex, TargetIndex: Integer);
procedure AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); virtual;
procedure Assign(Source: TPersistent); override;
property Items[Index: Integer]: TJvTFDaysCol read GetItem write SetItem; default;
procedure UpdateTitles;
end;
TJvTFRowHdrType = (rhGrid, rhFancy);
TJvTFDaysFancyRowHdrAttr = class(TPersistent)
private
FColor: TColor;
FHr2400: Boolean;
FMinorFont: TFont;
FMajorFont: TFont;
FTickColor: TColor;
FOnlyShow00Minutes: Boolean;
procedure SetColor(Value: TColor);
procedure SetHr2400(Value: Boolean);
procedure SetMinorFont(Value: TFont);
procedure SetMajorFont(Value: TFont);
procedure SetTickColor(Value: TColor);
procedure SetOnlyShow00Minutes(Value: Boolean);
protected
FGrid: TJvTFDays;
procedure Change; virtual;
procedure FontChange(Sender: TObject); virtual;
public
constructor Create(AOwner: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
published
property Color: TColor read FColor write SetColor default clBtnFace;
property Hr2400: Boolean read FHr2400 write SetHr2400;
property MinorFont: TFont read FMinorFont write SetMinorFont;
property MajorFont: TFont read FMajorFont write SetMajorFont;
property TickColor: TColor read FTickColor write SetTickColor default clGray;
property OnlyShow00Minutes: Boolean read FOnlyShow00Minutes write SetOnlyShow00Minutes
default True;
end;
TJvTFDaysHdrAttr = class(TPersistent)
private
FApptGrid: TJvTFDays;
FColor: TColor;
FFont: TFont;
FParentFont: Boolean;
FFrame3D: Boolean;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FFrameColor: TColor;
FTitleRotation: Integer;
{$ENDIF Jv_TIMEBLOCKS}
procedure SetColor(Value: TColor);
procedure SetFont(Value: TFont);
procedure SetParentFont(Value: Boolean);
procedure SetFrame3D(Value: Boolean);
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure SetFrameColor(Value: TColor);
procedure SetTitleRotation(Value: Integer);
{$ENDIF Jv_TIMEBLOCKS}
protected
procedure Change;
procedure FontChange(Sender: TObject);
public
constructor Create(AOwner: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure ParentFontChanged;
published
property Color: TColor read FColor write SetColor default clBtnFace;
property Font: TFont read FFont write SetFont;
property ParentFont: Boolean read FParentFont write SetParentFont default True;
property Frame3D: Boolean read FFrame3D write SetFrame3D default True;
{$IFDEF Jv_TIMEBLOCKS}
// ok
property FrameColor: TColor read FFrameColor write SetFrameColor nodefault;
property TitleRotation: Integer read FTitleRotation write SetTitleRotation default 0;
{$ENDIF Jv_TIMEBLOCKS}
end;
TJvTFTimeStampStyle = (tssNone, tssFullI, tssHalfI, tssBlock);
TJvTFDaysApptBar = class(TPersistent)
private
FColor: TColor;
FVisible: Boolean;
FWidth: Integer;
FTimeStampStyle: TJvTFTimeStampStyle;
FTimeStampColor: TColor;
function IsStoredWidth: Boolean;
procedure SetColor(Value: TColor);
procedure SetVisible(Value: Boolean);
procedure SetWidth(Value: Integer);
procedure SetTFTimeStampStyle(Value: TJvTFTimeStampStyle);
procedure SetTimeStampColor(Value: TColor);
protected
FApptGrid: TJvTFDays;
procedure Change; virtual;
public
constructor Create(AApptGrid: TJvTFDays);
procedure Assign(Source: TPersistent); override;
procedure AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); virtual;
published
property Color: TColor read FColor write SetColor default clBlue;
property Width: Integer read FWidth write SetWidth stored IsStoredWidth;
property Visible: Boolean read FVisible write SetVisible default True;
property TimeStampStyle: TJvTFTimeStampStyle read FTimeStampStyle
write SetTFTimeStampStyle default tssBlock;
property TimeStampColor: TColor read FTimeStampColor
write SetTimeStampColor default clBlue;
end;
TJvTFDaysApptAttr = class(TPersistent)
private
FColor: TColor;
FFont: TFont;
FParentFont: Boolean;
FFrameColor: TColor;
FFrameWidth: Integer;
procedure SetColor(Value: TColor);
procedure SetFont(Value: TFont);
procedure SetParentFont(Value: Boolean);
procedure SetFrameColor(Value: TColor);
procedure SetFrameWidth(Value: Integer);
protected
FApptGrid: TJvTFDays;
procedure Change; virtual;
procedure FontChange(Sender: TObject); virtual;
public
constructor Create(AApptGrid: TJvTFDays);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure ParentFontChanged; virtual;
published
property Color: TColor read FColor write SetColor default clWindow;
property Font: TFont read FFont write SetFont;
property ParentFont: Boolean read FParentFont write SetParentFont default True;
property FrameColor: TColor read FFrameColor write SetFrameColor default clBlack;
property FrameWidth: Integer read FFrameWidth write SetFrameWidth default 1;
end;
TJvTFSelCellStyle = (scsSolid, scsFrame, scsCombo);
TJvTFSelCellAttr = class(TPersistent)
private
FColor: TColor;
FFrameWidth: Integer;
FStyle: TJvTFSelCellStyle;
procedure SetColor(Value: TColor);
procedure SetFrameWidth(Value: Integer);
procedure SetStyle(Value: TJvTFSelCellStyle);
protected
FApptGrid: TJvTFDays;
procedure Change; virtual;
public
constructor Create(AApptGrid: TJvTFDays);
procedure Assign(Source: TPersistent); override;
published
property Color: TColor read FColor write SetColor default clHighlight;
property FrameWidth: Integer read FFrameWidth write SetFrameWidth default 2;
property Style: TJvTFSelCellStyle read FStyle write SetStyle default scsSolid;
end;
TJvTFGrabStyle = (gs3D, gsFlat);
TJvTFDaysGrabHandles = class(TPersistent)
private
FColor: TColor;
FHeight: Integer;
FStyle: TJvTFGrabStyle;
function IsStoredHeight: Boolean;
procedure SetColor(Value: TColor);
procedure SetHeight(Value: Integer);
procedure SetStyle(Value: TJvTFGrabStyle);
protected
FApptGrid: TJvTFDays;
procedure Change; virtual;
property Style: TJvTFGrabStyle read FStyle write SetStyle default gsFlat;
public
constructor Create(AApptGrid: TJvTFDays);
procedure Assign(Source: TPersistent); override;
procedure AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); virtual;
published
property Height: Integer read FHeight write SetHeight stored IsStoredHeight;
property Color: TColor read FColor write SetColor default clBlue;
end;
{$M+}
TJvTFDaysApptDrawInfo = class(TObject)
private
FColor: TColor;
FFrameColor: TColor;
FFrameWidth: Integer;
FFont: TFont;
FVisible: Boolean;
procedure SetColor(Value: TColor);
procedure SetFrameColor(Value: TColor);
procedure SetFont(Value: TFont);
procedure SetFrameWidth(const Value: Integer);
procedure SetVisible(Value: Boolean);
public
constructor Create;
destructor Destroy; override;
published
property Color: TColor read FColor write SetColor;
property FrameColor: TColor read FFrameColor write SetFrameColor;
property FrameWidth: Integer read FFrameWidth write SetFrameWidth;
property Font: TFont read FFont write SetFont;
property Visible: Boolean read FVisible write SetVisible;
end;
{$M-}
TJvTFGetDaysApptDrawInfoEvent = procedure(Sender: TObject; Appt: TJvTFAppt;
DrawInfo: TJvTFDaysApptDrawInfo) of object;
TDynPointArray = array of TPoint;
TDynIntArray = array of Integer;
TJvTFDaysGrouping = (grNone, grDate, grResource, grCustom);
TJvTFAutoScrollDir = (asdUp, asdDown, asdLeft, asdRight, asdNowhere);
TJvTFDays = class(TJvTFControl)
private
// internal stuff
// FBorderStyle: TBorderStyle;
FHitTest: TPoint;
FVisibleScrollBars: TJvTFVisibleScrollBars;
FDitheredBackground: Boolean;
// row, col layout
FGranularity: Integer;
FColHdrHeight: Integer;
FRowHdrWidth: Integer;
FRowHeight: Integer;
FMinRowHeight: Integer;
FDefColWidth: Integer;
FMinColWidth: Integer;
FAutoSizeCols: Boolean;
FColTitleStyle: TJvTFColTitleStyle;
FGroupHdrHeight: Integer;
FCols: TJvTFDaysCols;
FTemplate: TJvTFDaysTemplate;
FTopRow: Integer;
FFocusedRow: Integer;
FLeftCol: Integer;
FFocusedCol: Integer;
FGrouping: TJvTFDaysGrouping;
FGridStartTime: TTime;
FGridEndTime: TTime;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FTimeBlockProps: TJvTFDaysBlockProps;
FTimeBlocks: TJvTFDaysTimeBlocks;
{$ENDIF Jv_TIMEBLOCKS}
// visual appearance attr's
FHdrAttr: TJvTFDaysHdrAttr;
FSelHdrAttr: TJvTFDaysHdrAttr;
FApptAttr: TJvTFDaysApptAttr;
FSelApptAttr: TJvTFDaysApptAttr;
FFancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr;
FSelFancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr;
FRowHdrType: TJvTFRowHdrType;
FSelCellAttr: TJvTFSelCellAttr;
FApptBar: TJvTFDaysApptBar;
FApptBuffer: Integer;
FGridLineColor: TColor;
FGrabHandles: TJvTFDaysGrabHandles;
FThresholds: TJvTFDaysThresholds;
FPrimeTime: TJvTFDaysPrimeTime;
FGroupHdrAttr: TJvTFDaysHdrAttr;
FSelGroupHdrAttr: TJvTFDaysHdrAttr;
FOptions: TJvTFDaysOptions;
FEditor: TJvTFInPlaceApptEditor;
FHintProps: TJvTFHintProps;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FWeekend: TTFDaysOfWeek;
FWeekendColor: TColor;
{$ENDIF Jv_TIMEBLOCKS}
// Row/Col Sizing/Moving Events
FOnSizeCol: TJvTFDragRowColEvent;
FOnSizeRow: TJvTFDragRowColEvent;
FOnSizeColHdr: TJvTFDragRowColEvent;
FOnSizeRowHdr: TJvTFDragRowColEvent;
FOnMoveCol: TJvTFDragRowColEvent;
// Appt mouse events
FOnSelectingAppt: TJvTFVarApptEvent;
FOnSelectAppt: TJvTFSelecTJvTFApptEvent;
FOnSelectedAppt: TNotifyEvent;
FOnSizeAppt: TJvTFSizeApptEvent;
FOnDropAppt: TJvTFDropApptEvent;
// Drawing events
FOnDrawAppt: TJvTFDrawApptEvent;
FOnDrawApptBar: TJvTFDrawApptBarEvent;
FOnDrawCorner: TJvTFDrawCornerEvent;
FOnDrawColHdr: TJvTFDrawHdrEvent;
FOnDrawDataCell: TJvTFDrawDataCellEvent;
FOnDrawGrabHandle: TJvTFDrawGrabHandleEvent;
FOnDrawMajorRowHdr: TJvTFDrawHdrEvent;
FOnDrawMinorRowHdr: TJvTFDrawHdrEvent;
FOnDrawRowHdr: TJvTFDrawHdrEvent;
//FOnUpdateColTitle: TJvTFUpdateTitleEvent;
FOnUpdateColTitles: TJvTFUpdateTitlesEvent;
FOnDrawGroupHdr: TJvTFDrawHdrEvent;
FOnShadeCell: TJvTFShadeCellEvent;
FOnGetApptDrawInfo: TJvTFGetDaysApptDrawInfoEvent;
// editor events
FOnFailEditor: TJvTFFailEditorEvent;
FOnCreateQuickEntry: TJvTFCreateQuickEntryEvent;
FOnQuickEntry: TNotifyEvent;
FOnBeginEdit: TJvTFBeginEditEvent;
// navigation events
FOnInsertAppt: TNotifyEvent;
FOnInsertSchedule: TNotifyEvent;
FOnDeleteAppt: TNotifyEvent;
FOnDeleteSchedule: TNotifyEvent;
FOnDateChanging: TJvTFDateChangingEvent;
FOnDateChanged: TNotifyEvent;
FOnGranularityChanging: TJvTFGranChangingEvent;
FOnGranularityChanged: TNotifyEvent;
FOnFocusedRowChanged: TNotifyEvent;
FOnFocusedColChanged: TNotifyEvent;
FShowFocus: Boolean;
// internal stuff
// procedure CMCtl3DChanged(var Msg: TLMessage); message CM_CTL3DCHANGED;
procedure WMGetDlgCode(var Msg: TLMGetDlgCode); message LM_GETDLGCODE;
// procedure SetBorderStyle(Value: TBorderStyle);
procedure SetTFVisibleScrollBars(Value: TJvTFVisibleScrollBars);
procedure AlignScrollBars;
function CheckSBVis: Boolean;
procedure SetOnShowHint(Value: TJvTFShowHintEvent);
function GetOnShowHint: TJvTFShowHintEvent;
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure UpdateWeekendFillPic;
{$ENDIF Jv_TIMEBLOCKS}
// row, col layout
procedure SetGranularity(Value: Integer);
procedure SetColHdrHeight(Value: Integer);
procedure SetRowHdrWidth(Value: Integer);
procedure SetRowHeight(Value: Integer);
procedure SetMinRowHeight(Value: Integer);
procedure SetMinColWidth(Value: Integer);
procedure SetAutoSizeCols(Value: Boolean);
procedure SetTFColTitleStyle(Value: TJvTFColTitleStyle);
procedure SetCols(Value: TJvTFDaysCols);
procedure SetTopRow(Value: Integer);
procedure SetFocusedRow(Value: Integer);
function GetFocusedRow: Integer;
procedure SetLeftCol(Value: Integer);
procedure SetFocusedCol(Value: Integer);
function GetFocusedCol: Integer;
procedure SetGrouping(Value: TJvTFDaysGrouping);
procedure SetGroupHdrHeight(Value: Integer);
procedure SetGridStartTime(Value: TTime);
procedure SetGridEndTime(Value: TTime);
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure SetTimeBlockProps(Value: TJvTFDaysBlockProps);
// ok
procedure SetTimeBlocks(Value: TJvTFDaysTimeBlocks);
{$ENDIF Jv_TIMEBLOCKS}
// visual appearance attr's
procedure SetHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetSelHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetApptAttr(Value: TJvTFDaysApptAttr);
procedure SetSelApptAttr(Value: TJvTFDaysApptAttr);
procedure SetFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
procedure SetSelFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
procedure SetTFRowHdrType(Value: TJvTFRowHdrType);
procedure SetTFSelCellAttr(Value: TJvTFSelCellAttr);
procedure SetApptBar(Value: TJvTFDaysApptBar);
procedure SetApptBuffer(Value: Integer);
procedure SetGridLineColor(Value: TColor);
procedure SetGrabHandles(Value: TJvTFDaysGrabHandles);
procedure SetGroupHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetSelGroupHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetOptions(Value: TJvTFDaysOptions);
procedure SetTFHintProps(Value: TJvTFHintProps);
procedure DrawDither(ACanvas: TCanvas; ARect: TRect; Color1, Color2: TColor);
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure SetWeekend(Value: TTFDaysOfWeek);
// ok
procedure SetWeekendColor(Value: TColor);
procedure SetDitheredBackground(const Value: Boolean);
procedure SetShowFocus(const Value: Boolean);
{$ENDIF Jv_TIMEBLOCKS}
function IsStoredColHdrHeight: Boolean;
function IsStoredDefColWidth: Boolean;
function IsStoredGroupHdrHeight: Boolean;
function IsStoredMinColWidth: Boolean;
function IsStoredMinRowHeight: Boolean;
function IsStoredRowHdrWidth: Boolean;
function IsStoredRowHeight: Boolean;
protected
FState: TJvTFDaysState;
FHint: TJvTFHint;
FNeedCheckSBParams: Boolean;
PaintBuffer: TBitmap;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FWeekendFillPic: TBitmap;
{$ENDIF Jv_TIMEBLOCKS}
FBeginDraggingCoord: TJvTFDaysCoord;
FDraggingCoord: TJvTFDaysCoord;
FSelAppt: TJvTFAppt;
FSelStart: TPoint;
FSelEnd: TPoint;
FFromToSel: Boolean;
FSaveFocCol: Integer;
FHScrollBar: TScrollBar;
FVScrolLBar: TScrollBar;
{
FHScrollBar: TJvTFDaysScrollBar;
FVScrollBar: TJvTFDaysScrollBar;
}
FAutoScrollDir: TJvTFAutoScrollDir;
FLiveTimer: Boolean;
FMouseMovePt: TPoint;
FMouseMoveState: TShiftState;
procedure SetDateFormat(const Value: string); override;
procedure ReqSchedNotification(Schedule: TJvTFSched); override;
procedure RelSchedNotification(Schedule: TJvTFSched); override;
procedure CreateParams(var Params: TCreateParams); override;
function GetFocusedSchedule: TJvTFSched;
procedure SetSelAppt(Value: TJvTFAppt);
//procedure SetGroupTitles; dynamic;
//procedure ReorderCols;
// All painting routines
procedure Paint; override;
procedure DrawDataCell(ACanvas: TCanvas; ColIndex, RowIndex: Integer);
procedure DrawEmptyColHdr(ACanvas: TCanvas);
procedure DrawAppt(ACanvas: TCanvas; Col: Integer; Appt: TJvTFAppt;
StartRow, EndRow: Integer);
procedure DrawApptDetail(ACanvas: TCanvas; ARect: TRect; Appt: TJvTFAppt;
Selected: Boolean; Col, StartRow, EndRow: Integer);
procedure DrawApptBar(ACanvas: TCanvas; Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer);
function CalcTimeStampRect(Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer): TRect;
procedure DrawTimeStamp(ACanvas: TCanvas; TimeStampRect: TRect);
procedure DrawPics(ACanvas: TCanvas; var ARect: TRect; Appt: TJvTFAppt);
procedure CreatePicDrawList(ARect: TRect; Appt: TJvTFAppt; DrawList: TList);
procedure FilterPicDrawList(ARect: TRect; DrawList: TList;
out PicsHeight, PicsWidth: Integer);
procedure ClearPicDrawList(DrawList: TList);
procedure DrawListPics(ACanvas: TCanvas; var ARect: TRect; DrawList: TList);
procedure DrawGrabLines(ACanvas: TCanvas; LineTop, LineLeft,
LineRight: Integer);
procedure DrawGrabHandle(ACanvas: TCanvas; ARect: TRect;
AAppt: TJvTFAppt; TopHandle: Boolean);
procedure DrawCorner(ACanvas: TCanvas; Corner: TJvTFDaysCorner);
procedure DrawRowHdr(ACanvas: TCanvas; Index: Integer);
//procedure DrawColHdr(ACanvas: TCanvas; Index: Integer);
function GetTallestColTitle(ACanvas: TCanvas): Integer;
procedure GetApptDrawInfo(DrawInfo: TJvTFDaysApptDrawInfo;
AAppt: TJvTFAppt; Attr: TJvTFDaysApptAttr);
{$IFDEF Jv_TIMEBLOCKS}
// ok to REPLACE old DrawFrame
procedure DrawFrame(ACanvas: TCanvas; ARect: TRect; Draw3D: Boolean;
FrameColour: TColor);
{$ELSE}
// obsolete
//procedure DrawFrame(ACanvas: TCanvas; ARect: TRect; Draw3D: Boolean);
{$ENDIF Jv_TIMEBLOCKS}
procedure DrawAppts(ACanvas: TCanvas; DrawAll: Boolean);
procedure AdjustForMargins(var ARect: TRect);
procedure CanDrawWhat(ACanvas: TCanvas; ApptRect: TRect; PicsHeight: Integer;
out CanDrawText, CanDrawPics: Boolean);
procedure ManualFocusRect(ACanvas: TCanvas; ARect: TRect);
// Fancy painting routines
procedure DrawFancyRowHdrs(ACanvas: TCanvas);
procedure DrawMinor(ACanvas: TCanvas; ARect: TRect; RowNum: Integer;
const LabelStr: string; TickLength: Integer; Selected: Boolean);
function GetMinorLabel(RowNum: Integer): string;
function GetMinorTickLength: Integer; virtual;
function GetMajorTickLength: Integer; virtual;
procedure DrawGroupHdrs(ACanvas: TCanvas);
//procedure DrawGroupHdr(ACanvas: TCanvas; ACol: Integer);
procedure DrawColGroupHdr(ACanvas: TCanvas; Index: Integer;
IsGroupHdr: Boolean);
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure DrawBlockHdr(ACanvas: TCanvas; BlockIndex: Integer);
// ok
procedure FillBlockHdrDeadSpace(ACanvas: TCanvas);
// REMOVE, replaced by CalcTextPos in JvTFUtils
//procedure CalcTextPos(var ARect: TRect; aAngle: Integer; aTxt: string);
// REMOVE, replaced by DrawAngleText in JvTFUtils
//procedure DrawAngleText(ACanvas: TCanvas; ARect: TRect; aAngle: Integer;
//aTxt: string);
{$ENDIF Jv_TIMEBLOCKS}
// message handlers
procedure Resize; override;
procedure WMEraseBkgnd(var Msg: TLMessage); message LM_ERASEBKGND;
procedure WMSetCursor(var Msg: TLMSetCursor); message LM_SETCURSOR;
procedure WMNCHitTest(var Msg: TLMNCHitTest); message LM_NCHITTEST;
procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
procedure CNRequestRefresh(var Msg: TCNRequestRefresh); message CN_REQUESTREFRESH;
procedure WMTimer(var Msg: TLMTimer); message LM_TIMER;
procedure CMFontChanged(var Msg: TLMessage); message CM_FONTCHANGED;
procedure CMEnabledChanged(var Msg: TLMessage); message CM_ENABLEDCHANGED;
procedure CMMouseLeave(var Msg: TLMessage); message CM_MOUSELEAVE;
// internal routines
procedure Loaded; override;
procedure RefreshControl; override;
procedure UpdateDesigner;
// scroll bar stuff
procedure CheckSBParams;
procedure ScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
property VisibleScrollBars: TJvTFVisibleScrollBars read FVisibleScrollBars
write SetTFVisibleScrollBars;
// mouse routines
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure DblClick; override;
procedure DoApptHint(GridCoord: TJvTFDaysCoord);
procedure DoCellHint(GridCoord: TJvTFDaysCoord);
// Drag/Drop routines
procedure DoStartDrag(var DragObject: TDragObject); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
procedure DropAppt(ADragInfo: TJvTFDragInfo; X, Y: Integer);
procedure BeginDragging(Coord: TJvTFDaysCoord; DragWhat: TJvTFDaysState;
Appt: TJvTFAppt);
procedure DrawDrag(Coord: TJvTFDaysCoord; AAppt: TJvTFAppt; AClear: Boolean);
procedure ContinueDragging(Coord: TJvTFDaysCoord; Appt: TJvTFAppt);
procedure EndDragging(Coord: TJvTFDaysCoord; Appt: TJvTFAppt);
function CanDragWhat(Coord: TJvTFDaysCoord): TJvTFDaysState;
procedure CalcSizeEndTime(Appt: TJvTFAppt; out NewEndDT: TDateTime);
procedure CalcMoveStartEnd(Appt: TJvTFAppt; Coord: TJvTFDaysCoord;
KeepDates, KeepTimes: Boolean; out StartDT, EndDT: TDateTime);
procedure KillAutoScrollTimer;
procedure EnsureCol(ACol: Integer);
procedure EnsureRow(ARow: Integer);
// navigation
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure KeyPress(var Key: Char); override;
procedure DoInsertSchedule; dynamic;
procedure DoInsertAppt; dynamic;
procedure DoDeleteAppt; dynamic;
procedure DoDeleteSchedule; dynamic;
// procedure DoNavigate; virtual;
function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
procedure DestroyApptNotification(AAppt: TJvTFAppt); override;
procedure Navigate(AControl: TJvTFControl; SchedNames: TStringList;
Dates: TJvTFDateList); override;
procedure DoEnter; override;
procedure DoExit; override;
// Selection methods
function GetSelStart: TPoint;
function GetSelEnd: TPoint;
procedure SetSelStart(Value: TPoint);
procedure SetSelEnd(Value: TPoint);
procedure QuickEntry(Key: Char); virtual;
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure EnsureBlockRules(GridGran, BlockGran: Integer; DayStart: TTime);
// ok
function ValidateBlockRules(GridGran, BlockGran: Integer;
DayStart: TTime): Boolean;
{$ENDIF Jv_TIMEBLOCKS}
{ Lazarus }
class function GetControlClassDefaultSize: TSize; override;
{ lcl scaling }
{$IF LCL_FullVersion >= 1080000}
protected
procedure DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); override;
public
procedure ScaleFontsPPI({$IF LCL_FullVersion >= 1080100}const AToPPI: Integer;{$IFEND}
const AProportion: Double); override;
{$IFEND}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetTFHintClass: TJvTFHintClass; dynamic;
// move grab handles
function GetTopGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
// move grab handles
function GetBottomGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
function PtInTopHandle(APoint: TPoint; Col: Integer; Appt: TJvTFAppt): Boolean;
function PtInBottomHandle(APoint: TPoint; Col: Integer; Appt: TJvTFAppt): Boolean;
// grid region functions
function GetAdjClientRect: TRect;
function GetDataAreaRect: TRect;
function GetDataWidth: Integer;
function GetDataHeight: Integer;
function PtToCell(X, Y: Integer): TJvTFDaysCoord;
function CellRect(Col, Row: Integer): TRect;
function VirtualCellRect(Col, Row: Integer): TRect;
function GetApptRect(Col: Integer; Appt: TJvTFAppt): TRect;
function LocateDivCol(X, TotalWidth, SegCount: Integer): Integer;
function CalcGroupHdrHeight: Integer;
function CalcGroupColHdrsHeight: Integer;
function VirtualGroupHdrRect(Col: Integer): TRect;
procedure GetGroupStartEndCols(Col: Integer; var StartCol, EndCol: Integer);
{$IFDEF Jv_TIMEBLOCKS}
// ok
function RowToTimeBlock(ARow: Integer): Integer;
// ok
procedure GetTimeBlockStartEnd(ATimeBlock: Integer;
out BlockStart, BlockEnd: Integer);
// ok
function CalcBlockHdrWidth: Integer;
// ok
function CalcBlockRowHdrsWidth: Integer;
// ok
procedure GetBlockStartEndRows(Row: Integer; out StartRow, EndRow: Integer);
// ok
function VirtualBlockHdrRect(Row: Integer): TRect;
{$ENDIF Jv_TIMEBLOCKS}
// editor management routines
procedure EditAppt(Col: Integer; Appt: TJvTFAppt);
procedure FinishEditAppt;
function Editing: Boolean;
function CanEdit: Boolean; dynamic;
// grid layout routines
function RowsPerHour: Integer;
function RowCount: Integer;
function PossVisibleRows: Integer;
function VisibleRows: Integer;
function FullVisibleRows: Integer;
function VisibleCols: Integer;
function FullVisibleCols: Integer;
function RowToTime(RowNum: Integer): TTime;
function TimeToRow(ATime: TTime): Integer;
procedure TimeToTop(ATime: TTime);
function AdjustEndTime(ATime: TTime): TTime; dynamic;
function RowStartsHour(RowNum: Integer): Boolean;
function RowEndsHour(RowNum: Integer): Boolean;
function RowEndTime(RowNum: Integer): TTime;
function RowToHour(RowNum: Integer): Word;
function HourStartRow(Hour: Word): Integer;
function HourEndRow(Hour: Word): Integer;
property State: TJvTFDaysState read FState;
function BottomRow: Integer;
function RightCol: Integer;
property SelAppt: TJvTFAppt read FSelAppt write SetSelAppt;
property FocusedSchedule: TJvTFSched read GetFocusedSchedule;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
procedure CalcStartEndRows(AAppt: TJvTFAppt; SchedDate: TDate;
out StartRow, EndRow: Integer);
{$IFDEF Jv_TIMEBLOCKS}
// ok
function IsWeekend(ColIndex: Integer): Boolean;
{$ENDIF Jv_TIMEBLOCKS}
// date navigation methods
function CurrentDate: TDate;
procedure PrevDate;
procedure NextDate;
procedure GotoDate(aDate: TDate);
procedure ScrollDays(NumDays: Integer);
procedure ScrollMonths(NumMonths: Integer);
procedure ScrollYears(NumYears: Integer);
procedure ReleaseSchedule(const SchedName: string; SchedDate: TDate); override;
procedure RowInView(ARow: Integer);
procedure ColInView(ACol: Integer);
// selection properties and methods
property FocusedCol: Integer read GetFocusedCol write SetFocusedCol;
property FocusedRow: Integer read GetFocusedRow write SetFocusedRow;
property SelStart: TPoint read GetSelStart write SetSelStart;
property SelEnd: TPoint read GetSelEnd write SetSelEnd;
function CellIsSelected(ACell: TPoint): Boolean;
function ColIsSelected(ACol: Integer): Boolean;
function RowIsSelected(ARow: Integer): Boolean;
procedure ClearSelection;
function ValidSelection: Boolean;
procedure SelFirstAppt;
procedure SelPrevAppt;
procedure SelNextAppt;
procedure SelLastAppt;
procedure SelFirstApptNextCol;
procedure SelFirstApptPrevCol;
procedure ApptInView(AAppt: TJvTFAppt; ACol: Integer);
procedure SelApptCell(AAppt: TJvTFAppt; ACol: Integer);
function GroupHdrIsSelected(ACol: Integer): Boolean;
{$IFDEF Jv_TIMEBLOCKS}
// ok
function BlockHdrIsSelected(ARow: Integer): Boolean;
{$ENDIF Jv_TIMEBLOCKS}
function EnumSelCells: TDynPointArray;
function EnumSelCols: TDynIntArray;
function EnumSelRows: TDynIntArray;
function GetApptDispColor(Appt: TJvTFAppt; Selected: Boolean): TColor;
published
property DitheredBackground: Boolean read FDitheredBackground write SetDitheredBackground default false;
// property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
// grid layout properties
property AutoSizeCols: Boolean read FAutoSizeCols write SetAutoSizeCols default True;
property Granularity: Integer read FGranularity write SetGranularity default DEFAULT_GRANULARITY;
property ColHdrHeight: Integer read FColHdrHeight write SetColHdrHeight stored IsStoredColHdrHeight; //default DEFAULT_COL_HDR_HEIGHT;
property Cols: TJvTFDaysCols read FCols write SetCols;
property DefColWidth: Integer read FDefColWidth write FDefColWidth stored IsStoredDefColWidth; //default DEFAULT_DEF_COL_WIDTH;
property MinColWidth: Integer read FMinColWidth write SetMinColWidth stored IsStoredMinColWidth; //default AbsMinColWidth;
property MinRowHeight: Integer read FMinRowHeight write SetMinRowHeight stored IsStoredMinRowHeight; //default DEFAULT_MIN_ROW_HEIGHT;
property Options: TJvTFDaysOptions read FOptions write SetOptions
default [agoSizeCols, agoSizeRows, agoSizeColHdr, agoSizeRowHdr,
agoSizeAppt, agoMoveAppt, agoEditing, agoShowPics,
agoShowText, agoShowApptHints, agoQuickEntry, agoShowSelHint];
property RowHdrWidth: Integer read FRowHdrWidth write SetRowHdrWidth stored IsStoredRowHdrWidth; //default DEFAULT_ROW_HDR_WIDTH;
property RowHeight: Integer read FRowHeight write SetRowHeight stored IsStoredRowHeight; //default DEFAULT_ROW_HEIGHT;
property ShowFocus:Boolean read FShowFocus write SetShowFocus default True;
property Template: TJvTFDaysTemplate read FTemplate write FTemplate;
property Grouping: TJvTFDaysGrouping read FGrouping write SetGrouping;
property GroupHdrHeight: Integer read FGroupHdrHeight write SetGroupHdrHeight stored IsStoredGroupHdrHeight; //default DEFAULT_GROUP_HDR_HEIGHT;
property GridStartTime: TTime read FGridStartTime write SetGridStartTime;
property GridEndTime: TTime read FGridEndTime write SetGridEndTime;
{$IFDEF Jv_TIMEBLOCKS}
// ok
property TimeBlocks: TJvTFDaysTimeBlocks read FTimeBlocks write SetTimeBlocks;
property TimeBlockProps: TJvTFDaysBlockProps read FTimeBlockProps write SetTimeBlockProps;
{$ENDIF Jv_TIMEBLOCKS}
// visual appearance properties
property ApptAttr: TJvTFDaysApptAttr read FApptAttr write SetApptAttr;
property SelApptAttr: TJvTFDaysApptAttr read FSelApptAttr write SetSelApptAttr;
property HdrAttr: TJvTFDaysHdrAttr read FHdrAttr write SetHdrAttr;
property SelHdrAttr: TJvTFDaysHdrAttr read FSelHdrAttr write SetSelHdrAttr;
property FancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr read FFancyRowHdrAttr
write SetFancyRowHdrAttr;
property SelFancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr
read FSelFancyRowHdrAttr write SetSelFancyRowHdrAttr;
property SelCellAttr: TJvTFSelCellAttr read FSelCellAttr write SetTFSelCellAttr;
property ApptBar: TJvTFDaysApptBar read FApptBar write SetApptBar;
property ApptBuffer: Integer read FApptBuffer write SetApptBuffer default 5;
property ColTitleStyle: TJvTFColTitleStyle read FColTitleStyle
write SetTFColTitleStyle default ctsSingleEllipsis;
property GrabHandles: TJvTFDaysGrabHandles read FGrabHandles
write SetGrabHandles;
property GridLineColor: TColor read FGridLineColor write SetGridLineColor
default clGray;
property PrimeTime: TJvTFDaysPrimeTime read FPrimeTime write FPrimeTime;
property RowHdrType: TJvTFRowHdrType read FRowHdrType write SetTFRowHdrType
default rhFancy;
property Thresholds: TJvTFDaysThresholds read FThresholds write FThresholds;
property HintProps: TJvTFHintProps read FHintProps
write SetTFHintProps;
property GroupHdrAttr: TJvTFDaysHdrAttr read FGroupHdrAttr
write SetGroupHdrAttr;
property SelGroupHdrAttr: TJvTFDaysHdrAttr read FSelGroupHdrAttr
write SetSelGroupHdrAttr;
{$IFDEF Jv_TIMEBLOCKS}
// ok
property Weekend: TTFDaysOfWeek read FWeekend write SetWeekend
default [dowSunday, dowSaturday];
property WeekendColor: TColor read FWeekendColor write SetWeekendColor default clSilver;
{$ENDIF Jv_TIMEBLOCKS}
// navigation/selection properties
property LeftCol: Integer read FLeftCol write SetLeftCol;
property TopRow: Integer read FTopRow write SetTopRow default 0;
// Drag/Drop events
property OnDropAppt: TJvTFDropApptEvent read FOnDropAppt write FOnDropAppt;
property OnSizeAppt: TJvTFSizeApptEvent read FOnSizeAppt write FOnSizeAppt;
// Grid Layout events
property OnSizeCol: TJvTFDragRowColEvent read FOnSizeCol write FOnSizeCol;
property OnSizeRow: TJvTFDragRowColEvent read FOnSizeRow write FOnSizeRow;
property OnSizeColHdr: TJvTFDragRowColEvent read FOnSizeColHdr write FOnSizeColHdr;
property OnSizeRowHdr: TJvTFDragRowColEvent read FOnSizeRowHdr write FOnSizeRowHdr;
property OnMoveCol: TJvTFDragRowColEvent read FOnMoveCol write FOnMoveCol;
property OnDateChanging: TJvTFDateChangingEvent read FOnDateChanging
write FOnDateChanging;
property OnDateChanged: TNotifyEvent read FOnDateChanged write FOnDateChanged;
property OnGranularityChanging: TJvTFGranChangingEvent read FOnGranularityChanging
write FOnGranularityChanging;
property OnGranularityChanged: TNotifyEvent read FOnGranularityChanged
write FOnGranularityChanged;
// Custom draw events
property OnDrawAppt: TJvTFDrawApptEvent read FOnDrawAppt write FOnDrawAppt;
property OnDrawApptBar: TJvTFDrawApptBarEvent read FOnDrawApptBar
write FOnDrawApptBar;
property OnDrawColHdr: TJvTFDrawHdrEvent read FOnDrawColHdr write FOnDrawColHdr;
property OnDrawCorner: TJvTFDrawCornerEvent read FOnDrawCorner
write FOnDrawCorner;
property OnDrawDataCell: TJvTFDrawDataCellEvent read FOnDrawDataCell
write FOnDrawDataCell;
property OnDrawGrabHandle: TJvTFDrawGrabHandleEvent read FOnDrawGrabHandle
write FOnDrawGrabHandle;
property OnDrawMajorRowHdr: TJvTFDrawHdrEvent read FOnDrawMajorRowHdr
write FOnDrawMajorRowHdr;
property OnDrawMinorRowHdr: TJvTFDrawHdrEvent read FOnDrawMinorRowHdr
write FOnDrawMinorRowHdr;
property OnDrawRowHdr: TJvTFDrawHdrEvent read FOnDrawRowHdr write FOnDrawRowHdr;
property OnDrawGroupHdr: TJvTFDrawHdrEvent read FOnDrawGroupHdr
write FOnDrawGroupHdr;
property OnShadeCell: TJvTFShadeCellEvent read FOnShadeCell write FOnShadeCell;
property OnGetApptDrawInfo: TJvTFGetDaysApptDrawInfoEvent read FOnGetApptDrawInfo
write FOnGetApptDrawInfo;
// Input events
property OnFailEditor: TJvTFFailEditorEvent read FOnFailEditor write FOnFailEditor;
property OnInsertAppt: TNotifyEvent read FOnInsertAppt write FOnInsertAppt;
property OnInsertSchedule: TNotifyEvent read FOnInsertSchedule
write FOnInsertSchedule;
property OnDeleteAppt: TNotifyEvent read FOnDeleteAppt write FOnDeleteAppt;
property OnDeleteSchedule: TNotifyEvent read FOnDeleteSchedule
write FOnDeleteSchedule;
property OnCreateQuickEntry: TJvTFCreateQuickEntryEvent read FOnCreateQuickEntry
write FOnCreateQuickEntry;
property OnQuickEntry: TNotifyEvent read FOnQuickEntry write FOnQuickEntry;
property OnBeginEdit: TJvTFBeginEditEvent read FOnBeginEdit write FOnBeginEdit;
// Help and Hint events
property OnShowHint: TJvTFShowHintEvent read GetOnShowHint
write SetOnShowHint;
// Misc events
property OnSelectingAppt: TJvTFVarApptEvent read FOnSelectingAppt
write FOnSelectingAppt;
property OnSelectAppt: TJvTFSelecTJvTFApptEvent read FOnSelectAppt
write FOnSelectAppt;
property OnSelectedAppt: TNotifyEvent read FOnSelectedAppt
write FOnSelectedAppt;
//property OnUpdateColTitle: TJvTFUpdateTitleEvent read FOnUpdateColTitle
//write FOnUpdateColTitle;
property OnUpdateColTitles: TJvTFUpdateTitlesEvent read FOnUpdateColTitles
write FOnUpdateColTitles;
property OnFocusedRowChanged: TNotifyEvent read FOnFocusedRowChanged
write FOnFocusedRowChanged;
property OnFocusedColChanged: TNotifyEvent read FOnFocusedColChanged
write FOnFocusedColChanged;
//Inherited properties
property DateFormat; // from TJvTFControl
property TimeFormat; // from TJvTFControl
// property Navigator; // from TJvTFControl
// property OnNavigate; // from TJvTFControl
property Align;
property BorderSpacing;
property BorderStyle;
property Color default clSilver;
property ParentColor default False;
property Font;
property ParentFont;
property TabStop;
property TabOrder;
property Anchors;
property Constraints;
property DragKind;
property DragCursor;
property DragMode;
property Enabled;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnEndDock;
property OnStartDock;
property OnStartDrag;
end;
TJvTFDaysPrinterPageLayout = class(TJvTFPrinterPageLayout)
private
FColsPerPage: Integer;
FRowsPerPage: Integer;
FAlwaysShowColHdr: Boolean;
FAlwaysShowRowHdr: Boolean;
procedure SetColsPerPage(Value: Integer);
procedure SetRowsPerPage(Value: Integer);
procedure SetAlwaysShowColHdr(Value: Boolean);
procedure SetAlwaysShowRowHdr(Value: Boolean);
public
procedure Assign(Source: TPersistent); override;
published
property ColsPerPage: Integer read FColsPerPage write SetColsPerPage;
property RowsPerPage: Integer read FRowsPerPage write SetRowsPerPage;
property AlwaysShowColHdr: Boolean read FAlwaysShowColHdr
write SetAlwaysShowColHdr;
property AlwaysShowRowHdr: Boolean read FAlwaysShowRowHdr
write SetAlwaysShowRowHdr;
end;
TJvTFDaysPageInfo = class(TObject)
private
FPageNum: Integer;
FStartRow: Integer;
FEndRow: Integer;
FStartCol: Integer;
FEndCol: Integer;
FRowHeight: Integer;
FColWidth: Integer;
FShowRowHdr: Boolean;
FShowColHdr: Boolean;
public
property PageNum: Integer read FPageNum write FPageNum;
property StartRow: Integer read FStartRow write FStartRow;
property EndRow: Integer read FEndRow write FEndRow;
property StartCol: Integer read FStartCol write FStartCol;
property EndCol: Integer read FEndCol write FEndCol;
property RowHeight: Integer read FRowHeight write FRowHeight;
property ColWidth: Integer read FColWidth write FColWidth;
property ShowRowHdr: Boolean read FShowRowHdr write FShowRowHdr;
property ShowColHdr: Boolean read FShowColHdr write FShowColHdr;
end;
TJvTFDaysPrinter = class(TJvTFPrinter)
private
FApptCount: Integer;
FApptAttr: TJvTFDaysApptAttr;
FApptBar: TJvTFDaysApptBar;
FApptBuffer: Integer;
FColHdrHeight: Integer;
FColor: TColor;
FCols: TJvTFDaysCols;
FColTitleStyle: TJvTFColTitleStyle;
FFancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr;
FGranularity: Integer;
FGridLineColor: TColor;
FGroupHdrAttr: TJvTFDaysHdrAttr;
FGroupHdrHeight: Integer;
FGrouping: TJvTFDaysGrouping;
FHdrAttr: TJvTFDaysHdrAttr;
FMinColWidth: Integer;
FMinRowHeight: Integer;
FPrimeTime: TJvTFDaysPrimeTime;
FRowHdrType: TJvTFRowHdrType;
FRowHdrWidth: Integer;
FRowHeight: Integer;
FShowPics: Boolean;
FShowText: Boolean;
FFormattedDesc: Boolean;
FThresholds: TJvTFDaysThresholds;
FOnDrawCorner: TJvTFDrawCornerEvent;
//FOnUpdateColTitle: TJvTFUpdateTitleEvent;
FOnUpdateColTitles: TJvTFUpdateTitlesEvent;
FOnDrawColHdr: TJvTFDrawHdrEvent;
FOnDrawGroupHdr: TJvTFDrawHdrEvent;
FOnDrawRowHdr: TJvTFDrawHdrEvent;
FOnDrawMinorRowHdr: TJvTFDrawHdrEvent;
FOnDrawMajorRowHdr: TJvTFDrawHdrEvent;
FOnDrawDataCell: TJvTFDrawDataCellEvent;
FOnDrawAppt: TJvTFDrawApptEvent;
FOnDrawApptBar: TJvTFDrawApptBarEvent;
FOnGetApptDrawInfo: TJvTFGetDaysApptDrawInfoEvent;
FOnShadeCell: TJvTFShadeCellEvent;
FOnApptProgress: TJvTFProgressEvent;
FGridStartTime: TTime;
FGridEndTime: TTime;
procedure SetApptAttr(Value: TJvTFDaysApptAttr);
procedure SetApptBar(Value: TJvTFDaysApptBar);
procedure SetApptBuffer(Value: Integer);
procedure SetColHdrHeight(Value: Integer);
procedure SetColor(Value: TColor);
procedure SetCols(Value: TJvTFDaysCols);
procedure SetTFColTitleStyle(Value: TJvTFColTitleStyle);
procedure SetFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
procedure SetGranularity(Value: Integer);
procedure SetGridLineColor(Value: TColor);
procedure SetGroupHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetGroupHdrHeight(Value: Integer);
procedure SetGrouping(Value: TJvTFDaysGrouping);
procedure SetHdrAttr(Value: TJvTFDaysHdrAttr);
procedure SetMinColWidth(Value: Integer);
procedure SetMinRowHeight(Value: Integer);
procedure SetPrimeTime(Value: TJvTFDaysPrimeTime);
procedure SetTFRowHdrType(Value: TJvTFRowHdrType);
procedure SetRowHdrWidth(Value: Integer);
procedure SetRowHeight(Value: Integer);
procedure SetShowPics(Value: Boolean);
procedure SetShowText(Value: Boolean);
procedure SetThresholds(Value: TJvTFDaysThresholds);
procedure SetFormattedDesc(Value: Boolean);
function GetApptCount: Integer;
procedure SetGridStartTime(Value: TTime);
procedure SetGridEndTime(Value: TTime);
protected
FPageInfoList: TStringList;
FApptsDrawn: Integer;
FValidPageInfo: Boolean;
procedure SetMeasure(Value: TJvTFPrinterMeasure); override;
procedure DrawBody(ACanvas: TCanvas; ARect: TRect; PageNum: Integer); override;
procedure Loaded; override;
// Drawing routines
procedure DrawCorner(ACanvas: TCanvas);
procedure DrawFrame(ACanvas: TCanvas; ARect: TRect; Draw3D: Boolean);
procedure DrawEmptyColHdr(ACanvas: TCanvas; PageInfo: TJvTFDaysPageInfo);
//procedure DrawColHdr(ACanvas: TCanvas; Index: Integer;
//PageInfo: TJvTFDaysPageInfo);
procedure DrawColGroupHdr(ACanvas: TCanvas; Index: Integer;
PageInfo: TJvTFDaysPageInfo; IsGroupHdr: Boolean);
procedure DrawRowHdr(ACanvas: TCanvas; Index: Integer;
PageInfo: TJvTFDaysPageInfo);
procedure DrawGroupHdrs(ACanvas: TCanvas; PageInfo: TJvTFDaysPageInfo);
procedure DrawFancyRowHdrs(ACanvas: TCanvas; PageInfo: TJvTFDaysPageInfo);
procedure DrawMinor(ACanvas: TCanvas; ARect: TRect; RowNum: Integer;
const LabelStr: string; TickLength: Integer);
function GetMinorLabel(RowNum: Integer; PageInfo: TJvTFDaysPageInfo): string;
function GetMinorTickLength(ACanvas: TCanvas): Integer; virtual;
function GetMajorTickLength: Integer; virtual;
procedure DrawDataCell(ACanvas: TCanvas; ColIndex, RowIndex: Integer;
PageInfo: TJvTFDaysPageInfo);
procedure DrawAppts(ACanvas: TCanvas; DrawAll: Boolean;
PageInfo: TJvTFDaysPageInfo);
procedure PrintBitmap(ACanvas: TCanvas; SourceRect, DestRect: TRect;
aBitmap: TBitmap);
procedure DrawAppt(ACanvas: TCanvas; Col: Integer; Appt: TJvTFAppt;
StartRow, EndRow: Integer; PageInfo: TJvTFDaysPageInfo);
procedure DrawApptDetail(ACanvas: TCanvas; ARect: TRect; Appt: TJvTFAppt;
Col, StartRow, EndRow: Integer);
procedure DrawApptBar(ACanvas: TCanvas; Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer);
function CalcTimeStampRect(Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer): TRect;
procedure DrawTimeStamp(ACanvas: TCanvas; TimeStampRect: TRect);
procedure GetApptDrawInfo(DrawInfo: TJvTFDaysApptDrawInfo; Appt: TJvTFAppt);
procedure CreatePicDrawList(ARect: TRect; Appt: TJvTFAppt; DrawList: TList);
procedure FilterPicDrawList(ARect: TRect; DrawList: TList;
out PicsHeight, PicsWidth: Integer);
procedure CanDrawWhat(ACanvas: TCanvas; ApptRect: TRect;
PicsHeight, PicsWidth: Integer; out CanDrawText, CanDrawPics: Boolean);
procedure DrawListPics(ACanvas: TCanvas; var ARect: TRect; DrawList: TList);
procedure ClearPicDrawList(DrawList: TList);
function GetDataWidth(ShowRowHdr: Boolean): Integer;
function GetDataHeight(ShowColHdr: Boolean): Integer;
procedure EnsureRow(RowNum: Integer);
procedure CreateLayout; override;
procedure ClearPageInfo;
procedure CalcPageInfo; dynamic;
procedure CalcPageRowInfo(ShowColHdrs: Boolean; out CalcRowsPerPage,
CalcRowHeight: Integer);
procedure CalcPageColInfo(ShowRowHdrs: Boolean; out CalcColsPerPage,
CalcColWidth: Integer);
function GetPageLayout: TJvTFDaysPrinterPageLayout;
procedure SetPageLayout(Value: TJvTFDaysPrinterPageLayout);
procedure CreateDoc; override;
function GetPageInfo(PageNum: Integer): TJvTFDaysPageInfo;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetProperties(aJvTFDays: TJvTFDays); dynamic;
function RowCount: Integer;
function TimeToRow(ATime: TTime): Integer;
function RowToTime(RowNum: Integer): TTime;
function RowToHour(RowNum: Integer): Word;
function RowStartsHour(RowNum: Integer): Boolean;
function RowEndsHour(RowNum: Integer): Boolean;
function HourStartRow(Hour: Word): Integer;
function HourEndRow(Hour: Word): Integer;
function RowEndTime(RowNum: Integer): TTime;
function AdjustEndTime(ATime: TTime): TTime;
function DaysPageLayout: TJvTFDaysPrinterPageLayout;
function CellRect(Col, Row: Integer; PageInfo: TJvTFDaysPageInfo): TRect;
function GetApptRect(Col: Integer; Appt: TJvTFAppt;
PageInfo: TJvTFDaysPageInfo): TRect;
function GetApptDispColor(Appt: TJvTFAppt): TColor;
procedure CalcStartEndRows(AAppt: TJvTFAppt; SchedDate: TDate;
out StartRow, EndRow: Integer);
procedure Prepare; dynamic;
property ApptCount: Integer read GetApptCount;
property PageInfo[PageNum: Integer]: TJvTFDaysPageInfo read GetPageInfo;
procedure FreeDoc; override;
procedure PrintDirect; virtual;
function CalcGroupHdrHeight: Integer;
function CalcGroupColHdrsHeight: Integer;
function VirtualGroupHdrRect(Col: Integer; APageInfo: TJvTFDaysPageInfo): TRect;
procedure GetGroupStartEndCols(Col: Integer; var StartCol, EndCol: Integer);
published
property PageLayout: TJvTFDaysPrinterPageLayout read GetPageLayout
write SetPageLayout;
property ApptAttr: TJvTFDaysApptAttr read FApptAttr write SetApptAttr;
property ApptBar: TJvTFDaysApptBar read FApptBar write SetApptBar;
property ApptBuffer: Integer read FApptBuffer write SetApptBuffer;
property ColHdrHeight: Integer read FColHdrHeight write SetColHdrHeight;
property Color: TColor read FColor write SetColor;
property Cols: TJvTFDaysCols read FCols write SetCols;
property ColTitleStyle: TJvTFColTitleStyle read FColTitleStyle
write SetTFColTitleStyle;
property DateFormat; // inherited
property FancyRowHdrAttr: TJvTFDaysFancyRowHdrAttr read FFancyRowHdrAttr
write SetFancyRowHdrAttr;
property FormattedDesc: Boolean read FFormattedDesc write SetFormattedDesc;
property Granularity: Integer read FGranularity write SetGranularity;
property GridLineColor: TColor read FGridLineColor write SetGridLineColor;
property GroupHdrAttr: TJvTFDaysHdrAttr read FGroupHdrAttr
write SetGroupHdrAttr;
property GroupHdrHeight: Integer read FGroupHdrHeight
write SetGroupHdrHeight default 25;
property Grouping: TJvTFDaysGrouping read FGrouping write SetGrouping;
property HdrAttr: TJvTFDaysHdrAttr read FHdrAttr write SetHdrAttr;
property MinColWidth: Integer read FMinColWidth write SetMinColWidth;
property MinRowHeight: Integer read FMinRowHeight write SetMinRowHeight;
property PrimeTime: TJvTFDaysPrimeTime read FPrimeTime write SetPrimeTime;
property RowHdrType: TJvTFRowHdrType read FRowHdrType write SetTFRowHdrType;
property RowHdrWidth: Integer read FRowHdrWidth write SetRowHdrWidth default 0;
property RowHeight: Integer read FRowHeight write SetRowHeight default 0;
property ShowPics: Boolean read FShowPics write SetShowPics;
property ShowText: Boolean read FShowText write SetShowText;
property Thresholds: TJvTFDaysThresholds read FThresholds
write SetThresholds;
property TimeFormat; // inherited;
property OnDrawCorner: TJvTFDrawCornerEvent read FOnDrawCorner
write FOnDrawCorner;
property OnDrawGroupHdr: TJvTFDrawHdrEvent read FOnDrawGroupHdr
write FOnDrawGroupHdr;
property OnDrawMinorRowHdr: TJvTFDrawHdrEvent read FOnDrawMinorRowHdr
write FOnDrawMinorRowHdr;
property OnDrawMajorRowHdr: TJvTFDrawHdrEvent read FOnDrawMajorRowHdr
write FOnDrawMajorRowHdr;
//property OnUpdateColTitle: TJvTFUpdateTitleEvent read FOnUpdateColTitle
//write FOnUpdateColTitle;
property OnUpdateColTitles: TJvTFUpdateTitlesEvent read FOnUpdateColTitles
write FOnUpdateColTitles;
property OnDrawColHdr: TJvTFDrawHdrEvent read FOnDrawColHdr write FOnDrawColHdr;
property OnDrawRowHdr: TJvTFDrawHdrEvent read FOnDrawRowHdr write FOnDrawRowHdr;
property OnDrawDataCell: TJvTFDrawDataCellEvent read FOnDrawDataCell
write FOnDrawDataCell;
property OnDrawAppt: TJvTFDrawApptEvent read FOnDrawAppt write FOnDrawAppt;
property OnDrawApptBar: TJvTFDrawApptBarEvent read FOnDrawApptBar
write FOnDrawApptBar;
property OnGetApptDrawInfo: TJvTFGetDaysApptDrawInfoEvent read FOnGetApptDrawInfo
write FOnGetApptDrawInfo;
property OnShadeCell: TJvTFShadeCellEvent read FOnShadeCell write FOnShadeCell;
property OnApptProgress: TJvTFProgressEvent read FOnApptProgress
write FOnApptProgress;
property GridStartTime: TTime read FGridStartTime write SetGridStartTime;
property GridEndTime: TTime read FGridEndTime write SetGridEndTime;
end;
implementation
uses
FPCanvas,
JvResources;
//Type
// DEF TIMEBLOCK (not conditionally compiled, just marked for reference)
// removed as part of TimeBlock integration
//TVertAlignment = (vaTop, vaCenter, vaBottom);
// Utility routines
// Most, if not all, of these will be moved out of this unit and into
// a utilities unit.
function StripCRLF(const S: string): string;
var
I: Integer;
begin
Result := '';
for I := 1 to Length(S) do
if (S[I] <> #13) and (S[I] <> #10) then
Result := Result + S[I];
end;
function EmptyRect: TRect;
begin
Result := Classes.Rect(0, 0, 0, 0);
end;
function RectWidth(ARect: TRect): Integer;
begin
Result := ARect.Right - ARect.Left;
end;
function RectHeight(ARect: TRect): Integer;
begin
Result := ARect.Bottom - ARect.Top;
end;
// DEF TIMEBLOCK (not conditionally compiled, just marked for reference)
// the type of VAlign was orginally TVertAlignment
procedure DrawTxt(ACanvas: TCanvas; ARect: TRect;
const Txt: string; HAlign: TAlignment; VAlign: TJvTFVAlignment);
var
TxtWidth, TxtHeight, TxtLeft, TxtTop: Integer;
begin
TxtLeft := 0;
TxtTop := 0;
TxtWidth := ACanvas.TextWidth(Txt);
TxtHeight := ACanvas.TextHeight('Wq');
case HAlign of
taLeftJustify:
TxtLeft := ARect.Left;
taCenter:
TxtLeft := ARect.Left + RectWidth(ARect) div 2 - TxtWidth div 2;
taRightJustify:
TxtLeft := ARect.Right - TxtWidth;
end;
case VAlign of
vaTop:
TxtTop := ARect.Top;
vaCenter:
TxtTop := ARect.Top + RectHeight(ARect) div 2 - TxtHeight div 2;
vaBottom:
TxtTop := ARect.Bottom - TxtHeight;
end;
ACanvas.TextRect(ARect, TxtLeft, TxtTop, Txt);
end;
function Greater(I1, I2: Integer): Integer;
begin
if I1 > I2 then
Result := I1
else
Result := I2;
end;
function Lesser(I1, I2: Integer): Integer;
begin
if I1 < I2 then
Result := I1
else
Result := I2;
end;
//=== { TJvTFDaysTemplate } ==================================================
constructor TJvTFDaysTemplate.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FGrid := AApptGrid;
FCompNames := TJvTFCompNamesList.Create;
FCompNames.OnChange := @CompNamesChanged;
FCompNames.OnMove := @CompNamesMoved;
FLinearStartDate := Date;
FLinearEndDate := Date;
FLinearDayCount := 1;
FCompDate := Date;
FActiveTemplate := agtNone;
FShortTitles := True;
end;
destructor TJvTFDaysTemplate.Destroy;
begin
FCompNames.OnChange := nil;
FCompNames.OnMove := nil;
FCompNames.Free;
inherited Destroy;
end;
procedure TJvTFDaysTemplate.SetActiveTemplate(Value: TJvTFDaysTemplates);
begin
if Value <> FActiveTemplate then
begin
FActiveTemplate := Value;
UpdateGrid;
end;
end;
procedure TJvTFDaysTemplate.SetCompDate(Value: TDate);
var
I: Integer;
begin
if Trunc(Value) <> Trunc(FCompDate) then
begin
DoDateChangingEvent(Value);
FCompDate := Value;
if (ActiveTemplate = agtComparative) and Assigned(FGrid) then
try
BeginGridUpdate;
for I := 0 to FGrid.Cols.Count - 1 do
FGrid.Cols[I].SchedDate := CompDate;
finally
EndGridUpdate;
end;
DoDateChangedEvent;
end;
end;
function TJvTFDaysTemplate.GetCompNames: TStrings;
begin
Result := FCompNames;
end;
procedure TJvTFDaysTemplate.SetCompNames(Value: TStrings);
begin
FCompNames.Assign(Value);
CompNamesChanged(Self);
end;
procedure TJvTFDaysTemplate.SetLinearDayCount(Value: Integer);
begin
if Value < 1 then
Value := 1;
if (Value <> FLinearDayCount) then
begin
FLinearDayCount := Value;
if not (csLoading in FGrid.ComponentState) then
begin
FLinearEndDate := FLinearStartDate + Value - 1;
LinearDaysChanged;
end;
end;
end;
procedure TJvTFDaysTemplate.SetLinearEndDate(Value: TDate);
begin
if Trunc(Value) < Trunc(FLinearStartDate) then
Value := FLinearStartDate;
if (Trunc(Value) <> Trunc(FLinearEndDate)) then
begin
FLinearEndDate := Value;
if not (csLoading in FGrid.ComponentState) then
begin
FLinearDayCount := Trunc(FLinearEndDate - FLinearStartDate + 1);
LinearDaysChanged;
end;
end;
end;
procedure TJvTFDaysTemplate.SetLinearName(const Value: string);
var
I: Integer;
begin
if Value <> FLinearName then
begin
FLinearName := Value;
if (ActiveTemplate = agtLinear) and Assigned(FGrid) then
begin
try
BeginGridUpdate;
for I := 0 to FGrid.Cols.Count - 1 do
FGrid.Cols[I].SchedName := Value;
finally
EndGridUpdate;
end;
end;
end;
end;
procedure TJvTFDaysTemplate.SetLinearStartDate(Value: TDate);
var
I: Integer;
begin
if Trunc(Value) <> Trunc(FLinearStartDate) then
begin
DoDateChangingEvent(Value);
FLinearStartDate := Value;
FLinearEndDate := Value + FLinearDayCount - 1;
if (ActiveTemplate = agtLinear) and Assigned(FGrid) then
begin
BeginGridUpdate;
try
for I := 0 to FGrid.Cols.Count - 1 do
FGrid.Cols[I].SchedDate := Value + I;
finally
EndGridUpdate;
end;
end;
DoDateChangedEvent;
end;
end;
procedure TJvTFDaysTemplate.SetShortTitles(Value: Boolean);
begin
if Value <> FShortTitles then
begin
FShortTitles := Value;
if Assigned(FGrid) and (ActiveTemplate <> agtNone) then
FGrid.Cols.UpdateTitles;
end;
end;
procedure TJvTFDaysTemplate.DoDateChangedEvent;
begin
if Assigned(FGrid) and Assigned(FGrid.FOnDateChanged) then
FGrid.FOnDateChanged(FGrid);
end;
procedure TJvTFDaysTemplate.DoDateChangingEvent(var NewDate: TDate);
begin
if Assigned(FGrid) and Assigned(FGrid.FOnDateChanging) then
FGrid.FOnDateChanging(FGrid, NewDate);
end;
procedure TJvTFDaysTemplate.CompNamesChanged(Sender: TObject);
var
TempNames: TStringList;
I: Integer;
Col: TJvTFDaysCol;
begin
if FUpdatingCompNames then
begin
FCompNamesChanged := True;
Exit;
end;
FCompNamesChanged := False;
if (ActiveTemplate = agtComparative) and Assigned(FGrid) then
begin
TempNames := TStringList.Create;
try
BeginGridUpdate;
// remove any unneeded cols
I := 0;
while I < FGrid.Cols.Count do
if CompNames.IndexOf(FGrid.Cols[I].SchedName) = -1 then
FGrid.Cols[I].Free
else
begin
TempNames.Add(FGrid.Cols[I].SchedName);
Inc(I);
end;
// add all new cols
for I := 0 to CompNames.Count - 1 do
if TempNames.IndexOf(CompNames[I]) = -1 then
begin
Col := FGrid.Cols.Add;
Col.SchedName := CompNames[I];
Col.SchedDate := CompDate;
end;
finally
TempNames.Free;
EndGridUpdate;
end;
end;
end;
procedure TJvTFDaysTemplate.LinearDaysChanged;
var
I, DeltaDays: Integer;
Col: TJvTFDaysCol;
begin
if (ActiveTemplate = agtLinear) and Assigned(FGrid) then
begin
try
BeginGridUpdate;
DeltaDays := LinearDayCount - FGrid.Cols.Count;
// ONLY ONE OF THE FOLLOWING LOOPS WILL BE EXECUTED !!
// Add some days
for I := 1 to DeltaDays do
begin
Col := FGrid.Cols.Add;
Col.SchedName := LinearName;
Col.SchedDate := LinearStartDate + FGrid.Cols.Count - 1;
end;
// Remove some days
for I := -1 downto DeltaDays do
if FGrid.Cols.Count > 0 then
FGrid.Cols[FGrid.Cols.Count - 1].Free;
finally
EndGridUpdate;
end;
end;
end;
procedure TJvTFDaysTemplate.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysTemplate then
begin
FLinearName := TJvTFDaysTemplate(Source).LinearName;
FLinearStartDate := TJvTFDaysTemplate(Source).LinearStartDate;
FLinearEndDate := TJvTFDaysTemplate(Source).LinearEndDate;
FLinearDayCount := TJvTFDaysTemplate(Source).LinearDayCount;
FCompNames.OnChange := nil;
FCompNames.Assign(TJvTFDaysTemplate(Source).CompNames);
FCompNames.OnChange := @CompNamesChanged;
FCompDate := TJvTFDaysTemplate(Source).CompDate;
FActiveTemplate := TJvTFDaysTemplate(Source).ActiveTemplate;
FShortTitles := TJvTFDaysTemplate(Source).ShortTitles;
FIgnoreNav := TJvTFDaysTemplate(Source).IgnoreNav;
UpdateGrid;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysTemplate.BeginCompNamesUpdate;
begin
FUpdatingCompNames := True;
end;
procedure TJvTFDaysTemplate.EndCompNamesUpdate;
begin
FUpdatingCompNames := False;
if FCompNamesChanged then
CompNamesChanged(Self);
end;
procedure TJvTFDaysTemplate.UpdateGrid;
var
I: Integer;
Col: TJvTFDaysCol;
begin
if not Assigned(FGrid) then
Exit;
if ActiveTemplate = agtLinear then
begin
try
BeginGridUpdate;
FGrid.Cols.Clear;
for I := 0 to LinearDayCount - 1 do
begin
Col := FGrid.Cols.Add;
Col.SchedName := LinearName;
Col.SchedDate := LinearStartDate + I;
end;
finally
EndGridUpdate;
end
end
else
if ActiveTemplate = agtComparative then
begin
try
BeginGridUpdate;
FGrid.Cols.Clear;
for I := 0 to CompNames.Count - 1 do
begin
Col := FGrid.Cols.Add;
Col.SchedName := CompNames[I];
Col.SchedDate := CompDate;
end;
finally
EndGridUpdate;
end;
end;
FGrid.Cols.UpdateTitles;
end;
procedure TJvTFDaysTemplate.CompNamesMoved(Sender: TObject;
CurIndex, NewIndex: Integer);
begin
if Assigned(ApptGrid) and (ActiveTemplate = agtComparative) and
not ApptGrid.Cols.Updating then
ApptGrid.Cols.MoveCol(CurIndex, NewIndex);
end;
procedure TJvTFDaysTemplate.BeginGridUpdate;
begin
FUpdatingGrid := True;
end;
procedure TJvTFDaysTemplate.EndGridUpdate;
begin
FUpdatingGrid := False;
ApptGrid.ProcessBatches;
end;
//=== { TJvTFDaysPrimeTime } =================================================
constructor TJvTFDaysPrimeTime.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FApptGrid := AApptGrid;
FStartTime := EncodeTime(8, 0, 0, 0);
FEndTime := EncodeTime(17, 0, 0, 0);
FColor := DEFAULT_PRIMETIME_COLOR;
FFillPic := TBitmap.Create;
FFillPic.Width := 16;
FFillPic.Height := 16;
UpdateFillPic;
end;
destructor TJvTFDaysPrimeTime.Destroy;
begin
FFillPic.Free;
inherited Destroy;
end;
procedure TJvTFDaysPrimeTime.SetStartTime(Value: TTime);
begin
if Assigned(FApptGrid) and not (csLoading in FApptGrid.ComponentState) and
(Value >= EndTime) then
raise EJvTFDaysError.CreateRes(@RsEInvalidPrimeTimeStartTime);
FStartTime := Value;
Change;
end;
procedure TJvTFDaysPrimeTime.SetEndTime(Value: TTime);
begin
if Assigned(FApptGrid) and (Value <= StartTime) and
not (csLoading in FApptGrid.ComponentState) then
raise EJvTFDaysError.CreateRes(@RsEInvalidPrimeTimeEndTime);
FEndTime := Value;
Change;
end;
procedure TJvTFDaysPrimeTime.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
UpdateFillPic;
Change;
end;
end;
procedure TJvTFDaysPrimeTime.Change;
begin
if Assigned(FApptGrid) and not (csLoading in FApptGrid.ComponentState) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysPrimeTime.UpdateFillPic;
begin
with FFillPic.Canvas do
begin
Brush.Color := FColor;
FillRect(Classes.Rect(0, 0, FFillPic.Width, FFillPic.Height));
end;
end;
procedure TJvTFDaysPrimeTime.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysPrimeTime then
begin
FStartTime := TJvTFDaysPrimeTime(Source).StartTime;
FEndTime := TJvTFDaysPrimeTime(Source).EndTime;
FColor := TJvTFDaysPrimeTime(Source).Color;
UpdateFillPic;
Change;
end
else
inherited Assign(Source);
end;
//=== { TJvTFInPlaceApptEditor } =============================================
constructor TJvTFInPlaceApptEditor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csNoDesignVisible];
BorderStyle := bsNone;
FQuickCreate := False;
//ParentCtl3D := False;
//Ctl3D := False;
end;
procedure TJvTFInPlaceApptEditor.DoExit;
begin
inherited DoExit;
try
if not FCancelEdit then
TJvTFDays(Parent).FinishEditAppt
else
if FQuickCreate then
// Free the appointment
FLinkedAppt.Free;
finally
FCancelEdit := False;
Parent.SetFocus;
end;
end;
procedure TJvTFInPlaceApptEditor.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
if Key = VK_ESCAPE then
begin
FCancelEdit := True;
Key := 0;
Visible := False;
end;
end;
//=== { TJvTFApptMap } =======================================================
constructor TJvTFApptMap.Create(AGridCol: TJvTFDaysCol);
begin
inherited Create;
FGridCol := AGridCol;
FData := TJvTFSparseMatrix.Create;
end;
destructor TJvTFApptMap.Destroy;
begin
FData.Free;
inherited Destroy;
end;
function TJvTFApptMap.GetLocation(Row, Col: Integer): TJvTFAppt;
begin
Result := nil;
if (Row >= 0) and (Col > 0) then
Result := TJvTFAppt(FData[Row, Col]);
end;
procedure TJvTFApptMap.Add(Appt: TJvTFAppt);
var
StartRow: Integer = -1; // to silence the compiler
EndRow: Integer = -1; // dto.
MapRow, MapCol: Integer;
Empty: Boolean;
ApptGrid: TJvTFDays;
begin
// We need to find the left-most col that does not have any appts already
// scheduled in any of the rows needed by the new appt. (In other words,
// we need a contiguous set cols for the new appt.)
FGridCol.CalcStartEndRows(Appt, StartRow, EndRow);
StartRow := Greater(StartRow, 0);
ApptGrid := FGridCol.ColCollection.ApptGrid;
if Assigned(ApptGrid) then
EndRow := Lesser(EndRow, ApptGrid.RowCount - 1)
else
EndRow := Lesser(EndRow, FGridCol.ColCollection.Printer.RowCount - 1);
MapRow := StartRow;
MapCol := 1;
repeat
Empty := FData[MapRow, MapCol] = 0;
if Empty then
Inc(MapRow)
else
begin
Inc(MapCol);
MapRow := StartRow;
end;
until (MapRow > EndRow) and Empty;
// Now write the new appt to the map in all rows hit by appt, using the
// col found above.
for MapRow := StartRow to EndRow do
begin
FData[MapRow, MapCol] := NativeInt(Appt);
FData[MapRow, -1] := FData[MapRow, -1] + 1;
end;
end;
procedure TJvTFApptMap.ProcessMapGroup(GroupStart, GroupEnd: Integer);
var
MapRow, Examined, ApptCount, MaxCol, MapCol: Integer;
begin
// Find the highest used column in group
MaxCol := 0;
for MapRow := GroupStart to GroupEnd do
begin
Examined := 0;
ApptCount := FData[MapRow, -1];
// ApptCount > 0 check added by Mike 1/14/01
if ApptCount > 0 then
begin
MapCol := 1;
repeat
if FData[MapRow, MapCol] <> 0 then
Inc(Examined);
Inc(MapCol);
until Examined = ApptCount;
Dec(MapCol);
MaxCol := Greater(MaxCol, MapCol);
end;
end;
// Now write MaxCol in col 0 for each row in the groups
for MapRow := GroupStart to GroupEnd do
FData[MapRow, 0] := MaxCol;
end;
procedure TJvTFApptMap.UpdateMapGroups;
var
GridRowCount: Integer;
begin
if Assigned(FGridCol.ColCollection.ApptGrid) then
GridRowCount := FGridCol.ColCollection.ApptGrid.RowCount
else
if Assigned(FGridCol.ColCollection.Printer) then
GridRowCount := FGridCol.ColCollection.Printer.RowCount
else
GridRowCount := 0;
// we could try to find a smaller group, by looking for the first and last
// row where there is at least one appt, but CPU wise, it's actually simpler
// to let the ProcessMapGroup function deal with it.
ProcessMapGroup(0, GridRowCount);
end;
procedure TJvTFApptMap.Clear;
begin
FData.Clear;
end;
function TJvTFApptMap.ColCount(Row: Integer): Integer;
begin
Result := FData[Row, 0];
end;
procedure TJvTFApptMap.GetAppts(StartRow, EndRow: Integer; ApptList: TStringList);
var
Row, Col, Existing, Found, MapCols: Integer;
Appt: TJvTFAppt;
begin
ApptList.Clear;
for Row := StartRow to EndRow do
begin
Existing := FData[Row, -1];
MapCols := FData[Row, 0];
Found := 0;
Col := 1;
while (Found < Existing) and (Col <= MapCols) do
begin
if FData[Row, Col] <> 0 then
begin
Inc(Found);
Appt := TJvTFAppt(FData[Row, Col]);
if ApptList.IndexOf(Appt.ID) = -1 then
ApptList.AddObject(Appt.ID, Appt);
end;
Inc(Col);
end;
end;
end;
function TJvTFApptMap.LocateMapCol(Appt: TJvTFAppt; MapSearchRow: Integer): Integer;
var
Col, MapCols, ApptVal: Integer;
begin
MapCols := FData[MapSearchRow, 0];
Col := 1;
ApptVal := PtrInt(Appt);
while (Col <= MapCols) and (FData[MapSearchRow, Col] <> ApptVal) do
Inc(Col);
if FData[MapSearchRow, Col] = ApptVal then
Result := Col
else
Result := -2;
end;
procedure TJvTFApptMap.Refresh;
var
Sched: TJvTFSched;
I: Integer;
begin
Clear;
Sched := FGridCol.Schedule;
if Assigned(Sched) then
begin
for I := 0 to Sched.ApptCount - 1 do
Add(Sched.Appts[I]);
UpdateMapGroups;
end;
end;
procedure TJvTFApptMap.Dump(AName: TFileName);
var
DumpData: TStringList;
begin
// used for debugging only
DumpData := TStringList.Create;
try
FData.Dump(DumpData);
DumpData.SaveToFile(AName);
finally
DumpData.Free;
end;
end;
function TJvTFApptMap.HasAppt(Appt: TJvTFAppt): Boolean;
var
StartRow: Integer = -1; // to silence the compiler
EndRow: Integer = -1; // dto.
MapRow, MapCol, ApptsExamined: Integer;
Test: NativeInt;
ApptGrid: TJvTFDays;
begin
FGridCol.CalcStartEndRows(Appt, StartRow, EndRow);
StartRow := Greater(StartRow, 0);
ApptGrid := FGridCol.ColCollection.ApptGrid;
if Assigned(ApptGrid) then
EndRow := Lesser(EndRow, ApptGrid.RowCount - 1)
else
EndRow := Lesser(EndRow, FGridCol.ColCollection.Printer.RowCount - 1);
MapRow := 0;
Result := False;
while (MapRow <= EndRow) and not Result do
begin
MapCol := 1;
ApptsExamined := 0;
while (ApptsExamined < FData[MapRow, -1]) and not Result do
begin
Test := FData[MapRow, MapCol];
if Test <> 0 then
begin
Inc(ApptsExamined);
if Test = NativeInt(Appt) then
Result := True;
end;
Inc(MapCol);
end;
Inc(MapRow);
end;
end;
//=== { TJvTFDaysThresholds } ================================================
constructor TJvTFDaysThresholds.Create(AOwner: TJvTFDays);
begin
inherited Create;
FApptGrid := AOwner;
FTextHeight := 1;
FTextWidth := 10;
FEditHeight := 1;
FEditWidth := 10;
FDetailWidth := 10;
FDetailHeight := 10;
FDropTextFirst := True;
FPicsAllOrNone := False;
FWholePicsOnly := True;
end;
procedure TJvTFDaysThresholds.SetDetailHeight(Value: Integer);
begin
if Value < 1 then
Value := 1;
if Value <> FDetailHeight then
begin
FDetailHeight := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetDetailWidth(Value: Integer);
begin
if Value < 1 then
Value := 1;
if Value <> FDetailWidth then
begin
FDetailWidth := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetEditHeight(Value: Integer);
begin
if Value < 0 then
Value := 0;
if Value <> FEditHeight then
FEditHeight := Value;
end;
procedure TJvTFDaysThresholds.SetEditWidth(Value: Integer);
begin
if Value < 0 then
Value := 0;
if Value <> FEditWidth then
FEditWidth := Value;
end;
procedure TJvTFDaysThresholds.SetTextHeight(Value: Integer);
begin
if Value < 0 then
Value := 0;
if Value <> FTextHeight then
begin
FTextHeight := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetTextWidth(Value: Integer);
begin
if Value < 0 then
Value := 0;
if Value <> FTextWidth then
begin
FTextWidth := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetDropTextFirst(Value: Boolean);
begin
if Value <> FDropTextFirst then
begin
FDropTextFirst := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetPicsAllOrNone(Value: Boolean);
begin
if Value <> FPicsAllOrNone then
begin
FPicsAllOrNone := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.SetWholePicsOnly(Value: Boolean);
begin
if Value <> FWholePicsOnly then
begin
FWholePicsOnly := Value;
Change;
end;
end;
procedure TJvTFDaysThresholds.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysThresholds.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysThresholds then
begin
FTextWidth := TJvTFDaysThresholds(Source).TextWidth;
FTextHeight := TJvTFDaysThresholds(Source).TextHeight;
FEditHeight := TJvTFDaysThresholds(Source).EditHeight;
FEditWidth := TJvTFDaysThresholds(Source).EditWidth;
FDropTextFirst := TJvTFDaysThresholds(Source).DropTextFirst;
FPicsAllOrNone := TJvTFDaysThresholds(Source).PicsAllOrNone;
FWholePicsOnly := TJvTFDaysThresholds(Source).WholePicsOnly;
Change;
end
else
inherited Assign(Source);
end;
//=== { TJvTFDaysScrollBar } =================================================
constructor TJvTFDaysScrollBar.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// if we set the csNoDesignVisible flag then visibility at design time
// is controled by the Visible property, which is exactly what we want.
ControlStyle := ControlStyle + [csNoDesignVisible];
//ParentCtl3D := False;
//Ctl3D := False;
end;
procedure TJvTFDaysScrollBar.CMDesignHitTest(var Msg: TCMDesignHitTest);
begin
Msg.Result := 1;
end;
procedure TJvTFDaysScrollBar.CreateWnd;
begin
inherited CreateWnd;
UpdateRange;
end;
function TJvTFDaysScrollBar.GetLargeChange: Integer;
begin
Result := inherited LargeChange;
end;
procedure TJvTFDaysScrollBar.SetLargeChange(Value: Integer);
begin
inherited LargeChange := Value;
UpdateRange;
end;
procedure TJvTFDaysScrollBar.UpdateRange;
var
Info: TScrollInfo;
begin
if not HandleAllocated then
exit;
FillChar(Info{%H-}, SizeOf(Info), 0);
with Info do
begin
cbsize := SizeOf(Info);
fmask := SIF_PAGE;
nPage := LargeChange;
end;
SetScrollInfo(Handle, SB_CTL, Info, True);
end;
//=== { TJvTFDaysCol } =======================================================
constructor TJvTFDaysCol.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FNullSchedDate := True;
FMap := TJvTFApptMap.Create(Self);
end;
destructor TJvTFDaysCol.Destroy;
begin
Disconnect;
FMap.Free;
inherited Destroy;
end;
procedure TJvTFDaysCol.SetSchedDate(Value: TDate);
begin
if Value <> FSchedDate then
begin
Disconnect;
FSchedDate := Value;
FNullSchedDate := False;
Connect;
//UpdateTitle;
UpdateTitles;
CheckTemplate;
end;
end;
procedure TJvTFDaysCol.SetSchedName(const Value: string);
begin
if Value <> FSchedName then
begin
Disconnect;
FSchedName := Value;
Connect;
//UpdateTitle;
UpdateTitles;
CheckTemplate;
end;
end;
procedure TJvTFDaysCol.SetTitle(const Value: string);
begin
if FTitle <> Value then
begin
FTitle := Value;
if Assigned(ColCollection.ApptGrid) then
ColCollection.ApptGrid.Invalidate;
end;
end;
function TJvTFDaysCol.IsStoredWidth: Boolean;
begin
if Assigned(TJvTFDaysCols(Collection).ApptGrid) then
Result := FWidth <> TJvTFDaysCols(Collection).ApptGrid.Scale96ToFont(FWidth)
else
Result := true;
end;
procedure TJvTFDaysCol.SetWidth(Value: Integer);
var
ApptGrid: TJvTFDays;
absMinColWidth: Integer;
begin
if Assigned(ColCollection.ApptGrid) then
absMinColWidth := ColCollection.ApptGrid.Scale96ToFont(DEFAULT_MIN_COL_WIDTH)
else
absMinColWidth := DEFAULT_MIN_COL_WIDTH;
if Value < absMinColWidth then
Value := absMinColWidth;
if Assigned(ColCollection.ApptGrid) then
if Value > ColCollection.ApptGrid.GetDataWidth then
Value := ColCollection.ApptGrid.GetDataWidth;
if Value < 1 then
Value := 1;
// For the printer, just set the private member then EXIT
if Assigned(ColCollection.Printer) then
begin
FWidth := Value;
Exit;
end;
if Value <> FWidth then
begin
FWidth := Value;
ApptGrid := ColCollection.ApptGrid;
if not (csLoading in ApptGrid.ComponentState) then
begin
if ApptGrid.AutoSizeCols then
begin
if not ColCollection.AddingCol and
not (vsbHorz in ApptGrid.VisibleScrollBars) then
ColCollection.ResizeCols;
end
else
ApptGrid.CheckSBVis;
ApptGrid.CheckSBParams;
ApptGrid.Invalidate;
end;
end;
end;
function TJvTFDaysCol.GetDisplayName: string;
begin
Result := SchedName + ' [';
if not FNullSchedDate then
Result := Result + FormatDateTime('ddddd', SchedDate);
Result := Result + ']';
{
if Title <> '' then
Result := Title
else
Result := Inherited GetDisplayName;
}
end;
procedure TJvTFDaysCol.CheckTemplate;
begin
if Assigned(ColCollection.ApptGrid) then
with ColCollection.ApptGrid.Template do
if not UpdatingGrid then
ActiveTemplate := agtNone;
end;
procedure TJvTFDaysCol.SetIndex(Value: Integer);
begin
if not Assigned(ColCollection.ApptGrid) or
(ColCollection.ApptGrid.Template.ActiveTemplate <> agtLinear) then
inherited SetIndex(Value);
end;
procedure TJvTFDaysCol.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysCol then
begin
Title := TJvTFDaysCol(Source).Title;
Width := TJvTFDaysCol(Source).Width;
SchedName := TJvTFDaysCol(Source).SchedName;
SchedDate := TJvTFDaysCol(Source).SchedDate;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysCol.AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
if IsStoredWidth then
FWidth := round(FWidth * AXProportion);
end;
end;
function TJvTFDaysCol.ColCollection: TJvTFDaysCols;
begin
Result := TJvTFDaysCols(Collection);
end;
function TJvTFDaysCol.Connected: Boolean;
begin
Result := Assigned(FSchedule);
end;
procedure TJvTFDaysCol.Connect;
var
ApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
begin
ApptGrid := ColCollection.ApptGrid;
FPrinter := ColCollection.Printer;
if Assigned(ApptGrid) then
begin
if not Connected and not (csDesigning in ApptGrid.ComponentState) and
not FNullSchedDate and (SchedName <> '') and Assigned(ApptGrid.ScheduleManager) and
not (csLoading in ApptGrid.ComponentState) then
begin
FSchedule := ApptGrid.RetrieveSchedule(SchedName, SchedDate);
FMap.Refresh;
ApptGrid.Invalidate;
//UpdateTitle;
UpdateTitles;
end;
end
else
if Assigned(FPrinter) then
begin
if not Connected and not (csDesigning in FPrinter.ComponentState) and
not FNullSchedDate and (SchedName <> '') and
Assigned(FPrinter.ScheduleManager) and
not (csLoading in FPrinter.ComponentState) then
begin
FSchedule := FPrinter.RetrieveSchedule(SchedName, SchedDate);
FMap.Refresh;
//UpdateTitle;
UpdateTitles;
end;
end;
end;
procedure TJvTFDaysCol.Disconnect;
var
ApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
lSchedName: string;
lSchedDate: TDate;
begin
if not FDisconnecting then
try
FDisconnecting := True;
ApptGrid := ColCollection.ApptGrid;
FPrinter := ColCollection.Printer;
if Assigned(ApptGrid) then
begin
if Connected and Assigned(ApptGrid.ScheduleManager) then
begin
lSchedName := Schedule.SchedName;
lSchedDate := Schedule.SchedDate;
FSchedule := nil;
FMap.Clear;
ApptGrid.ReleaseSchedule(lSchedName, lSchedDate);
ApptGrid.Invalidate;
end;
end
else
if Assigned(FPrinter) then
begin
if Connected and Assigned(FPrinter.ScheduleManager) then
begin
lSchedName := Schedule.SchedName;
lSchedDate := Schedule.SchedDate;
FSchedule := nil;
FMap.Clear;
FPrinter.ReleaseSchedule(lSchedName, lSchedDate);
end;
end;
finally
FDisconnecting := False;
end;
end;
procedure TJvTFDaysCol.SetSchedule(const NewSchedName: string; NewSchedDate: TDate);
begin
Disconnect;
FSchedName := SchedName;
FSchedDate := SchedDate;
FNullSchedDate := False;
Connect;
//UpdateTitle;
UpdateTitles;
CheckTemplate;
end;
procedure TJvTFDaysCol.RefreshMap;
begin
FMap.Refresh;
end;
procedure TJvTFDaysCol.CalcStartEndRows(Appt: TJvTFAppt;
var StartRow, EndRow: Integer);
var
ApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
begin
ApptGrid := ColCollection.ApptGrid;
FPrinter := ColCollection.Printer;
if Assigned(ApptGrid) then
begin
if Trunc(Appt.StartDate) = Trunc(SchedDate) then
StartRow := ApptGrid.TimeToRow(Appt.StartTime)
else
StartRow := 0;
if Trunc(Appt.EndDate) = Trunc(SchedDate) then
EndRow := ApptGrid.TimeToRow(ApptGrid.AdjustEndTime(Appt.EndTime))
else
EndRow := ApptGrid.RowCount - 1;
end
else
if Assigned(FPrinter) then
begin
if Trunc(Appt.StartDate) = Trunc(SchedDate) then
StartRow := FPrinter.TimeToRow(Appt.StartTime)
else
StartRow := 0;
if Trunc(Appt.EndDate) = Trunc(SchedDate) then
EndRow := FPrinter.TimeToRow(FPrinter.AdjustEndTime(Appt.EndTime))
else
EndRow := FPrinter.RowCount - 1;
end;
end;
{
procedure TJvTFDaysCol.UpdateTitle;
Var
NewTitle: string;
ApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
begin
ApptGrid := ColCollection.ApptGrid;
FPrinter := ColCollection.Printer;
if Assigned(ApptGrid) then
begin
if (ApptGrid.Template.ActiveTemplate = agtLinear) and
(ApptGrid.Template.ShortTitles) then
NewTitle := FormatDateTime(ApptGrid.DateFormat, SchedDate)
else
if (ApptGrid.Template.ActiveTemplate = agtComparative) and
(ApptGrid.Template.ShortTitles) then
NewTitle := SchedName
else
NewTitle := SchedName + ' - ' + FormatDateTime(ApptGrid.DateFormat, SchedDate);
if Assigned(ApptGrid.OnUpdateColTitle) then
ApptGrid.OnUpdateColTitle(ApptGrid, Self, NewTitle);
Title := NewTitle;
end
else
if Assigned(FPrinter) then
begin
NewTitle := SchedName + ' - ' +
FormatDateTime(FPrinter.DateFormat, SchedDate);
if Assigned(FPrinter.OnUpdateColTitle) then
FPrinter.OnUpdateColTitle(FPrinter, Self, NewTitle);
Title := NewTitle;
end;
end;
}
function TJvTFDaysCol.GetFirstAppt: TJvTFAppt;
var
ApptList: TStringList;
begin
Result := nil;
ApptList := TStringList.Create;
try
FMap.GetAppts(0, ColCollection.ApptGrid.RowCount - 1, ApptList);
if ApptList.Count > 0 then
Result := TJvTFAppt(ApptList.Objects[0]);
finally
ApptList.Free;
end;
end;
function TJvTFDaysCol.GetLastAppt: TJvTFAppt;
var
ApptList: TStringList;
begin
Result := nil;
ApptList := TStringList.Create;
try
FMap.GetAppts(0, ColCollection.ApptGrid.RowCount - 1, ApptList);
if ApptList.Count > 0 then
Result := TJvTFAppt(ApptList.Objects[ApptList.Count - 1]);
finally
ApptList.Free;
end;
end;
function TJvTFDaysCol.GetNextAppt(RefAppt: TJvTFAppt): TJvTFAppt;
var
ApptList: TStringList;
NextIndex: Integer;
begin
if not Assigned(RefAppt) then
begin
Result := GetFirstAppt;
Exit;
end;
Result := nil;
ApptList := TStringList.Create;
try
FMap.GetAppts(0, ColCollection.ApptGrid.RowCount - 1, ApptList);
if ApptList.Count > 0 then
begin
NextIndex := ApptList.IndexOfObject(RefAppt) + 1;
// if NextIndex = 0 then RefAppt is in a different column,
// so return the first appt.
if (NextIndex >= 0) and (NextIndex < ApptList.Count) then
Result := TJvTFAppt(ApptList.Objects[NextIndex]);
end;
finally
ApptList.Free;
end;
end;
function TJvTFDaysCol.GetPrevAppt(RefAppt: TJvTFAppt): TJvTFAppt;
var
ApptList: TStringList;
PrevIndex: Integer;
begin
if RefAppt = nil then
begin
Result := GetLastAppt;
Exit;
end;
Result := nil;
ApptList := TStringList.Create;
try
FMap.GetAppts(0, ColCollection.ApptGrid.RowCount - 1, ApptList);
if ApptList.Count > 0 then
begin
PrevIndex := ApptList.IndexOfObject(RefAppt) - 1;
if PrevIndex > -1 then
Result := TJvTFAppt(ApptList.Objects[PrevIndex])
else
if PrevIndex = -2 then
// RefAppt is in a different column so return last appt
Result := GetLastAppt;
end;
finally
ApptList.Free;
end;
end;
procedure TJvTFDaysCol.SetGroupTitle(const Value: string);
begin
if Value <> FGroupTitle then
begin
FGroupTitle := Value;
if Assigned(ColCollection.ApptGrid) then
ColCollection.ApptGrid.Invalidate;
end;
end;
procedure TJvTFDaysCol.UpdateTitles;
var
NewTitle, NewGroupTitle, NameStr, DateStr: string;
ApptGrid: TJvTFDays;
FPrinter: TJvTFDaysPrinter;
FromGrid: Boolean;
Grouping: TJvTFDaysGrouping;
begin
ApptGrid := ColCollection.ApptGrid;
FPrinter := ColCollection.Printer;
if not Assigned(ApptGrid) and not Assigned(FPrinter) then
Exit;
FromGrid := Assigned(ApptGrid);
if FromGrid then
Grouping := ApptGrid.Grouping
else
Grouping := FPrinter.Grouping;
if FNullSchedDate then
DateStr := ''
else
if FromGrid then
DateStr := FormatDateTime(ApptGrid.DateFormat, SchedDate)
else
DateStr := FormatDateTime(FPrinter.DateFormat, SchedDate);
if Assigned(Schedule) and (Schedule.SchedDisplayName <> '') then
NameStr := Schedule.SchedDisplayName
else
NameStr := SchedName;
case Grouping of
grNone:
begin
NewGroupTitle := '';
NewTitle := NameStr + ' - ' + DateStr;
end;
grDate:
begin
NewGroupTitle := DateStr;
NewTitle := NameStr;
end;
grResource:
begin
NewGroupTitle := NameStr;
NewTitle := DateStr;
end;
grCustom:
begin
NewGroupTitle := GroupTitle;
NewTitle := NameStr + ' - ' + DateStr;
end;
end;
if FromGrid then
begin
if Assigned(ApptGrid.OnUpdateColTitles) then
ApptGrid.OnUpdateColTitles(ApptGrid, Self, NewGroupTitle, NewTitle)
end
else
if Assigned(FPrinter.OnUpdateColTitles) then
FPrinter.OnUpdateColTitles(FPrinter, Self, NewGroupTitle, NewTitle);
GroupTitle := NewGroupTitle;
Title := NewTitle;
end;
procedure TJvTFDaysCol.DumpMap;
begin
FMap.Dump('Map Dump (' + IntToStr(Index) + ').txt');
end;
function TJvTFDaysCol.ApptInCol(Appt: TJvTFAppt): Boolean;
begin
Result := FMap.HasAppt(Appt);
end;
function TJvTFDaysCol.LocateMapCol(Appt: TJvTFAppt; MapSearchRow: Integer): Integer;
begin
Result := FMap.LocateMapCol(Appt, MapSearchRow);
end;
function TJvTFDaysCol.MapColCount(Row: Integer): Integer;
begin
Result := FMap.ColCount(Row);
end;
function TJvTFDaysCol.MapLocation(Col, Row: Integer): TJvTFAppt;
begin
Result := FMap.Location[Row, Col];
end;
//=== { TJvTFDaysCols } ======================================================
constructor TJvTFDaysCols.Create(AApptGrid: TJvTFDays);
begin
inherited Create(TJvTFDaysCol);
FApptGrid := AApptGrid;
FOldCount := 0;
end;
constructor TJvTFDaysCols.CreateForPrinter(APrinter: TJvTFDaysPrinter);
begin
inherited Create(TJvTFDaysCol);
FPrinter := APrinter;
end;
function TJvTFDaysCols.GetItem(Index: Integer): TJvTFDaysCol;
begin
Result := TJvTFDaysCol(inherited GetItem(Index));
end;
procedure TJvTFDaysCols.SetItem(Index: Integer; Value: TJvTFDaysCol);
begin
inherited SetItem(Index, Value);
end;
procedure TJvTFDaysCols.EnsureCol(Index: Integer);
begin
if (Index < 0) or (Index > Count - 1) then
raise EJvTFDaysError.CreateRes(@RsEColumnIndexOutOfBounds);
end;
function TJvTFDaysCols.GetOwner: TPersistent;
begin
if Assigned(FApptGrid) then
Result := FApptGrid
else
if Assigned(FPrinter) then
Result := FPrinter
else
Result := nil;
end;
procedure TJvTFDaysCols.SizeCols;
var
DataWidth, Base, MakeUp, I: Integer;
begin
// DO NOT RUN IF WE'RE ALREADY IN THE SIZING PROCESS!!
if SizingCols or (Count <= 0) then
Exit;
if Assigned(FApptGrid) then
try
FSizingCols := True;
DataWidth := ApptGrid.GetDataWidth;
Base := DataWidth div Count;
if Base >= ApptGrid.MinColWidth then
begin
MakeUp := DataWidth - (Base * Count);
for I := 0 to MakeUp - 1 do
Items[I].Width := Base + 1;
for I := MakeUp to Count - 1 do
Items[I].Width := Base;
end
finally
FSizingCols := False;
end
else
begin
// sizing for printer
end;
end;
procedure TJvTFDaysCols.Update(Item: TCollectionItem);
begin
{*******************************************************************}
{** DO NOT PUT ANY CALLS TO SHOWMESSAGE IN THIS ROUTINE!!!! *******}
{** IT WILL BLOW UP WHEN REMOVING COLS AT DESIGN TIME!!!! *******}
{*******************************************************************}
// Exit if owner is printer
if not Assigned(ApptGrid) or (csLoading in ApptGrid.ComponentState) then
Exit;
try
FUpdating := True;
ApptGrid.ClearSelection;
if Count > FOldCount then // we're adding a col
try
FAddingCol := True;
// if we're adding the first col then set left col to 0.
if FOldCount = 0 then
ApptGrid.LeftCol := 0;
if ApptGrid.AutoSizeCols then
begin
// default col width to grid's min col width
Items[Count - 1].Width := ApptGrid.MinColWidth;
if not (vsbHorz in ApptGrid.VisibleScrollBars) then
// run the CheckSBVis routine
if not ApptGrid.CheckSBVis then
// if CheckSBVis didn't resize the cols then recheck
// the visibility of the horz scroll bar. if still not
// visible, then size the cols.
if not (vsbHorz in ApptGrid.VisibleScrollBars) then
SizeCols;
end
else
Items[Count - 1].Width := ApptGrid.DefColWidth;
finally
FAddingCol := False;
end
else
if Count < FOldCount then // we're removing a col
begin
if ApptGrid.FocusedCol >= Count then
ApptGrid.FocusedCol := Count - 1;
if ApptGrid.SelStart.X >= Count then
ApptGrid.SelStart := Point(Count - 1, ApptGrid.SelStart.Y);
if ApptGrid.LeftCol >= Count then
ApptGrid.LeftCol := Count - 1;
if ApptGrid.AutoSizeCols then
begin
if vsbHorz in ApptGrid.VisibleScrollBars then
begin
// run the CheckSBVis routine
if not ApptGrid.CheckSBVis then
// if CheckSBVis didn't resize the cols then recheck
// the visibility of the horz scroll bar. if still not
// visible, then size the cols.
if not (vsbHorz in ApptGrid.VisibleScrollBars) then
SizeCols;
end
else
SizeCols;
end
else
ApptGrid.CheckSBVis;
end;
finally
FUpdating := False;
FOldCount := Count;
FApptGrid.Invalidate;
end;
end;
function TJvTFDaysCols.Add: TJvTFDaysCol;
begin
Result := TJvTFDaysCol(inherited Add);
end;
procedure TJvTFDaysCols.AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
var
i: Integer;
begin
for i := 0 to Count-1 do
Items[i].AutoAdjustLayout(AMode, AXProportion, AYProportion);
end;
procedure TJvTFDaysCols.EnsureMinColWidth;
var
I, MCW: Integer;
begin
if Assigned(ApptGrid) then
MCW := ApptGrid.MinColWidth
else
if Assigned(FPrinter) then
MCW := FPrinter.MinColWidth
else
Exit;
for I := 0 to Count - 1 do
if Items[I].Width < MCW then
Items[I].Width := MCW;
end;
procedure TJvTFDaysCols.EnsureMaxColWidth;
var
I: Integer;
DataW: Integer;
begin
if not Assigned(ApptGrid) or not (agoEnforceMaxColWidth in ApptGrid.Options) then
Exit;
DataW := ApptGrid.GetDataWidth;
for I := 0 to Count - 1 do
if Items[I].Width > DataW then
Items[I].Width := DataW;
end;
procedure TJvTFDaysCols.ResizeCols;
begin
SizeCols;
end;
procedure TJvTFDaysCols.MoveCol(SourceIndex, TargetIndex: Integer);
var
SelID: Integer;
begin
if SourceIndex <> TargetIndex then
begin
SelID := -1;
EnsureCol(SourceIndex);
EnsureCol(TargetIndex);
if Assigned(ApptGrid) and (ApptGrid.FocusedCol > -1) then
SelID := Items[ApptGrid.FocusedCol].ID;
Items[SourceIndex].Index := TargetIndex;
if Assigned(ApptGrid) and (ApptGrid.FocusedCol > -1) then
ApptGrid.FocusedCol := FindItemID(SelID).Index;
// sychronize the CompName list
if Assigned(ApptGrid) and
(ApptGrid.Template.ActiveTemplate = agtComparative) then
begin
FUpdating := True;
try
ApptGrid.Template.CompNames.Move(SourceIndex, TargetIndex);
finally
FUpdating := False;
end;
end;
end;
end;
procedure TJvTFDaysCols.Assign(Source: TPersistent);
var
I: Integer;
begin
if Source is TJvTFDaysCols then
begin
BeginUpdate;
try
Clear;
for I := 0 to TJvTFDaysCols(Source).Count - 1 do
Add.Assign(TJvTFDaysCols(Source).Items[I]);
finally
EndUpdate;
end;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysCols.UpdateTitles;
var
I: Integer;
begin
for I := 0 to Count - 1 do
Items[I].UpdateTitles;
end;
//=== { TJvTFDaysFancyRowHdrAttr } ===========================================
constructor TJvTFDaysFancyRowHdrAttr.Create(AOwner: TJvTFDays);
var
h: Integer;
begin
inherited Create;
FGrid := AOwner;
FTickColor := clGray;
FColor := clBtnFace;
FMinorFont := TFont.Create;
if Assigned(FGrid) then
FMinorFont.Assign(FGrid.Font);
FMinorFont.PixelsPerInch := 96;
FMajorFont := TFont.Create;
if Assigned(FGrid) then
FMajorFont.Assign(FGrid.Font);
if FMajorFont.Height = 0 then
begin
h := MulDiv(GetFontData(FMajorFont.Reference.Handle).Height, FMajorFont.PixelsPerInch, Screen.PixelsPerInch);
FMajorFont.Height := h*3 div 2;
end;
FMajorFont.PixelsPerInch := 96;
FMinorFont.OnChange := @FontChange;
FMajorFont.OnChange := @FontChange;
FOnlyShow00Minutes := True;
end;
destructor TJvTFDaysFancyRowHdrAttr.Destroy;
begin
FMinorFont.OnChange := nil;
FMajorFont.OnChange := nil;
FMinorFont.Free;
FMajorFont.Free;
inherited Destroy;
end;
procedure TJvTFDaysFancyRowHdrAttr.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFDaysFancyRowHdrAttr.SetHr2400(Value: Boolean);
begin
if Value <> FHr2400 then
begin
FHr2400 := Value;
Change;
end;
end;
procedure TJvTFDaysFancyRowHdrAttr.SetMinorFont(Value: TFont);
begin
FMinorFont.Assign(Value);
end;
procedure TJvTFDaysFancyRowHdrAttr.SetMajorFont(Value: TFont);
begin
FMajorFont.Assign(Value);
end;
procedure TJvTFDaysFancyRowHdrAttr.SetTickColor(Value: TColor);
begin
if Value <> FTickColor then
begin
FTickColor := Value;
Change;
end;
end;
procedure TJvTFDaysFancyRowHdrAttr.SetOnlyShow00Minutes(Value: Boolean);
begin
if Value <> FOnlyShow00Minutes then
begin
FOnlyShow00Minutes := Value;
Change;
end;
end;
procedure TJvTFDaysFancyRowHdrAttr.Change;
begin
if Assigned(FGrid) then
FGrid.Invalidate;
end;
procedure TJvTFDaysFancyRowHdrAttr.FontChange(Sender: TObject);
begin
Change;
end;
procedure TJvTFDaysFancyRowHdrAttr.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysFancyRowHdrAttr then
begin
FTickColor := TJvTFDaysFancyRowHdrAttr(Source).TickColor;
FMinorFont.OnChange := nil;
FMajorFont.OnChange := nil;
FMinorFont.Assign(TJvTFDaysFancyRowHdrAttr(Source).MinorFont);
FMajorFont.Assign(TJvTFDaysFancyRowHdrAttr(Source).MajorFont);
FMinorFont.OnChange := @FontChange;
FMajorFont.OnChange := @FontChange;
FHr2400 := TJvTFDaysFancyRowHdrAttr(Source).Hr2400;
FColor := TJvTFDaysFancyRowHdrAttr(Source).Color;
Change;
end
else
inherited Assign(Source);
end;
//=== { TJvTFDaysHdrAttr } ===================================================
constructor TJvTFDaysHdrAttr.Create(AOwner: TJvTFDays);
begin
inherited Create;
FApptGrid := AOwner;
FFont := TFont.Create;
if Assigned(FApptGrid) then
begin
FFont.Assign(FApptGrid.Font);
FParentFont := True;
end else
FParentFont := False;
FFont.PixelsPerInch := 96;
FFont.OnChange := @FontChange;
FColor := clBtnFace;
FFrame3D := True;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FFrameColor := clBlack;
{$ENDIF Jv_TIMEBLOCKS}
end;
destructor TJvTFDaysHdrAttr.Destroy;
begin
FFont.Free;
inherited Destroy;
end;
procedure TJvTFDaysHdrAttr.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFDaysHdrAttr.SetFont(Value: TFont);
begin
if Value <> FFont then
begin
FFont.Assign(Value);
FFont.OnChange := @FontChange;
if Assigned(FApptGrid) then
ParentFont := Value = FApptGrid.Font;
Change;
end;
end;
procedure TJvTFDaysHdrAttr.SetParentFont(Value: Boolean);
begin
if Value and Assigned(FApptGrid) then
Font.Assign(FApptGrid.Font);
FParentFont := Value;
end;
procedure TJvTFDaysHdrAttr.SetFrame3D(Value: Boolean);
begin
if Value <> FFrame3D then
begin
FFrame3D := Value;
Change;
end;
end;
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDaysHdrAttr.SetFrameColor(Value: TColor);
begin
if Value <> FFrameColor then
begin
FFrameColor := Value;
Change;
end;
end;
// ok
procedure TJvTFDaysHdrAttr.SetTitleRotation(Value: Integer);
begin
if Value <> FTitleRotation then
begin
FTitleRotation := Value;
Change;
end;
end;
{$ENDIF Jv_TIMEBLOCKS}
procedure TJvTFDaysHdrAttr.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysHdrAttr.FontChange(Sender: TObject);
begin
ParentFont := False;
Change;
end;
procedure TJvTFDaysHdrAttr.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysHdrAttr then
try
FParentFont := False;
Frame3D := TJvTFDaysHdrAttr(Source).Frame3D;
FColor := TJvTFDaysHdrAttr(Source).Color;
Font.Assign(TJvTFDaysHdrAttr(Source).Font);
Font.OnChange := @FontChange;
ParentFont := TJvTFDaysHdrAttr(Source).ParentFont;
{$IFDEF Jv_TIMEBLOCKS}
// ok
FFrameColor := TJvTFDaysHdrAttr(Source).FrameColor;
// ok
FTitleRotation := TJvTFDaysHdrAttr(Source).TitleRotation;
{$ENDIF Jv_TIMEBLOCKS}
finally
Change;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysHdrAttr.ParentFontChanged;
begin
if ParentFont and Assigned(FApptGrid) then
begin
// Disconnect Font.OnChange
FFont.OnChange := nil;
// Assign the parent font to FFont
FFont.Assign(FApptGrid.Font);
// Reconnect Font.OnChange
FFont.OnChange := @FontChange;
end;
end;
//=== { TJvTFDaysApptBar } ===================================================
constructor TJvTFDaysApptBar.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FApptGrid := AApptGrid;
FColor := clBlue;
FWidth := DEFAULT_APPT_BAR_WIDTH; // will be scaled by ApptGrid
FVisible := True;
FTimeStampStyle := tssBlock;
FTimeStampColor := clBlue;
end;
procedure TJvTFDaysApptBar.AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
if IsStoredWidth then
FWidth := round(FWidth * AXProportion);
end;
end;
procedure TJvTFDaysApptBar.SetColor(Value: TColor);
begin
if FColor <> Value then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFDaysApptBar.SetVisible(Value: Boolean);
begin
if FVisible <> Value then
begin
FVisible := Value;
Change;
end;
end;
procedure TJvTFDaysApptBar.SetWidth(Value: Integer);
begin
if Value < 0 then
Value := 0;
if FWidth <> Value then
begin
FWidth := Value;
Change;
end;
end;
procedure TJvTFDaysApptBar.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysApptBar.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysApptBar then
begin
FColor := TJvTFDaysApptBar(Source).Color;
FVisible := TJvTFDaysApptBar(Source).Visible;
FWidth := TJvTFDaysApptBar(Source).Width;
FTimeStampStyle := TJvTFDaysApptBar(Source).TimeStampStyle;
FTimeStampColor := TJvTFDaysApptBar(Source).TimeStampColor;
Change;
end
else
inherited Assign(Source);
end;
function TJvTFDaysApptBar.IsStoredWidth: Boolean;
begin
if Assigned(FApptGrid) then
Result := FWidth <> FApptGrid.Scale96ToFont(DEFAULT_APPT_BAR_WIDTH)
else
Result := true;
end;
procedure TJvTFDaysApptBar.SetTimeStampColor(Value: TColor);
begin
if FTimeStampColor <> Value then
begin
FTimeStampColor := Value;
Change;
end;
end;
procedure TJvTFDaysApptBar.SetTFTimeStampStyle(Value: TJvTFTimeStampStyle);
begin
if FTimeStampStyle <> Value then
begin
FTimeStampStyle := Value;
Change;
end;
end;
//=== { TJvTFDaysApptAttr } ==================================================
constructor TJvTFDaysApptAttr.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FApptGrid := AApptGrid;
FFont := TFont.Create;
if Assigned(FApptGrid) then
begin
FFont.Assign(FApptGrid.Font);
FParentFont := True;
end
else
FParentFont := False;
FFont.PixelsPerInch := 96;
FFont.OnChange := @FontChange;
FFrameWidth := 1;
FFrameColor := clBlack;
FColor := clWindow;
end;
destructor TJvTFDaysApptAttr.Destroy;
begin
FFont.OnChange := nil;
FFont.Free;
inherited Destroy;
end;
procedure TJvTFDaysApptAttr.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFDaysApptAttr.SetFont(Value: TFont);
begin
if Value <> FFont then
begin
FFont.Assign(Value);
FFont.OnChange := @FontChange;
if Assigned(FApptGrid) then
ParentFont := Value = FApptGrid.Font;
Change;
end;
end;
procedure TJvTFDaysApptAttr.SetParentFont(Value: Boolean);
begin
if Assigned(FApptGrid) and Value then
Font.Assign(FApptGrid.Font);
FParentFont := Value;
end;
procedure TJvTFDaysApptAttr.SetFrameColor(Value: TColor);
begin
if Value <> FFrameColor then
begin
FFrameColor := Value;
Change;
end;
end;
procedure TJvTFDaysApptAttr.SetFrameWidth(Value: Integer);
begin
if Value <> FFrameWidth then
begin
FFrameWidth := Value;
Change;
end;
end;
procedure TJvTFDaysApptAttr.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysApptAttr.FontChange(Sender: TObject);
begin
ParentFont := False;
Change;
end;
procedure TJvTFDaysApptAttr.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysApptAttr then
try
FParentFont := False;
FFrameWidth := TJvTFDaysApptAttr(Source).FrameWidth;
FFrameColor := TJvTFDaysApptAttr(Source).FrameColor;
FColor := TJvTFDaysApptAttr(Source).Color;
Font.Assign(TJvTFDaysApptAttr(Source).Font);
ParentFont := TJvTFDaysApptAttr(Source).ParentFont;
finally
Change;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysApptAttr.ParentFontChanged;
begin
if ParentFont and Assigned(FApptGrid) then
begin
FFont.OnChange := nil;
FFont.Assign(FApptGrid.Font);
FFont.OnChange := @FontChange;
end;
end;
//=== { TJvTFSelCellAttr } ===================================================
constructor TJvTFSelCellAttr.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FApptGrid := AApptGrid;
FColor := clHighlight;
FStyle := scsSolid;
FFrameWidth := 2;
end;
procedure TJvTFSelCellAttr.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFSelCellAttr.SetFrameWidth(Value: Integer);
begin
if Value <> FFrameWidth then
begin
FFrameWidth := Value;
Change;
end;
end;
procedure TJvTFSelCellAttr.SetStyle(Value: TJvTFSelCellStyle);
begin
if Value <> FStyle then
begin
FStyle := Value;
Change;
end;
end;
procedure TJvTFSelCellAttr.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFSelCellAttr.Assign(Source: TPersistent);
begin
if Source is TJvTFSelCellAttr then
begin
FColor := TJvTFSelCellAttr(Source).Color;
FStyle := TJvTFSelCellAttr(Source).Style;
FFrameWidth := TJvTFSelCellAttr(Source).FrameWidth;
Change;
end
else
inherited Assign(Source);
end;
//=== { TJvTFDaysGrabHandles } ===============================================
constructor TJvTFDaysGrabHandles.Create(AApptGrid: TJvTFDays);
begin
inherited Create;
FApptGrid := AApptGrid;
FStyle := gsFlat;
FColor := clBlue;
FHeight := DEFAULT_GRAB_HANDLES_HEIGHT; // will be scaled by ApptGrid
end;
procedure TJvTFDaysGrabHandles.AutoAdjustLayout(
const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
if IsStoredHeight then
FHeight := round(FHeight * AYProportion);
end;
end;
function TJvTFDaysGrabHandles.IsStoredHeight: Boolean;
begin
if Assigned(FApptGrid) then
Result := FHeight <> FApptGrid.Scale96ToFont(DEFAULT_GRAB_HANDLES_HEIGHT)
else
Result := true;
end;
procedure TJvTFDaysGrabHandles.SetColor(Value: TColor);
begin
if Value <> FColor then
begin
FColor := Value;
Change;
end;
end;
procedure TJvTFDaysGrabHandles.SetHeight(Value: Integer);
begin
if Value < 1 then
Value := 1;
if Value <> FHeight then
begin
FHeight := Value;
Change;
end;
end;
procedure TJvTFDaysGrabHandles.SetStyle(Value: TJvTFGrabStyle);
begin
if Value <> FStyle then
begin
FStyle := Value;
if Style = gs3D then
FHeight := 6;
Change;
end;
end;
procedure TJvTFDaysGrabHandles.Change;
begin
if Assigned(FApptGrid) then
FApptGrid.Invalidate;
end;
procedure TJvTFDaysGrabHandles.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysGrabHandles then
begin
FHeight := TJvTFDaysGrabHandles(Source).Height;
FColor := TJvTFDaysGrabHandles(Source).Color;
FStyle := TJvTFDaysGrabHandles(Source).Style;
Change;
end
else
inherited Assign(Source);
end;
//=== { TJvTFDays } ==========================================================
constructor TJvTFDays.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle +
[csOpaque, csCaptureMouse, csClickEvents, csDoubleClicks];
FSaveFocCol := -1;
//set property defaults
// FBorderStyle := bsSingle;
FColHdrHeight := Scale96ToFont(DEFAULT_COL_HDR_HEIGHT);
FGroupHdrHeight := Scale96ToFont(DEFAULT_GROUP_HDR_HEIGHT);
FDefColWidth := Scale96ToFont(DEFAULT_DEF_COL_WIDTH);
FMinColWidth := Scale96ToFont(DEFAULT_MIN_COL_WIDTH);
FMinRowHeight := Scale96ToFont(DEFAULT_MIN_ROW_HEIGHT);
FRowHdrWidth := Scale96ToFont(DEFAULT_ROW_HDR_WIDTH);
FRowHeight := Scale96ToFont(DEFAULT_ROW_HEIGHT);
FGranularity := DEFAULT_GRANULARITY;
FTopRow := 0;
FFocusedRow := -1;
FLeftCol := -1;
FFocusedCol := -1;
FVisibleScrollBars := [];
FAutoSizeCols := True;
ParentColor := False;
Color := clSilver;
FOptions := [agoSizeCols, agoSizeRows, agoSizeColHdr, agoSizeRowHdr,
agoSizeAppt, agoMoveAppt, agoEditing, agoShowPics,
agoShowText, agoShowApptHints, agoQuickEntry, agoShowSelHint];
FColTitleStyle := ctsSingleEllipsis;
FRowHdrType := rhFancy;
FSelStart := Point(-1, -1);
FSelEnd := FSelStart;
FApptBuffer := 5;
FFocusedCol := -1;
FFocusedRow := -1;
FGridLineColor := clGray;
FDitheredBackground := false;
{$IFDEF Jv_TIMEBLOCKS}
// all ok
FWeekend := [dowSunday, dowSaturday];
FWeekendColor := clSilver;
FWeekendFillPic := TBitmap.Create;
FWeekendFillPic.Height := 16;
FWeekendFillPic.Width := 16;
UpdateWeekendFillPic;
{$ENDIF Jv_TIMEBLOCKS}
// Create internal objects
FVScrollBar := TScrollBar.Create(Self); //TJvTFDaysScrollBar.Create(Self);
with FVScrollBar do
begin
Kind := sbVertical;
TabStop := False;
Anchors := [];
Parent := Self;
Visible := False;
OnScroll := @ScrollBarScroll;
end;
FHScrollBar := TScrollBar.Create(Self); //TJvTFDaysScrollBar.Create(Self);
with FHScrollBar do
begin
Kind := sbHorizontal;
TabStop := False;
Anchors := [];
Parent := Self;
Visible := False;
OnScroll := @ScrollBarScroll;
end;
FHdrAttr := TJvTFDaysHdrAttr.Create(Self);
FHdrAttr.Color := clBtnFace;
FSelHdrAttr := TJvTFDaysHdrAttr.Create(Self);
with FSelHdrAttr do
begin
Color := clBtnFace;
Font.Color := clWindowText;
end;
FGroupHdrAttr := TJvTFDaysHdrAttr.Create(Self);
FGroupHdrAttr.Color := clBtnFace;
FSelGroupHdrAttr := TJvTFDaysHdrAttr.Create(Self);
with FSelGroupHdrAttr do
begin
Color := clBtnFace;
Font.Color := clWindowText;
end;
FFancyRowHdrAttr := TJvTFDaysFancyRowHdrAttr.Create(Self);
FSelFancyRowHdrAttr := TJvTFDaysFancyRowHdrAttr.Create(Self);
with FSelFancyRowHdrAttr do
begin
TickColor := clWindowText;
MinorFont.Color := clWindowText;
MajorFont.Color := clWindowText;
end;
FSelCellAttr := TJvTFSelCellAttr.Create(Self);
FApptBar := TJvTFDaysApptBar.Create(Self);
FApptBar.Width := Scale96ToFont(DEFAULT_APPT_BAR_WIDTH);
FCols := TJvTFDaysCols.Create(Self);
{$IFDEF Jv_TIMEBLOCKS}
// ok
FTimeBlocks := TJvTFDaysTimeBlocks.Create(Self);
FTimeBlockProps := TJvTFDaysBlockProps.Create(Self);
FTimeBlockProps.FBlockHdrWidth := Scale96ToFont(DEFAULT_BLOCK_HDR_WIDTH);
{$ENDIF Jv_TIMEBLOCKS}
FEditor := TJvTFInPlaceApptEditor.Create(Self);
with FEditor do
begin
Visible := False;
Parent := Self;
end;
FThresholds := TJvTFDaysThresholds.Create(Self);
FPrimeTime := TJvTFDaysPrimeTime.Create(Self);
FApptAttr := TJvTFDaysApptAttr.Create(Self);
FSelApptAttr := TJvTFDaysApptAttr.Create(Self);
FTemplate := TJvTFDaysTemplate.Create(Self);
FGrabHandles := TJvTFDaysGrabHandles.Create(Self);
FGrabHandles.Height := Scale96ToFont(DEFAULT_GRAB_HANDLES_HEIGHT);
FHintProps := TJvTFHintProps.Create(Self);
//FHint := TJvTFHint.Create(Self);
FHint := GetTFHintClass.Create(Self);
FHint.RefProps := FHintProps;
PaintBuffer := TBitmap.Create;
FShowFocus := True;
with GetControlClassDefaultSize do
SetInitialBounds(0, 0, CX, CY);
end;
destructor TJvTFDays.Destroy;
begin
FVScrollBar.Free;
FHScrollBar.Free;
FHdrAttr.Free;
FSelHdrAttr.Free;
FGroupHdrAttr.Free;
FSelGroupHdrAttr.Free;
FFancyRowHdrAttr.Free;
FSelFancyRowHdrAttr.Free;
FSelCellAttr.Free;
FApptBar.Free;
FPrimeTime.Free;
{$IFDEF Jv_TIMEBLOCKS}
// all ok
FTimeBlocks.Free;
FTimeBlockProps.Free;
FWeekendFillPic.Free;
{$ENDIF Jv_TIMEBLOCKS}
FEditor.Free;
FThresholds.Free;
FApptAttr.Free;
FSelApptAttr.Free;
FHint.Free;
FHintProps.Free;
FTemplate.Free;
FGrabHandles.Free;
PaintBuffer.Free;
inherited Destroy;
// This MUST be done after the inherited Destroy as it will set the Manager
// property to nil, thus triggering RelSchedNotification if ScheduleCount
// is still not 0. And in that very method, there is a test on Cols.Count.
// Hence, if FCols was to be freed before inherited, RelSchedNotification
// would try to access a freed object, leading to potential AVs.
FCols.Free;
end;
{
procedure TJvTFDays.CMCtl3DChanged(var Msg: TLMessage);
begin
if FBorderStyle = bsSingle then
RecreateWnd;
inherited;
end; }
{$IF LCL_FullVersion >= 1080000}
procedure TJvTFDays.DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
inherited;
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
if IsStoredColHdrHeight then
FColHdrHeight := round(FColHdrHeight * AYProportion);
if IsStoredDefColWidth then
FDefColWidth := round(FDefColWidth * AXProportion);
if IsStoredGroupHdrHeight then
FGroupHdrHeight := round(FGroupHdrHeight * AYProportion);
if IsStoredMinColWidth then
FMinColWidth := round(FMinColWidth * AXProportion);
if IsStoredMinRowHeight then
FMinRowHeight := round(FMinRowHeight * AYProportion);
if IsStoredRowHdrWidth then
FRowHdrWidth := round(FRowHdrWidth * AXProportion);
if IsStoredRowHeight then
FRowHeight := round(FRowHeight * AYProportion);
FApptBar.AutoAdjustLayout(AMode, AXProportion, AYProportion);
FCols.AutoAdjustLayout(AMode, AXProportion, AYProportion);
FGrabHandles.AutoAdjustLayout(AMode, AXProportion, AYProportion);
end;
end;
{$IFEND}
{$IF LCL_FullVersion >= 1080100}
procedure TJvTFDays.ScaleFontsPPI(const AToPPI: Integer; const AProportion: Double);
begin
inherited;
DoScaleFontPPI(ApptAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(FancyRowHdrAttr.MajorFont, AToPPI, AProportion);
DoScaleFontPPI(FancyRowHdrAttr.MinorFont, AToPPI, AProportion);
DoScaleFontPPI(GroupHdrAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(HdrAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(SelApptAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(SelFancyRowHdrAttr.MajorFont, AToPPI, AProportion);
DoScaleFontPPI(SelFancyRowHdrAttr.MinorFont, AToPPI, AProportion);
DoScaleFontPPI(SelGroupHdrAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(SelHdrAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(TimeBlockProps.BlockHdrAttr.Font, AToPPI, AProportion);
DoScaleFontPPI(TimeBlockProps.SelBlockHdrAttr.Font, AToPPI, AProportion);
end;
{$ELSEIF LCL_FullVersion >= 1080000}
procedure TJvTFDays.ScaleFontsPPI(const AProportion: Double);
begin
inherited;
DoScaleFontPPI(ApptAttr.Font, AProportion);
DoScaleFontPPI(FancyRowHdrAttr.MajorFont, AProportion);
DoScaleFontPPI(FancyRowHdrAttr.MinorFont, AProportion);
DoScaleFontPPI(GroupHdrAttr.Font, AProportion);
DoScaleFontPPI(HdrAttr.Font, AProportion);
DoScaleFontPPI(SelApptAttr.Font, AProportion);
DoScaleFontPPI(SelFancyRowHdrAttr.MajorFont, AProportion);
DoScaleFontPPI(SelFancyRowHdrAttr.MinorFont, AProportion);
DoScaleFontPPI(SelGroupHdrAttr.Font, AProportion);
DoScaleFontPPI(SelHdrAttr.Font, AProportion);
DoScaleFontPPI(TimeBlockProps.BlockHdrAttr.Font, AProportion);
DoScaleFontPPI(TimeBlockProps.SelBlockHdrAttr.Font, AProportion);
end;
{$IFEND}
procedure TJvTFDays.WMGetDlgCode(var Msg: TLMGetDlgCode);
begin
Msg.Result := DLGC_WANTALLKEYS or DLGC_WANTARROWS;
end;
{
procedure TJvTFDays.SetBorderStyle(Value: TBorderStyle);
begin
if FBorderStyle <> Value then
begin
FBorderStyle := Value;
RecreateWnd;
end;
end;
}
procedure TJvTFDays.SetTFVisibleScrollBars(Value: TJvTFVisibleScrollBars);
begin
if Value <> FVisibleScrollBars then
begin
FVisibleScrollBars := Value;
AlignScrollBars;
FVScrollBar.Visible := vsbVert in FVisibleScrollBars;
FHScrollBar.Visible := vsbHorz in FVisibleScrollBars;
end;
end;
procedure TJvTFDays.AlignScrollBars;
begin
// DO NOT INVALIDATE GRID IN THIS METHOD
if (FVScrollBar = nil) or (FHScrollbar = nil) then
exit;
FVScrollBar.Left := ClientWidth - FVScrollBar.Width;
FHScrollBar.Top := ClientHeight - FHScrollBar.Height;
with FVScrollBar do
begin
//group Top := ColHdrHeight;
Top := CalcGroupColHdrsHeight;
if vsbHorz in VisibleScrollBars then
Height := FHScrollBar.Top - Top
else
Height := Self.ClientHeight - Top;
end;
with FHScrollBar do
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
Left := CalcBlockRowHdrsWidth;
{$ELSE}
// remove
//Left := RowHdrWidth;
{$ENDIF Jv_TIMEBLOCKS}
if vsbVert in VisibleScrollBars then
Width := FVScrollBar.Left - Left
else
Width := Self.ClientWidth - Left;
end;
end;
function TJvTFDays.CheckSBVis: Boolean;
var
NewSBVis: TJvTFVisibleScrollBars;
I, TempWidth, NewDataHeight, NewDataWidth: Integer;
DoColResize: Boolean;
function CalcDataRect(ForScrollBars: TJvTFVisibleScrollBars): TRect;
begin
Result := GetClientRect;
{$IFDEF Jv_TIMEBLOCKS}
// ok
Inc(Result.Left, CalcBlockRowHdrsWidth);
{$ELSE}
// remove
//Inc(Result.Left, RowHdrWidth);
{$ENDIF Jv_TIMEBLOCKS}
//group Inc(Result.Top, ColHdrHeight);
Inc(Result.Top, CalcGroupColHdrsHeight);
if vsbHorz in ForScrollBars then
Dec(Result.Bottom, FHScrollBar.Height);
if vsbVert in ForScrollBars then
Dec(Result.Right, FVScrollBar.Width);
end;
function CalcDataWidth(ForScrollBars: TJvTFVisibleScrollBars): Integer;
begin
Result := RectWidth(CalcDataRect(ForScrollBars));
end;
function CalcDataHeight(ForScrollBars: TJvTFVisibleScrollBars): Integer;
begin
Result := RectHeight(CalcDataRect(ForScrollBars));
end;
begin
NewSBVis := [];
// First check vert scroll bar, assuming horz is not needed
NewDataHeight := CalcDataHeight(NewSBVis);
if (RowCount * RowHeight > NewDataHeight) or (TopRow > 0) then
Include(NewSBVis, vsbVert);
if Cols.Count > 0 then
begin
// Now check the horz scroll under the new conditions
NewDataWidth := CalcDataWidth(NewSBVis);
if AutoSizeCols then
begin
if (Cols.Count * MinColWidth > NewDataWidth) or (LeftCol > 0) then
Include(NewSBVis, vsbHorz);
end
else
begin
TempWidth := 0;
I := 0;
while (TempWidth <= NewDataWidth) and (I < Cols.Count) do
begin
Inc(TempWidth, Cols[I].Width);
Inc(I);
end;
if (TempWidth > NewDataWidth) or (LeftCol > 0) then
Include(NewSBVis, vsbHorz);
end;
end;
// if the horz scrollbar should show, we must recheck the vert scrollbar,
// since the vert scrollbar was initially checked with the assumption
// that the horz scrollbar was not needed.
if vsbHorz in NewSBVis then
begin
NewDataHeight := CalcDataHeight(NewSBVis);
if (RowCount * RowHeight > NewDataHeight) or (TopRow > 0) then
Include(NewSBVis, vsbVert);
end;
// if we're autosizing the cols and the vert scrollbar has been
// toggled and the horz scroll isn't visible then we need to resize
// the cols. We can't call Cols.Resize until VisibleScrollBars has
// been updated so just set a flag here.
DoColResize := AutoSizeCols and not (vsbHorz in NewSBVis) and
((vsbVert in NewSBVis) xor (vsbVert in VisibleScrollBars));
// At this point NewSBVis will correctly reflect which scrollbars need to
// visible on the control.
VisibleScrollBars := NewSBVis;
// In order to optimize the resizing of cols when AutoSizeCols is on, this
// function needs a return value specifying whether or not the cols have
// been resized from within this routine. if we're not autosizing cols
// it'll return false, but the result is meaningless.
Result := DoColResize;
// Finally, resize the cols if necessary
if DoColResize then
Cols.ResizeCols;
CheckSBParams;
end;
procedure TJvTFDays.SetOnShowHint(Value: TJvTFShowHintEvent);
begin
FHint.OnShowHint := Value;
end;
function TJvTFDays.GetOnShowHint: TJvTFShowHintEvent;
begin
Result := FHint.OnShowHint;
end;
procedure TJvTFDays.SetGranularity(Value: Integer);
var
ATime: TTime;
MaxRowHeight, I: Integer;
begin
if Assigned(FOnGranularityChanging) then
FOnGranularityChanging(Self, Value);
// Enforce minimum granularity of 1 min and max of 60 mins
if Value < 1 then
Value := 1
else
if Value > 60 then
Value := 60;
// Ensure that granularity is evenly divisable by an hour
while 60 mod Value <> 0 do
Dec(Value);
// Sum of row heights cannot exceed 32767
MaxRowHeight := 32767 div (60 div Value * 24);
if RowHeight > MaxRowHeight then
RowHeight := MaxRowHeight;
if Value <> FGranularity then
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
EnsureBlockRules(Value, TimeBlockProps.BlockGran, TimeBlockProps.DayStart);
{$ENDIF Jv_TIMEBLOCKS}
ATime := RowToTime(TopRow);
FGranularity := Value;
ClearSelection;
if not (csLoading in ComponentState) then
begin
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
TopRow := TimeToRow(ATime);
CheckSBVis;
CheckSBParams;
Invalidate;
if Assigned(FOnGranularityChanged) then
FOnGranularityChanged(Self);
end;
end;
end;
procedure TJvTFDays.SetColHdrHeight(Value: Integer);
begin
if Value > RectHeight(GetAdjClientRect) then
Value := RectHeight(GetAdjClientRect);
if Value < 1 then
Value := 1;
if Value <> ColHdrHeight then
begin
FColHdrHeight := Value;
AlignScrollBars;
if not (csLoading in ComponentState) then
begin
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
end;
function TJvTFDays.IsStoredColHdrHeight: Boolean;
begin
Result := FColHdrHeight <> Scale96ToFont(DEFAULT_COL_HDR_HEIGHT);
end;
procedure TJvTFDays.SetRowHdrWidth(Value: Integer);
begin
if Value > RectWidth(GetAdjClientRect) then
Value := RectWidth(GetAdjClientRect);
if Value < 1 then
Value := 1;
if Value <> FRowHdrWidth then
begin
FRowHdrWidth := Value;
AlignScrollBars;
if AutoSizeCols then
begin
if not CheckSBVis then
if not (vsbHorz in VisibleScrollBars) then
Cols.ResizeCols;
end
else
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
function TJvTFDays.IsStoredRowHdrWidth: Boolean;
begin
Result := FRowHdrWidth <> Scale96ToFont(DEFAULT_ROW_HDR_WIDTH);
end;
procedure TJvTFDays.SetRowHeight(Value: Integer);
var
MaxRowHeight: Integer;
begin
if Value > GetDataHeight then
Value := GetDataHeight;
if Value < MinRowHeight then
Value := MinRowHeight;
if Value < 1 then
Value := 1;
// Sum of row heights cannot exceed 32767.
MaxRowHeight := 32767 div (60 div Granularity * 24);
if Value > MaxRowHeight then
Value := MaxRowHeight;
if Value <> FRowHeight then
begin
FRowHeight := Value;
if not (csLoading in ComponentState) then
begin
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
end;
function TJvTFDays.IsStoredRowHeight: Boolean;
begin
Result := FRowHeight <> Scale96ToFont(DEFAULT_ROW_HEIGHT);
end;
procedure TJvTFDays.SetMinRowHeight(Value: Integer);
var
absMinColWidth: Integer;
begin
absMinColWidth := Scale96ToFont(DEFAULT_MIN_COL_WIDTH);
if Value < absMinColWidth then
Value := absMinColWidth;
if Value <> FMinRowHeight then
begin
FMinRowHeight := Value;
if Value > RowHeight then
RowHeight := Value;
end;
end;
function TJvTFDays.IsStoredMinRowHeight: Boolean;
begin
Result := FMinRowHeight <> Scale96ToFont(DEFAULT_MIN_ROW_HEIGHT);
end;
procedure TJvTFDays.SetMinColWidth(Value: Integer);
var
absMinColWidth: Integer;
begin
absMinColWidth := Scale96ToFont(DEFAULT_MIN_COL_WIDTH);
if Value < absMinColWidth then
Value := absMinColWidth;
if Value <> FMinColWidth then
begin
FMinColWidth := Value;
if not (csLoading in ComponentState) then
Cols.EnsureMinColWidth;
end;
end;
function TJvTFDays.IsStoredMinColWidth: Boolean;
begin
Result := FMinColWidth <> Scale96ToFont(DEFAULT_MIN_COL_WIDTH);
end;
function TJvTFDays.IsStoredDefColWidth: Boolean;
begin
Result := FDefColWidth <> Scale96ToFont(DEFAULT_DEF_COL_WIDTH);
end;
procedure TJvTFDays.SetAutoSizeCols(Value: Boolean);
begin
if Value <> FAutoSizeCols then
begin
FAutoSizeCols := Value;
if FAutoSizeCols then
if not CheckSBVis then
Cols.ResizeCols;
end;
end;
procedure TJvTFDays.SetTFColTitleStyle(Value: TJvTFColTitleStyle);
begin
if Value <> FColTitleStyle then
begin
FColTitleStyle := Value;
Invalidate;
end;
end;
procedure TJvTFDays.SetCols(Value: TJvTFDaysCols);
begin
FCols.Assign(Value);
end;
procedure TJvTFDays.SetTopRow(Value: Integer);
var
MaxTopRow: Integer;
begin
MaxTopRow := RowCount - 1;
if MaxTopRow < 0 then
MaxTopRow := 0;
if Value > MaxTopRow then
Value := MaxTopRow;
if Value <> FTopRow then
if (Value > -1) and (Value < RowCount) then
begin
if Editing then
FinishEditAppt;
FTopRow := Value;
FVScrollBar.Position := Value;
CheckSBVis;
Invalidate;
end
else
raise EJvTFDaysError.CreateRes(@RsERowIndexOutOfBounds);
end;
procedure TJvTFDays.SetFocusedRow(Value: Integer);
begin
// ALLOW -1 TO INDICATE NO SELECTED ROW
{$IFDEF Jv_TIMEBLOCKS}
// ok
if (Value <> -1) and (RowToTimeBlock(Value) = -1) and (TimeBlocks.Count > 0) then
Exit;
{$ENDIF Jv_TIMEBLOCKS}
if Value <> FFocusedRow then
if (Value >= -1) and (Value < RowCount) then
begin
FFocusedRow := Value;
if not (csDesigning in ComponentState) then
SetFocus;
if not Assigned(SelAppt) and (Value > -1) then
RowInView(Value);
if Assigned(FOnFocusedRowChanged) then
FOnFocusedRowChanged(Self);
Invalidate;
end
else
raise EJvTFDaysError.CreateRes(@RsERowIndexOutOfBounds);
end;
function TJvTFDays.GetFocusedRow: Integer;
begin
if Focused then
Result := FFocusedRow
else
Result := -1;
end;
procedure TJvTFDays.SetLeftCol(Value: Integer);
begin
// LeftCol will be -1 when no cols are present.
// After the first col is added, LeftCol is set to 0, which is done in
// TJvTFDaysCols.Update. Likewise, when all cols are removed, LeftCol
// must be set to -1. This is also done in TJvTFDaysCols.Update.
if Value <> FLeftCol then
if Cols.Count > 0 then
if (Value > -1) and (Value < Cols.Count) then
begin
FLeftCol := Value;
FHScrollBar.Position := Value;
if not Cols.Updating then
begin
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end
else
raise EJvTFDaysError.CreateRes(@RsEColumnIndexOutOfBounds)
else
if Value = -1 then
begin
FLeftCol := -1;
Invalidate;
end
else
raise EJvTFDaysError.CreateRes(@RsEColumnIndexOutOfBounds);
end;
procedure TJvTFDays.SetFocusedCol(Value: Integer);
begin
// ALLOW -1 TO INDICATE NO SELECTED COL
if Value <> FFocusedCol then
if (Value >= -1) and (Value < Cols.Count) then
begin
FFocusedCol := Value;
if not (csDesigning in ComponentState) then
SetFocus;
if not Cols.Updating then
begin
if Value > -1 then
ColInView(Value);
if Assigned(FOnFocusedColChanged) then
FOnFocusedColChanged(Self);
Invalidate;
end;
end
else
raise EJvTFDaysError.CreateRes(@RsEColumnIndexOutOfBounds);
end;
function TJvTFDays.GetFocusedCol: Integer;
begin
if Focused then
Result := FFocusedCol
else
Result := -1;
end;
procedure TJvTFDays.SetHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FHdrAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetSelHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FSelHdrAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetApptAttr(Value: TJvTFDaysApptAttr);
begin
FApptAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetSelApptAttr(Value: TJvTFDaysApptAttr);
begin
FSelApptAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
begin
FFancyRowHdrAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetSelFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
begin
FSelFancyRowHdrAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetTFRowHdrType(Value: TJvTFRowHdrType);
begin
if Value <> FRowHdrType then
begin
FRowHdrType := Value;
Invalidate;
end;
end;
procedure TJvTFDays.SetTFSelCellAttr(Value: TJvTFSelCellAttr);
begin
FSelCellAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetApptBar(Value: TJvTFDaysApptBar);
begin
FApptBar.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetApptBuffer(Value: Integer);
begin
if Value < 0 then
Value := 0;
if Value <> FApptBuffer then
begin
FApptBuffer := Value;
Invalidate;
end;
end;
procedure TJvTFDays.SetGridLineColor(Value: TColor);
begin
if Value <> FGridLineColor then
begin
FGridLineColor := Value;
Invalidate;
end;
end;
procedure TJvTFDays.SetGrabHandles(Value: TJvTFDaysGrabHandles);
begin
FGrabHandles.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetOptions(Value: TJvTFDaysOptions);
begin
FOptions := Value;
Invalidate;
end;
procedure TJvTFDays.SetDateFormat(const Value: string);
begin
if Value <> FDateFormat then
begin
FDateFormat := Value;
Cols.UpdateTitles;
Invalidate;
end;
end;
procedure TJvTFDays.RelSchedNotification(Schedule: TJvTFSched);
var
I: Integer;
begin
for I := 0 to Cols.Count - 1 do
if Cols[I].Schedule = Schedule then
Cols[I].Disconnect;
inherited RelSchedNotification(Schedule);
end;
procedure TJvTFDays.CreateParams(var Params: TCreateParams);
{
const
BorderStyles: array [TBorderStyle] of DWORD = (0, WS_BORDER);
}
begin
inherited CreateParams(Params);
{
with Params do
begin
Style := Style or BorderStyles[FBorderStyle] or WS_CLIPCHILDREN;
if Ctl3D and (FBorderStyle = bsSingle) then
begin
Style := Style and not WS_BORDER;
ExStyle := ExStyle or WS_EX_CLIENTEDGE;
end;
end;
}
end;
function TJvTFDays.GetFocusedSchedule: TJvTFSched;
begin
Result := nil;
if FocusedCol > gcHdr then
Result := Cols[FocusedCol].Schedule;
end;
procedure TJvTFDays.SetSelAppt(Value: TJvTFAppt);
begin
// need event here with var Appt param - allows handler to set Appt
// to nil.
if Assigned(FOnSelectingAppt) then
FOnSelectingAppt(Self, Value);
if Value <> FSelAppt then
begin
if Editing then
FinishEditAppt;
if Assigned(FOnSelectAppt) then
FOnSelectAppt(Self, FSelAppt, Value);
FSelAppt := Value;
if Assigned(FOnSelectedAppt) then
FOnSelectedAppt(Self);
Invalidate;
end;
end;
procedure TJvTFDays.Paint;
var
I, J, lRightCol, lBottomRow: Integer;
w, h: Integer;
begin
{ optimization incorrectly kicks in if control is only partially
visible on the screen
if not PaintBuffer.Empty and
((Canvas.ClipRect.Left <> ClientRect.Left) or
(Canvas.ClipRect.Top <> ClientRect.Top) or
(Canvas.ClipRect.Right <> ClientRect.Right) or
(Canvas.ClipRect.Bottom <> ClientRect.Bottom)) then
begin
With Canvas do
Windows.BitBlt(Canvas.Handle, ClipRect.Left, ClipRect.Top,
RectWidth(ClipRect), RectHeight(ClipRect),
PaintBuffer.Canvas.Handle,
ClipRect.Left, ClipRect.Top, SRCCOPY);
Exit;
end;
}
w := ClientWidth;
h := ClientHeight;
with PaintBuffer do
begin
SetSize(w, h);
with Canvas do
begin
Pixels[0, 0] := clWhite; // Workaround for Lazarus to avoid black background
if FDitheredBackground then
// added by TIM, 10/27/2001 10:36:03 PM:
DrawDither(Canvas, Classes.Rect(0, 0, w, h), Self.Color, clGray)
else
begin
Brush.Color := Self.Color;
FillRect(Classes.Rect(0, 0, Width, Height));
end;
end;
DrawCorner(Canvas, agcTopLeft);
if Cols.Count = 0 then
DrawEmptyColHdr(Canvas);
DrawGroupHdrs(Canvas);
lRightCol := LeftCol + VisibleCols - 1;
for I := LeftCol to lRightCol do
//DrawColHdr(Canvas, I);
DrawColGroupHdr(Canvas, I, False);
if vsbVert in VisibleScrollBars then
DrawCorner(Canvas, agcTopRight);
{$IFDEF Jv_TIMEBLOCKS}
// all ok
FillBlockHdrDeadSpace(Canvas);
for I := 0 to TimeBlocks.Count - 1 do
DrawBlockHdr(Canvas, I);
{$ENDIF Jv_TIMEBLOCKS}
lBottomRow := TopRow + VisibleRows - 1;
if RowHdrType = rhFancy then
DrawFancyRowHdrs(Canvas)
else
for I := TopRow to lBottomRow do
DrawRowHdr(Canvas, I);
for I := TopRow to lBottomRow do
for J := LeftCol to lRightCol do
DrawDataCell(Canvas, J, I);
if not (csDesigning in ComponentState) then
DrawAppts(Canvas, False);
if vsbHorz in VisibleScrollBars then
begin
DrawCorner(Canvas, agcBottomLeft);
if vsbVert in VisibleScrollBars then
DrawCorner(Canvas, agcBottomRight);
end;
end;
if Enabled then
BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight,
PaintBuffer.Canvas.Handle, 0, 0, SRCCOPY)
else
BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight,
PaintBuffer.Canvas.Handle, 0, 0, SRCCOPY)
{ wp --- to do: Above line is a work-around because LCL does not
support DrawState
Windows.DrawState(Canvas.Handle, 0, nil, PaintBuffer.Handle, 0,
0, 0, 0, 0, DST_BITMAP or DSS_UNION or DSS_DISABLED);
}
end;
{$IFNDEF Jv_TIMEBLOCKS}
// OBSOLETE
{
procedure TJvTFDays.DrawDataCell(ACanvas: TCanvas; ColIndex, RowIndex: Integer);
Var
SelFrameRect,
FocusRect,
ARect: TRect;
I,
PrimeStartRow,
PrimeEndRow,
FrameOffset: Integer;
CellColor: TColor;
IsPrimeTimeCell: Boolean;
begin
// Calc the cell rect
ARect.Left := RowHdrWidth;
For I := LeftCol to ColIndex - 1 do
Inc(ARect.Left, Cols[I].Width);
ARect.Right := ARect.Left + Cols[ColIndex].Width;
//group Top := ColHdrHeight + (RowIndex - TopRow) * RowHeight;
ARect.Top := CalcGroupColHdrsHeight + (RowIndex - TopRow) * RowHeight;
ARect.Bottom := ARect.Top + RowHeight;
PrimeStartRow := TimeToRow(PrimeTime.StartTime);
PrimeEndRow := TimeToRow(AdjustEndTime(PrimeTime.EndTime));
IsPrimeTimeCell := (RowIndex >= PrimeStartRow) and (RowIndex <= PrimeEndRow);
if IsPrimeTimeCell then
CellColor := PrimeTime.Color
else
CellColor := Color;
if Assigned(FOnShadeCell) then
FOnShadeCell(Self, ColIndex, RowIndex, CellColor);
if IsPrimeTimeCell and (CellColor = PrimeTime.Color) then
Windows.StretchBlt(ACanvas.Handle, ARect.Left, ARect.Top, RectWidth(ARect),
RectHeight(ARect), PrimeTime.FFillPic.Canvas.Handle,
0, 0, PrimeTime.FFillPic.Width,
PrimeTime.FFillPic.Height, SRCCOPY)
else
if CellColor <> Color then
begin
ACanvas.Brush.Color := CellColor;
ACanvas.FillRect(ARect);
end;
if CellIsSelected(Point(ColIndex, RowIndex)) then
if SelCellAttr.Style = scsFrame then
begin
SelFrameRect := ARect;
FrameOffset := -(SelCellAttr.FrameWidth div 2);
Windows.InflateRect(SelFrameRect, FrameOffset, FrameOffset);
if SelCellAttr.FrameWidth mod 2 <> 0 then
begin
Dec(SelFrameRect.Right);
Dec(SelFrameRect.Bottom);
end;
With ACanvas do
begin
Pen.Color := SelCellAttr.Color;
Pen.Width := SelCellAttr.FrameWidth;
if FFromToSel then
begin
// Draw Left border
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
// Draw Top border only if this cell is the same as SelStart cell
if (ColIndex = SelStart.X) and (RowIndex = SelStart.Y) then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
end;
// Draw Right border
MoveTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
// Draw bottom border only in this cell is the same as SelEnd cell
if (ColIndex = SelEnd.X) and (RowIndex = SelEnd.Y) then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
end
else
begin
// Draw Left border only if col is left-most in selection
if ColIndex = SelStart.X then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
end;
// Draw Top border only if row is top-most in selection
if RowIndex = SelStart.Y then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
end;
// Draw Right border only if col is right-most in selection
if ColIndex = SelEnd.X then
begin
MoveTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
// Draw Bottom border only if row is bottom-most in selection
if RowIndex = SelEnd.Y then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
end;
end;
end
// Refer to the private FSel* fields because we want anchor
else
if (SelCellAttr.Style = scsCombo) and
(FSelStart.X = ColIndex) and (FSelStart.Y = RowIndex) then
begin
SelFrameRect := ARect;
FrameOffset := -(SelCellAttr.FrameWidth div 2);
Windows.InflateRect(SelFrameRect, FrameOffset, FrameOffset);
if SelCellAttr.FrameWidth mod 2 <> 0 then
begin
Dec(SelFrameRect.Right);
Dec(SelFrameRect.Bottom);
end;
With ACanvas do
begin
Pen.Color := SelCellAttr.Color;
Pen.Width := SelCellAttr.FrameWidth;
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Left, SelFrameRect.Top);
end;
end
else
begin
ACanvas.Brush.Color := SelCellAttr.Color;
ACanvas.FillRect(ARect);
end;
if (ColIndex = FocusedCol) and (RowIndex = FocusedRow) and Focused then
begin
FocusRect := ARect;
Windows.InflateRect(FocusRect, -1, -1);
Dec(FocusRect.Bottom);
Dec(FocusRect.Right);
ManualFocusRect(ACanvas, FocusRect);
end;
// Draw a line across the bottom and down the right side
With ACanvas do
begin
Pen.Color := GridLineColor;
Pen.Width := 1;
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
end;
if Assigned(FOnDrawDataCell) then
FOnDrawDataCell(Self, ACanvas, ARect, ColIndex, RowIndex);
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDays.DrawDataCell(ACanvas: TCanvas; ColIndex, RowIndex: Integer);
var
BlockStart: Integer = -1; // to silence the compiler
BlockEnd: Integer = -1; // dto.
SelFrameRect, FocusRect, Rect: TRect;
I, PrimeStartRow, PrimeEndRow: Integer;
FrameOffset, TimeBlockIndex: Integer;
IsPrimeTimeCell: Boolean;
CellColor: TColor;
// col buffer start
BufferRect: TRect;
// col buffer end
begin
// Calc the cell rect
//block Left := RowHdrWidth;
Rect.Left := CalcBlockRowHdrsWidth;
for I := LeftCol to ColIndex - 1 do
Inc(Rect.Left, Cols[I].Width);
Rect.Right := Rect.Left + Cols[ColIndex].Width;
//group Top := ColHdrHeight + (RowIndex - TopRow) * RowHeight;
Rect.Top := CalcGroupColHdrsHeight + (RowIndex - TopRow) * RowHeight;
Rect.Bottom := Rect.Top + RowHeight;
PrimeStartRow := TimeToRow(PrimeTime.StartTime);
PrimeEndRow := TimeToRow(AdjustEndTime(PrimeTime.EndTime));
IsPrimeTimeCell := (RowIndex >= PrimeStartRow) and (RowIndex <= PrimeEndRow);
if IsWeekend(ColIndex) then
CellColor := WeekendColor
else
if IsPrimeTimeCell then
CellColor := PrimeTime.Color
else
CellColor := Color;
if Assigned(FOnShadeCell) then
FOnShadeCell(Self, ColIndex, RowIndex, CellColor);
if IsWeekend(ColIndex) and (CellColor = WeekendColor) then
begin
if FDitheredBackground then
DrawDither(ACanvas, Rect, CellColor, clWhite)
else
StretchBlt(ACanvas.Handle, Rect.Left, Rect.Top, RectWidth(Rect),
RectHeight(Rect), FWeekendFillPic.Canvas.Handle,
0, 0, FWeekendFillPic.Width,
FWeekendFillPic.Height, SRCCOPY);
end
else
if IsPrimeTimeCell and (CellColor = PrimeTime.Color) then
begin
if FDitheredBackground then
DrawDither(ACanvas, Rect, CellColor, clWhite)
else
StretchBlt(ACanvas.Handle, Rect.Left, Rect.Top, RectWidth(Rect),
RectHeight(Rect), PrimeTime.FFillPic.Canvas.Handle,
0, 0, PrimeTime.FFillPic.Width,
PrimeTime.FFillPic.Height, SRCCOPY);
end
else
if CellColor <> Color then
begin
ACanvas.Brush.Color := CellColor;
ACanvas.FillRect(Rect);
end
else
begin
if FDitheredBackground then
DrawDither(ACanvas, Rect, CellColor, clWhite);
end;
{
if IsWeekend(ColIndex) then
Windows.StretchBlt(ACanvas.Handle, ARect.Left, ARect.Top, RectWidth(ARect),
RectHeight(ARect), FWeekendFillPic.Canvas.Handle,
0, 0, FWeekendFillPic.Width,
FWeekendFillPic.Height, SRCCOPY)
else
if (RowIndex >= PrimeStartRow) and (RowIndex <= PrimeEndRow) then
Windows.StretchBlt(ACanvas.Handle, ARect.Left, ARect.Top, RectWidth(ARect),
RectHeight(ARect), PrimeTime.FFillPic.Canvas.Handle,
0, 0, PrimeTime.FFillPic.Width,
PrimeTime.FFillPic.Height, SRCCOPY);
}
if CellIsSelected(Point(ColIndex, RowIndex)) then
if SelCellAttr.Style = scsFrame then
begin
SelFrameRect := Rect;
FrameOffset := -(SelCellAttr.FrameWidth div 2);
InflateRect(SelFrameRect, FrameOffset, FrameOffset);
if SelCellAttr.FrameWidth mod 2 <> 0 then
begin
Dec(SelFrameRect.Right);
Dec(SelFrameRect.Bottom);
end;
with ACanvas do
begin
Pen.Color := SelCellAttr.Color;
Pen.Width := SelCellAttr.FrameWidth;
if FFromToSel then
begin
// Draw Left border
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
// Draw Top border only if this cell is the same as SelStart cell
if (ColIndex = SelStart.X) and (RowIndex = SelStart.Y) then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
end;
// Draw Right border
MoveTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
// Draw bottom border only in this cell is the same as SelEnd cell
if (ColIndex = SelEnd.X) and (RowIndex = SelEnd.Y) then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
end
else
begin
// Draw Left border only if col is left-most in selection
if ColIndex = SelStart.X then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
end;
// Draw Top border only if row is top-most in selection
if RowIndex = SelStart.Y then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
end;
// Draw Right border only if col is right-most in selection
if ColIndex = SelEnd.X then
begin
MoveTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
// Draw Bottom border only if row is bottom-most in selection
if RowIndex = SelEnd.Y then
begin
MoveTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
end;
end;
end;
end
// Refer to the private FSel* fields because we want anchor
else
if (SelCellAttr.Style = scsCombo) and
(FSelStart.X = ColIndex) and (FSelStart.Y = RowIndex) then
begin
SelFrameRect := Rect;
FrameOffset := -(SelCellAttr.FrameWidth div 2);
InflateRect(SelFrameRect, FrameOffset, FrameOffset);
if SelCellAttr.FrameWidth mod 2 <> 0 then
begin
Dec(SelFrameRect.Right);
Dec(SelFrameRect.Bottom);
end;
with ACanvas do
begin
Pen.Color := SelCellAttr.Color;
Pen.Width := SelCellAttr.FrameWidth;
MoveTo(SelFrameRect.Left, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Top);
LineTo(SelFrameRect.Right - 1, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Left, SelFrameRect.Bottom - 1);
LineTo(SelFrameRect.Left, SelFrameRect.Top);
end;
end
else
begin
ACanvas.Brush.Color := SelCellAttr.Color;
ACanvas.FillRect(Rect);
end;
if (ColIndex = FocusedCol) and (RowIndex = FocusedRow) and Focused and ShowFocus then
begin
FocusRect := Rect;
InflateRect(FocusRect, -1, -1);
Dec(FocusRect.Bottom);
Dec(FocusRect.Right);
ManualFocusRect(ACanvas, FocusRect);
end;
// Draw a line across the bottom and down the right side
with ACanvas do
begin
Pen.Color := GridLineColor;
Pen.Width := 1;
MoveTo(Rect.Left, Rect.Bottom - 1);
LineTo(Rect.Right, Rect.Bottom - 1);
MoveTo(Rect.Right - 1, Rect.Top);
LineTo(Rect.Right - 1, Rect.Bottom);
if TimeBlocks.Count > 0 then
begin
GetTimeBlockStartEnd(0, BlockStart, BlockEnd);
if RowIndex = BlockStart - 1 then
begin
Pen.Color := TimeBlockProps.DataDivColor;
MoveTo(Rect.Left, Rect.Bottom - 1);
LineTo(Rect.Right, Rect.Bottom - 1);
end;
TimeBlockIndex := RowToTimeBlock(RowIndex);
if TimeBlockIndex > -1 then
begin
GetTimeBlockStartEnd(TimeBlockIndex, BlockStart, BlockEnd);
if BlockEnd = RowIndex then
begin
Pen.Color := TimeBlockProps.DataDivColor;
MoveTo(Rect.Left, Rect.Bottom - 1);
LineTo(Rect.Right, Rect.Bottom - 1);
end;
end;
end;
end;
// Col Buffer start
// Draw the column buffer
with ACanvas do
begin
BufferRect := Rect;
BufferRect.Right := BufferRect.Left + ApptBar.Width; // + 10 to simulate buffer
Brush.Color := clWhite;
FillRect(BufferRect);
Pen.Color := clBlack;
Pen.Width := 1;
MoveTo(BufferRect.Right, BufferRect.Top);
LineTo(BufferRect.Right, BufferRect.Bottom);
end;
// Col buffer end
if Assigned(FOnDrawDataCell) then
FOnDrawDataCell(Self, ACanvas, Rect, ColIndex, RowIndex);
end;
{$ENDIF Jv_TIMEBLOCKS}
procedure TJvTFDays.DrawEmptyColHdr(ACanvas: TCanvas);
var
Rect: TRect;
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
Rect.Left := CalcBlockRowHdrsWidth;
{$ELSE}
// remove
//Left := RowHdrWidth;
{$ENDIF Jv_TIMEBLOCKS}
Rect.Top := 0;
Rect.Right := Rect.Left + GetDataWidth;
//group Bottom := ColHdrHeight;
Rect.Bottom := CalcGroupColHdrsHeight;
ACanvas.Brush.Color := HdrAttr.Color;
ACanvas.FillRect(Rect);
ACanvas.Pen.Color := clGray;
ACanvas.MoveTo(Rect.Left, Rect.Bottom - 1);
ACanvas.LineTo(Rect.Right, Rect.Bottom - 1);
end;
procedure TJvTFDays.DrawAppt(ACanvas: TCanvas; Col: Integer;
Appt: TJvTFAppt; StartRow, EndRow: Integer);
var
ApptRect: TRect;
ClipRgn: HRgn;
begin
ApptRect := GetApptRect(Col, Appt);
if IsRectEmpty(ApptRect) then
Exit;
// Printer bug, fixed
ClipRgn := CreateRectRgn(RowHdrWidth, CalcGroupColHdrsHeight,
ClientWidth, ClientHeight);
SelectClipRgn(ACanvas.Handle, ClipRgn);
DrawApptDetail(ACanvas, ApptRect, Appt, Appt = SelAppt, Col, StartRow, EndRow);
SelectClipRgn(ACanvas.Handle, 0);
DeleteObject(ClipRgn);
end;
function TJvTFDays.CalcTimeStampRect(Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer): TRect;
var
Offset, ApptLength: TTime;
ColDate: TDate;
StartPercent, EndPercent: Double;
begin
Result := BarRect;
if StartRow < 0 then
StartRow := 0;
if EndRow > RowCount - 1 then
EndRow := RowCount - 1;
Offset := RowToTime(StartRow);
ApptLength := RowEndTime(EndRow) - Offset;
ColDate := Cols[Col].SchedDate;
if Trunc(ColDate) <> Trunc(Appt.StartDate) then
StartPercent := 0
else
StartPercent := (Appt.StartTime - Offset) / ApptLength;
if Trunc(ColDate) <> Trunc(Appt.EndDate) then
EndPercent := 1.0
else
EndPercent := (Appt.EndTime - Offset) / ApptLength;
Result.Top := Round((BarRect.Bottom - BarRect.Top) * StartPercent) + BarRect.Top;
Result.Bottom := Round((BarRect.Bottom - BarRect.Top) * EndPercent) + BarRect.Top;
end;
procedure TJvTFDays.DrawTimeStamp(ACanvas: TCanvas; TimeStampRect: TRect);
var
OldColor: TColor;
StampLeft: Integer;
begin
with ACanvas do
case ApptBar.TimeStampStyle of
tssFullI:
begin
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
MoveTo(TimeStampRect.Left + 1, TimeStampRect.Top);
LineTo(TimeStampRect.Right - 1, TimeStampRect.Top);
MoveTo(TimeStampRect.Left + 1, TimeStampRect.Bottom - 1);
LineTo(TimeStampRect.Right - 1, TimeStampRect.Bottom - 1);
if ApptBar.Width > 5 then
Pen.Width := 2
else
Pen.Width := 1;
// Printer bug, fixed
StampLeft := TimeStampRect.Left + RectWidth(TimeStampRect) div 2;
MoveTo(StampLeft, TimeStampRect.Top + 1);
LineTo(StampLeft, TimeStampRect.Bottom - 1);
Pen.Width := 1;
Pen.Color := OldColor;
end;
tssHalfI:
begin
// we only want the left half of the time stamp rect
TimeStampRect.Right := (TimeStampRect.Left + TimeStampRect.Right) div 2;
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
MoveTo(TimeStampRect.Left, TimeStampRect.Top);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Top);
MoveTo(TimeStampRect.Left, TimeStampRect.Bottom - 0);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Bottom - 0);
if ApptBar.Width > 5 then
Pen.Width := 2
else
Pen.Width := 1;
MoveTo(TimeStampRect.Right - 0, TimeStampRect.Top + 1);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Bottom);
Pen.Color := OldColor;
Pen.Width := 1;
end;
tssBlock:
begin
// we only want the left half of the time stamp rect
TimeStampRect.Right := (TimeStampRect.Left + TimeStampRect.Right) div 2;
OldColor := Brush.Color;
Brush.Color := ApptBar.TimeStampColor;
FillRect(TimeStampRect);
Brush.Color := OldColor;
end;
end;
end;
procedure TJvTFDays.DrawApptBar(ACanvas: TCanvas; Appt: TJvTFAppt;
BarRect: TRect; Col, StartRow, EndRow: Integer);
var
OldColor: TColor;
TimeStampRect: TRect;
Attr: TJvTFDaysApptAttr;
begin
with ACanvas do
begin
if Appt <> SelAppt then
Attr := ApptAttr
else
Attr := SelApptAttr;
// Fill Bar Color
OldColor := Brush.Color;
if Appt.BarColor = clDefault then
Brush.Color := ApptBar.Color
else
Brush.Color := Appt.BarColor;
FillRect(BarRect);
// Draw Bar Border
Pen.Width := 1;
Pen.Color := Attr.FrameColor;
MoveTo(BarRect.Right - 1, BarRect.Top);
LineTo(BarRect.Right - 1, BarRect.Bottom);
// Rectangle(BarRect);
Brush.Color := OldColor;
// Draw Time Stamp
TimeStampRect := CalcTimeStampRect(Appt, BarRect, Col, StartRow, EndRow);
if ApptBar.TimeStampStyle <> tssNone then
DrawTimeStamp(ACanvas, TimeStampRect);
if Assigned(FOnDrawApptBar) then
FOnDrawApptBar(Self, ACanvas, Appt, Col, BarRect, TimeStampRect);
end;
end;
procedure TJvTFDays.DrawApptDetail(ACanvas: TCanvas; ARect: TRect;
Appt: TJvTFAppt; Selected: Boolean; Col, StartRow, EndRow: Integer);
var
TheFrameRect, TxtRect, DetailRect, BarRect, HandleRect: TRect;
Txt: string;
Flags: UINT;
CanDrawText, CanDrawPics, CanDrawAppt: Boolean;
PicsHeight, PicsWidth: Integer;
DrawList: TList;
Attr: TJvTFDaysApptAttr;
DrawInfo: TJvTFDaysApptDrawInfo;
begin
with ACanvas do
begin
if Appt <> SelAppt then
Attr := ApptAttr
else
Attr := SelApptAttr;
DrawInfo := TJvTFDaysApptDrawInfo.Create;
try
GetApptDrawInfo(DrawInfo, Appt, Attr);
Font.Assign(DrawInfo.Font);
Brush.Color := DrawInfo.Color;
Pen.Color := DrawInfo.FrameColor;
Pen.Width := DrawInfo.FrameWidth;
CanDrawAppt := DrawInfo.Visible;
finally
DrawInfo.Free;
end;
// !!!!!!!!!!!!!!!!!!!!!!!!!!
// EXIT IF NOTHING TO DRAW !!
// !!!!!!!!!!!!!!!!!!!!!!!!!!
if not CanDrawAppt then
Exit;
FillRect(ARect);
TheFrameRect := ARect;
InflateRect(TheFrameRect, -(Attr.FrameWidth div 2), -(Attr.FrameWidth div 2));
// Need to fine tune the frame rect
if Attr.FrameWidth mod 2 = 0 then
begin
Inc(TheFrameRect.Right);
Inc(TheFrameRect.Bottom);
end;
MoveTo(TheFrameRect.Left, TheFrameRect.Top);
LineTo(TheFrameRect.Right - 1, TheFrameRect.Top);
LineTo(TheFrameRect.Right - 1, TheFrameRect.Bottom - 1);
LineTo(TheFrameRect.Left, TheFrameRect.Bottom - 1);
LineTo(TheFrameRect.Left, TheFrameRect.Top);
// Only go through the following work if all details must be drawn
// if (RectHeight(ARect) > Thresholds.DetailHeight) and
// (RectWidth(ARect) > Thresholds.DetailWidth) then
begin
InflateRect(TheFrameRect, -(Attr.FrameWidth div 2), -(Attr.FrameWidth div 2));
DetailRect := TheFrameRect;
if ApptBar.Visible then
begin
Inc(DetailRect.Left, ApptBar.Width);
SubtractRect(BarRect, TheFrameRect, DetailRect);
Dec(BarRect.Bottom);
DrawApptBar(ACanvas, Appt, BarRect, Col, StartRow, EndRow);
end;
TxtRect := DetailRect;
AdjustForMargins(TxtRect);
DrawList := TList.Create;
try
CreatePicDrawList(TxtRect, Appt, DrawList);
FilterPicDrawList(TxtRect, DrawList, PicsHeight, PicsWidth);
// Calc'ing text height and width in CanDrawWhat
CanDrawWhat(ACanvas, TxtRect, PicsHeight, CanDrawText, CanDrawPics);
if CanDrawPics then
begin
DrawListPics(ACanvas, TxtRect, DrawList);
Inc(TxtRect.Left, PicsWidth); // Tim
end;
finally
ClearPicDrawList(DrawList);
DrawList.Free;
end;
if CanDrawText then
begin
Flags := DT_WORDBREAK or DT_NOPREFIX or DT_EDITCONTROL;
Txt := ScheduleManager.GetApptDisplayText(Self, Appt);
if not (agoFormattedDesc in Options) then
begin
Txt := StripCRLF(Txt);
Flags := Flags or DT_END_ELLIPSIS;
end;
//PTxt := StrNew(PChar(Txt));
DrawText(ACanvas.Handle, PChar(Txt), -1, TxtRect, Flags);
end;
end;
if Assigned(FOnDrawAppt) then
FOnDrawAppt(Self, ACanvas, ARect, Appt, Selected);
if Selected then
begin
{ OLD 3D HANDLES CODE
if agoMoveAppt in Options then
DrawGrabLines(ACanvas, ARect.Top + 0, ARect.Left + 2,
ARect.Right - 3);
if agoSizeAppt in Options then
DrawGrabLines(ACanvas, ARect.Bottom - GrabHandles.Height,
ARect.Left + 2, ARect.Right - 3);
}
// move grab handles
if agoMoveAppt in Options then
begin
// HandleRect := Classes.Rect(ARect.Left + 2, ARect.Top, ARect.Right - 3,
// ARect.Top + GrabHandles.Height);
// DrawGrabHandle(ACanvas, HandleRect, Appt, True);
HandleRect := GetTopGrabHandleRect(Col, Appt);
DrawGrabHandle(ACanvas, HandleRect, Appt, True);
end;
if agoSizeAppt in Options then
begin
// HandleRect := Classes.Rect(ARect.Left + 2,
// ARect.Bottom - GrabHandles.Height,
// ARect.Right - 3, ARect.Bottom);
// DrawGrabHandle(ACanvas, HandleRect, Appt, False);
HandleRect := GetBottomGrabHandleRect(Col, Appt);
DrawGrabHandle(ACanvas, HandleRect, Appt, False);
end;
end;
end;
end;
procedure TJvTFDays.DrawPics(ACanvas: TCanvas; var ARect: TRect; Appt: TJvTFAppt);
var
I, PicAdjust, NextPicLeft, CustomPicLeft, ImageIndex: Integer;
ImageList: TCustomImageList;
ImageMap: TJvTFStateImageMap;
CustomImageMap: TJvTFCustomImageMap;
w, h, d: Integer;
{$IF LCL_FullVersion >= 2000000}
PPI: Integer;
f: Double;
{$ENDIF}
begin
PicAdjust := 0;
NextPicLeft := ARect.Left;
{$IF LCL_FullVersion >= 1080000}
d := Scale96ToForm(PIC_DIST);
{$ELSE}
d := ScaleX(PIC_DIST, Screen.PixelsPerInch);
{$ENDIF}
if (agoShowPics in Options) and Assigned(ScheduleManager.CustomImages) then
begin
ImageList := ScheduleManager.CustomImages;
CustomImageMap := Appt.ImageMap;
{$IF LCL_FullVersion >= 2000000}
PPI := Font.PixelsPerInch;
f := GetCanvasScaleFactor;
w := Imagelist.WidthForPPI[ImageList.Width, PPI];
h := round(ImageList.Height/ImageList.Width * w);
{$ELSE}
w := ImageList.Width;
h := ImageList.Height;
{$IFEND}
for I := 0 to CustomImageMap.Count - 1 do
begin
ImageIndex := CustomImageMap[I];
{$IF LCL_FullVersion >= 2000000}
ImageList.DrawForPPI(ACanvas, NextPicLeft, ARect.Top, ImageIndex, 0, PPI, f);
{$ELSE}
ImageList.Draw(ACanvas, NextPicLeft, ARect.Top, ImageIndex);
{$IFEND}
Inc(NextPicLeft, w + d);
end;
if CustomImageMap.Count > 0 then
PicAdjust := h + d;
end;
CustomPicLeft := NextPicLeft;
if (agoShowPics in Options) and Assigned(ScheduleManager.StateImages) then
begin
ImageList := ScheduleManager.StateImages;
ImageMap := ScheduleManager.StateImageMap;
{$IF LCL_FullVersion >= 2000000}
PPI := Font.PixelsPerInch;
f := GetCanvasScaleFactor;
w := Imagelist.WidthForPPI[ImageList.Width, PPI];
h := round(ImageList.Height/ImageList.Width * w);
{$ELSE}
w := ImageList.Width;
h := ImageList.Height;
{$IFEND}
if Appt.AlarmEnabled then
ImageIndex := ImageMap.AlarmEnabled
else
ImageIndex := ImageMap.AlarmDisabled;
if ImageIndex > -1 then begin
{$IF LCL_FullVersion >= 2000000}
ImageList.DrawForPPI(ACanvas, NextPicLeft, ARect.Top, ImageIndex, 0, PPI, f);
{$ELSE}
ImageList.Draw(ACanvas, NextPicLeft, ARect.Top, ImageIndex);
{$IFEND}
Inc(NextPicLeft, w + d);
end;
ImageIndex := ImageMap.Shared;
if Appt.Shared and (ImageIndex > -1) then
begin
{$IF LCL_FullVersion >= 2000000}
ImageList.DrawForPPI(ACanvas, NextPicLeft, ARect.Top, ImageIndex, 0, PPI, f);
{$ELSE}
ImageList.Draw(ACanvas, NextPicLeft, ARect.Top, ImageIndex);
{$IFEND}
Inc(NextPicLeft, w + d);
end;
if Appt.Modified and (ImageMap.Modified > -1) then
begin
{$IF LCL_FullVersion >= 2000000}
ImageList.DrawForPPI(ACanvas, NextPicLeft, ARect.Top, ImageMap.Modified, 0, PPI, f);
{$ELSE}
ImageList.Draw(ACanvas, NextPicLeft, ARect.Top, ImageMap.Modified);
{$IFEND}
Inc(NextPicLeft, w + d);
end;
if (NextPicLeft <> CustomPicLeft) and (h + d > PicAdjust) then
PicAdjust := h + d;
end;
Inc(ARect.Top, PicAdjust);
end;
procedure TJvTFDays.CreatePicDrawList(ARect: TRect; Appt: TJvTFAppt;
DrawList: TList);
var
I, NextPicLeft, ImageIndex: Integer;
ImageList: TCustomImageList;
ImageMap: TJvTFStateImageMap;
CustomImageMap: TJvTFCustomImageMap;
//h,
w, d: Integer;
{$IF LCL_FullVersion >= 2000000}
PPI: integer;
//f: Double;
{$IFEND}
procedure AddToList(AImageList: TCustomImageList; AImageIndex: Integer;
AGlyph: TGraphic; APicLeft, APicTop: Integer);
var
DrawInfo: TJvTFDrawPicInfo;
begin
DrawInfo := TJvTFDrawPicInfo.Create;
DrawInfo.ImageList := AImageList;
DrawInfo.ImageIndex := AImageIndex;
DrawInfo.Glyph := AGlyph;
DrawInfo.PicLeft := APicLeft;
DrawInfo.PicTop := APicTop;
DrawList.Add(DrawInfo);
end;
begin
{$IF LCL_FullVersion >= 1080000}
d := Scale96ToForm(PIC_DIST);
{$ELSE}
d := ScaleX(PIC_DIST, Screen.PixelsPerInch);
{$ENDIF}
NextPicLeft := ARect.Left;
if (agoShowPics in Options) and Assigned(Appt.Glyph.Graphic) and not Appt.Glyph.Graphic.Empty then
begin
AddToList(nil, -1, Appt.Glyph.Graphic, NextPicLeft, ARect.Top);
Inc(NextPicLeft, Appt.Glyph.Graphic.Width + d);
end;
if (agoShowPics in Options) and Assigned(ScheduleManager.CustomImages) then
begin
ImageList := ScheduleManager.CustomImages;
CustomImageMap := Appt.ImageMap;
{$IF LCL_FullVersion >= 2000000}
PPI := Font.PixelsPerInch;
w := Imagelist.WidthForPPI[ImageList.Width, PPI];
//h := round(ImageList.Height/ImageList.Width * w);
//f := GetCanvasScaleFactor;
{$ELSE}
w := ImageList.Width;
//h := ImageList.Height;
{$IFEND}
for I := 0 to CustomImageMap.Count - 1 do
begin
ImageIndex := CustomImageMap[I];
AddToList(ImageList, ImageIndex, nil, NextPicLeft, ARect.Top);
Inc(NextPicLeft, w + d);
end;
end;
if (agoShowPics in Options) and Assigned(ScheduleManager.StateImages) then
begin
ImageList := ScheduleManager.StateImages;
ImageMap := ScheduleManager.StateImageMap;
if Appt.AlarmEnabled then
begin
ImageIndex := ImageMap.AlarmEnabled;
if ImageIndex > -1 then
begin
AddToList(ImageList, ImageIndex, nil, NextPicLeft, ARect.Top);
Inc(NextPicLeft, w + d);
end
end
else
begin
ImageIndex := ImageMap.AlarmDisabled;
if ImageIndex > -1 then
begin
AddToList(ImageList, ImageIndex, nil, NextPicLeft, ARect.Top);
Inc(NextPicLeft, w + d);
end;
end;
ImageIndex := ImageMap.Shared;
if Appt.Shared and (ImageIndex > -1) then
begin
AddToList(ImageList, ImageIndex, nil, NextPicLeft, ARect.Top);
Inc(NextPicLeft, w + 2);
end;
if Appt.Modified and (ImageMap.Modified > -1) then
begin
AddToList(ImageList, ImageMap.Modified, nil, NextPicLeft, ARect.Top);
// The following line generates a compiler hint so comment out,
// but leave here as reminder in case method is expanded.
//Inc(NextPicLeft, ImageList.Width + 2);
end;
end;
end;
procedure TJvTFDays.FilterPicDrawList(ARect: TRect; DrawList: TList;
out PicsHeight, PicsWidth: Integer);
var
I, NextPicLeft: Integer;
DrawIt: Boolean;
DrawInfo: TJvTFDrawPicInfo;
d: Integer;
w, h: Integer;
{$IF LCL_FullVersion >=2000000}
PPI: Integer;
//f: Double;
{$IFEND}
begin
PicsHeight := 0;
PicsWidth := 0;
if DrawList.Count = 0 then
Exit;
{$IF LCL_FullVersion >= 2000000}
PPI := Font.PixelsPerInch;
//f := GetCanvasScaleFactor;
{$IFEND}
{$IF LCL_FullVersion >= 1080000}
d := Scale96ToForm(PIC_DIST);
{$ELSE}
d := ScaleX(PIC_DIST, Screen.PixelsPerInch);
{$ENDIF}
if Thresholds.PicsAllOrNone then
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[DrawList.Count - 1]);
if Assigned(DrawInfo.ImageList) then begin
{$IF LCL_FullVersion >= 2000000}
w := DrawInfo.Imagelist.WidthForPPI[DrawInfo.ImageList.Width, PPI];
h := round(DrawInfo.ImageList.Height/DrawInfo.ImageList.Width * w);
{$ELSE}
w := DrawInfo.ImageList.Width;
h := DrawInfo.ImageList.Height;
{$IFEND}
end;
if DrawInfo.PicLeft + w >= ARect.Right then
begin
while DrawList.Count > 0 do
begin
TJvTFDrawPicInfo(DrawList[0]).Free;
DrawList.Delete(0);
end;
end;
end;
NextPicLeft := ARect.Left;
I := 0;
while I < DrawList.Count do
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[I]);
with DrawInfo do
begin
DrawIt := True;
// if Thresholds.WholePicsOnly and
// ((PicLeft + ImageList.Width >= ARect.Right) or
// (PicTop + ImageList.Height >= ARect.Bottom)) then
// DrawIt := False;
if DrawIt then
begin
if Assigned(ImageList) then begin
{$IF LCL_FullVersion >= 2000000}
w := Imagelist.WidthForPPI[ImageList.Width, PPI];
h := round(ImageList.Height/ImageList.Width * w);
{$ELSE}
w := ImageList.Width;
h := ImageList.Height;
{$IFEND}
PicsHeight := Greater(PicsHeight, h + d);
end else
PicsHeight := Greater(PicsHeight, Glyph.Height + d);
PicLeft := NextPicLeft;
if Assigned(ImageList) then
Inc(NextPicLeft, w + d)
else
Inc(NextPicLeft, Glyph.Width + d);
// Increment I to move onto next pic in list
Inc(I);
end
else // Remove pic from list
begin
// Remove pic from list
DrawInfo.Free;
DrawList.Delete(I);
// DO NOT increment I - Since pic was removed from list
// I will now point to next pic
end;
end;
end;
PicsWidth := NextPicLeft - ARect.Left;
end;
procedure TJvTFDays.ClearPicDrawList(DrawList: TList);
begin
while DrawList.Count > 0 do
begin
TJvTFDrawPicInfo(DrawList[0]).Free;
DrawList.Delete(0);
end;
end;
procedure TJvTFDays.DrawListPics(ACanvas: TCanvas; var ARect: TRect;
DrawList: TList);
var
I: Integer;
DrawInfo: TJvTFDrawPicInfo;
{$IF LCL_FullVersion >= 2000000}
f: Double;
PPI: Integer;
{$IFEND}
begin
{$IF LCL_FullVersion >= 2000000}
PPI := Font.PixelsPerInch;
f := GetCanvasScaleFactor;
{$IFEND}
for I := 0 to DrawList.Count - 1 do
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[I]);
with DrawInfo do
begin
if Assigned(ImageList) then
{$IF LCL_FullVersion >= 2000000}
ImageList.DrawForPPI(ACanvas, PicLeft, PicTop, ImageIndex, 0, PPI, f)
{$ELSE}
ImageList.Draw(ACanvas, PicLeft, PicTop, ImageIndex)
{$IFEND}
else
ACanvas.Draw(PicLeft, PicTop, Glyph);
end;
end;
end;
procedure TJvTFDays.DrawGrabLines(ACanvas: TCanvas; LineTop, LineLeft,
LineRight: Integer);
begin
// This draws the 3D grab handles, which have been replaced by flat style
// handles. This remains as reference for possible future comeback as option.
with ACanvas do
begin
Pen.Width := 1;
Pen.Color := clWhite;
MoveTo(LineLeft, LineTop);
LineTo(LineRight, LineTop);
MoveTo(LineLeft, LineTop + 1);
LineTo(LineLeft + 1, LineTop + 1);
Pen.Color := clSilver;
LineTo(LineRight - 1, LineTop + 1);
Pen.Color := clGray;
LineTo(LineRight, LineTop + 1);
MoveTo(LineLeft, LineTop + 2);
LineTo(LineRight, LineTop + 2);
Pen.Color := clWhite;
MoveTo(LineLeft, LineTop + 3);
LineTo(LineRight, LineTop + 3);
MoveTo(LineLeft, LineTop + 4);
LineTo(LineLeft + 1, LineTop + 4);
Pen.Color := clSilver;
LineTo(LineRight - 1, LineTop + 4);
Pen.Color := clGray;
LineTo(LineRight, LineTop + 4);
MoveTo(LineLeft, LineTop + 5);
LineTo(LineRight, LineTop + 5);
end
end;
procedure TJvTFDays.DrawGrabHandle(ACanvas: TCanvas; ARect: TRect;
AAppt: TJvTFAppt; TopHandle: Boolean);
begin
with ACanvas do
begin
Pen.Color := clBlack;
Pen.Width := 1;
Brush.Color := GrabHandles.Color;
Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
end;
if Assigned(FOnDrawGrabHandle) then
FOnDrawGrabHandle(Self, ACanvas, ARect, AAppt, TopHandle);
end;
procedure TJvTFDays.DrawCorner(ACanvas: TCanvas; Corner: TJvTFDaysCorner);
var
ARect: TRect;
CornerLeft: Integer;
begin
case Corner of
//group agcTopLeft : ARect := Classes.Rect(0, 0, RowHdrWidth, ColHdrHeight);
agcTopLeft:
{$IFDEF Jv_TIMEBLOCKS}
// ok
ARect := Classes.Rect(0, 0, CalcBlockRowHdrsWidth, CalcGroupColHdrsHeight);
{$ELSE}
// remove
// ARect := Classes.Rect(0, 0, RowHdrWidth, CalcGroupColHdrsHeight);
{$ENDIF Jv_TIMEBLOCKS}
agcTopRight:
begin
CornerLeft := Lesser(CellRect(RightCol, -1).Right, ClientWidth - FVScrollBar.Width);
//group ARect := Classes.Rect(CornerLeft, 0, ClientWidth, ColHdrHeight);
ARect := Classes.Rect(CornerLeft, 0, ClientWidth, CalcGroupColHdrsHeight);
end;
agcBottomLeft:
{$IFDEF Jv_TIMEBLOCKS}
// ok
ARect := Classes.Rect(0, ClientHeight - FHScrollBar.Height,
CalcBlockRowHdrsWidth, ClientHeight);
{$ELSE}
// remove
// ARect := Classes.Rect(0, ClientHeight - FHScrollBar.Height,
// RowHdrWidth, ClientHeight);
{$ENDIF Jv_TIMEBLOCKS}
agcBottomRight:
ARect := Classes.Rect(ClientWidth - FVScrollBar.Width - 1,
ClientHeight - FHScrollBar.Height - 1, ClientWidth, ClientHeight);
end;
with ACanvas do
begin
Brush.Color := HdrAttr.Color;
FillRect(ARect);
if HdrAttr.Frame3D then
{$IFDEF Jv_TIMEBLOCKS}
// ok
DrawFrame(ACanvas, ARect,
not ((Corner = agcTopLeft) and not HdrAttr.Frame3D), GridLineColor)
{$ELSE}
// remove
//DrawFrame(ACanvas, ARect,
// not ((Corner = agcTopLeft) and not HdrAttr.Frame3D))
{$ENDIF Jv_TIMEBLOCKS}
else
begin
case Corner of
agcTopLeft:
if RowHdrType = rhFancy then
begin
Pen.Color := FancyRowHdrAttr.TickColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom - 1);
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
end
else
{$IFDEF Jv_TIMEBLOCKS}
// ok
DrawFrame(ACanvas, ARect, False, GridLineColor);
{$ELSE}
// remove
//DrawFrame(ACanvas, ARect, False);
{$ENDIF Jv_TIMEBLOCKS}
agcTopRight:
begin
Pen.Color := clGray;
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
if VirtualCellRect(RightCol, -1).Right > ClientWidth - FVScrollBar.Width then
begin
MoveTo(ClientWidth - FVScrollBar.Width, ARect.Top);
LineTo(ClientWidth - FVScrollBar.Width, ARect.Bottom - 1);
end;
end;
agcBottomLeft:
begin
Pen.Color := clGray;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Right - 1, ARect.Top);
end;
end;
end;
if Assigned(FOnDrawCorner) then
FOnDrawCorner(Self, ACanvas, ARect, Corner);
end;
end;
procedure TJvTFDays.DrawRowHdr(ACanvas: TCanvas; Index: Integer);
var
Rect: TRect;
UseAttr: TJvTFDaysHdrAttr;
Txt: string;
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
Rect.Left := CalcBlockHdrWidth;
{$ELSE}
// remove
//Rect.Left := 0;
{$ENDIF Jv_TIMEBLOCKS}
//group Rect.Top := ColHdrHeight + (Index - TopRow) * RowHeight;
Rect.Top := CalcGroupColHdrsHeight + (Index - TopRow) * RowHeight;
{$IFDEF Jv_TIMEBLOCKS}
// ok
Rect.Right := Rect.Left + RowHdrWidth;
{$ELSE}
// remove
//Rect.Right := RowHdrWidth;
{$ENDIF Jv_TIMEBLOCKS}
Rect.Bottom := Rect.Top + RowHeight;
Txt := FormatDateTime(TimeFormat, RowToTime(Index));
if RowIsSelected(Index) then
UseAttr := SelHdrAttr
else
UseAttr := HdrAttr;
ACanvas.Brush.Color := UseAttr.Color;
ACanvas.Font.Assign(UseAttr.Font);
DrawTxt(ACanvas, Rect, Txt, taCenter, vaCenter);
if (Index = FocusedRow) and Focused and ShowFocus then
begin
InflateRect(Rect, -2, -2);
ManualFocusRect(ACanvas, Rect);
InflateRect(Rect, 2, 2);
end;
{$IFDEF Jv_TIMEBLOCKS}
// ok
DrawFrame(ACanvas, Rect, UseAttr.Frame3D, UseAttr.FrameColor);
{$ELSE}
// remove
//DrawFrame(ACanvas, ARect, UseAttr.Frame3D);
{$ENDIF Jv_TIMEBLOCKS}
if Assigned(FOnDrawRowHdr) then
FOnDrawRowHdr(Self, ACanvas, Rect, Index, RowIsSelected(Index));
end;
(*
procedure TJvTFDays.DrawColHdr(ACanvas: TCanvas; Index: Integer);
var
ARect,
TxtRect,
CalcRect: TRect;
Txt: string;
PTxt: PChar;
UseAttr: TJvTFDaysHdrAttr;
Flags: UINT;
TxtHt,
TxtRectHt: Integer;
begin
ARect := CellRect(Index, -1);
//Txt := Copy(Cols[Index].Title, 1, Length(Cols[Index].Title));
Txt := Cols[Index].Title;
if ColIsSelected(Index) then
UseAttr := SelHdrAttr
else
UseAttr := HdrAttr;
ACanvas.Brush.Color := UseAttr.Color;
ACanvas.Font.Assign(UseAttr.Font);
Flags := DT_NOPREFIX or DT_CENTER;
Case ColTitleStyle of
ctsSingleClip : Flags := Flags or DT_SINGLELINE or DT_VCENTER;
ctsSingleEllipsis: Flags := Flags or DT_END_ELLIPSIS or DT_SINGLELINE or
DT_VCENTER;
ctsMultiClip : Flags := Flags or DT_WORDBREAK;
ctsMultiEllipsis : Flags := Flags or DT_END_ELLIPSIS or
DT_WORDBREAK or DT_EDITCONTROL;
ctsHide : Flags := Flags or DT_SINGLELINE or DT_VCENTER;
end;
ACanvas.FillRect(ARect);
TxtRect := ARect;
Windows.InflateRect(TxtRect, -2, -2);
CalcRect := TxtRect;
PTxt := StrNew(PChar(Txt));
if (ColTitleStyle = ctsMultiClip) or
(ColTitleStyle = ctsMultiEllipsis) then
begin
TxtHt := Windows.DrawText(ACanvas.Handle, PTxt, -1, CalcRect,
Flags or DT_CALCRECT);
if TxtHt < RectHeight(TxtRect) then
begin
// we need to vertically center the text
TxtRectHt := RectHeight(TxtRect);
TxtRect.Top := TxtRect.Top + RectHeight(TxtRect) div 2 - TxtHt div 2;
TxtRect.Bottom := Lesser(TxtRect.Top + TxtRectHt, TxtRect.Bottom);
end;
end
else
if ColTitleStyle = ctsHide then
begin
Windows.DrawText(ACanvas.Handle, PTxt, -1, CalcRect, Flags or DT_CALCRECT);
if RectWidth(CalcRect) > RectWidth(TxtRect) then
PTxt := '';
end;
Windows.DrawText(ACanvas.Handle, PTxt, -1, TxtRect, Flags);
if (Index = FocusedCol) and Focused then
begin
CalcRect := ARect;
Windows.InflateRect(CalcRect, -2, -2);
ManualFocusRect(ACanvas, CalcRect);
{
if Windows.IsRectEmpty(TxtRect) then
Windows.InflateRect(TxtRect, 5, 5);
ManualFocusRect(ACanvas, TxtRect);
}
{ end;
DrawFrame(ACanvas, ARect, UseAttr.Frame3D);
if Assigned(FOnDrawColHdr) then
FOnDrawColHdr(Self, ACanvas, ARect, Index, ColIsSelected(Index));
end;
*)
// returns height in pixels of tallest col title
// assumes word wrap and bounds all of title
function TJvTFDays.GetTallestColTitle(ACanvas: TCanvas): Integer;
var
I, Tallest, ColLeft, TxtHt: Integer;
LRect: TRect;
TheCol: TJvTFDaysCol;
Txt: string;
Flags: UINT;
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
ColLeft := CalcBlockRowHdrsWidth;
{$ELSE}
// remove
//ColLeft := RowHdrWidth;
{$ENDIF Jv_TIMEBLOCKS}
Tallest := 0;
for I := 0 to Cols.Count - 1 do
begin
TheCol := Cols[I];
// (rom) silly assignments
// Just set top (0), left, and bottom (ColHdrHeight) for now.
//group ARect := Classes.Rect(ColLeft, 0, 0, ColHdrHeight);
LRect := Classes.Rect(ColLeft, CalcGroupHdrHeight, 0, CalcGroupColHdrsHeight);
// Set right by adding this col's width to the left value
LRect.Right := LRect.Left + TheCol.Width;
LRect := CellRect(I, -1);
InflateRect(LRect, -2, -2);
Txt := Copy(TheCol.Title, 1, Length(TheCol.Title));
if ColIsSelected(I) then
begin
ACanvas.Brush.Color := SelHdrAttr.Color;
ACanvas.Font.Assign(SelHdrAttr.Font);
end
else
begin
ACanvas.Brush.Color := HdrAttr.Color;
ACanvas.Font.Assign(HdrAttr.Font);
end;
// All parameters now specified. Now calc text height.
Flags := DT_NOPREFIX or DT_WORDBREAK or DT_CENTER or DT_CALCRECT;
TxtHt := DrawText(ACanvas.Handle, PChar(Txt), -1, LRect, Flags);
if TxtHt > Tallest then
Tallest := TxtHt;
Inc(ColLeft, TheCol.Width);
end;
Result := Tallest;
end;
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
procedure TJvTFDays.DrawFrame(ACanvas: TCanvas; ARect: TRect; Draw3D: Boolean);
var
OldPenColor: TColor;
begin
OldPenColor := ACanvas.Pen.Color;
if Draw3D then
ACanvas.Pen.Color := clBtnShadow
else
ACanvas.Pen.Color := GridLineColor;
ACanvas.MoveTo(ARect.Right - 1, ARect.Top);
ACanvas.LineTo(ARect.Right - 1, ARect.Bottom);
ACanvas.MoveTo(ARect.Left, ARect.Bottom - 1);
ACanvas.LineTo(ARect.Right, ARect.Bottom - 1);
if Draw3D then
begin
ACanvas.Pen.Color := clBtnHighlight;
ACanvas.MoveTo(ARect.Left, ARect.Top);
ACanvas.LineTo(ARect.Right, ARect.Top);
ACanvas.MoveTo(ARect.Left, ARect.Top);
ACanvas.LineTo(ARect.Left, ARect.Bottom);
end;
ACanvas.Pen.Color := OldPenColor;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
procedure TJvTFDays.DrawAppts(ACanvas: TCanvas; DrawAll: Boolean);
var
FromCol, ToCol, FromRow, ToRow, Col, I: Integer;
ApptStartRow, ApptEndRow, SchedDate: Integer;
Appt: TJvTFAppt;
TempSelAppt: TJvTFAppt;
begin
if DrawAll then
begin
FromCol := 0;
ToCol := Cols.Count - 1;
FromRow := 0;
ToRow := RowCount - 1;
end
else
begin
FromCol := LeftCol;
ToCol := RightCol;
FromRow := TopRow;
ToRow := BottomRow;
end;
for Col := FromCol to ToCol do
if Cols[Col].Connected then
begin
TempSelAppt := nil;
SchedDate := Trunc(Cols[Col].SchedDate);
for I := 0 to Cols[Col].Schedule.ApptCount - 1 do
begin
Appt := Cols[Col].Schedule.Appts[I];
// Added by Mike 10/31/01 7:04pm - Happy Haloween!!
// We want to draw the selected appt last. Check to see if the
// current appt is selected, if so, save a reference in TempSelAppt
// and then use TempSelAppt to draw the appt after the loop finishes.
// This solves the problem of having the bottom grab handle
// overwritten by an appt that lies immediately below the sel appt.
if Appt = SelAppt then
TempSelAppt := Appt
else
begin
CalcStartEndRows(Appt, SchedDate, ApptStartRow, ApptEndRow);
if (ApptStartRow <= ToRow) and (ApptEndRow >= FromRow) then
DrawAppt(ACanvas, Col, Appt, ApptStartRow, ApptEndRow);
end;
end;
// Added by Mike 10/31/01 7:04 pm - see above
if Assigned(TempSelAppt) then
begin
CalcStartEndRows(TempSelAppt, SchedDate, ApptStartRow, ApptEndRow);
if (ApptStartRow <= ToRow) and (ApptEndRow >= FromRow) then
DrawAppt(ACanvas, Col, TempSelAppt, ApptStartRow, ApptEndRow);
end;
end;
end;
procedure TJvTFDays.AdjustForMargins(var ARect: TRect);
begin
// Make room for side margins and grab handles
// Changed by TIM:
// Windows.InflateRect(ARect, -2, -2);
InflateRect(ARect, -1, -1);
// Commented out by Tim:
// if agoMoveAppt in Options then
// Inc(ARect.Top, GrabHandles.Height - 1);
// if agoSizeAppt in Options then
// Dec(ARect.Bottom, GrabHandles.Height - 1);
end;
procedure TJvTFDays.CanDrawWhat(ACanvas: TCanvas; ApptRect: TRect;
PicsHeight: Integer; out CanDrawText, CanDrawPics: Boolean);
//var
// TextHeightThreshold,
// TextWidthThreshold: Integer;
begin
// TextHeightThreshold := CanvasMaxTextHeight(ACanvas) * Thresholds.TextHeight;
// TextWidthThreshold := ACanvas.TextWidth('Bi') div 2 * Thresholds.TextWidth;
// if TextHeightThreshold + PicsHeight < RectHeight(ApptRect) then
// begin
// CanDrawText := RectWidth(ApptRect) >= TextWidthThreshold;
// CanDrawPics := True;
// end
// else
// if Thresholds.DropTextFirst then
// begin
// CanDrawText := False;
// CanDrawPics := True;
// if Thresholds.WholePicsOnly then
// if PicsHeight > RectHeight(ApptRect) then
// CanDrawPics := False;
// end
// else
// begin
// CanDrawText := (RectHeight(ApptRect) >= TextHeightThreshold) and
// (RectWidth(ApptRect) >= TextWidthThreshold);
// CanDrawPics := False;
// end;
CanDrawText := True;
CanDrawPics := True;
if not (agoShowPics in Options) then
CanDrawPics := False;
if not (agoShowText in Options) then
CanDrawText := False;
end;
procedure TJvTFDays.ManualFocusRect(ACanvas: TCanvas; ARect: TRect);
var
Mark: Boolean;
I: Integer;
OldPenMode: TPenMode;
begin
OldPenMode := ACanvas.Pen.Mode;
ACanvas.Pen.Mode := pmNot;
Mark := True;
// Top side
for I := ARect.Left to ARect.Right - 1 do
begin
if Mark then
ACanvas.Pixels[I, ARect.Top] := clBlack;
Mark := not Mark;
end;
// Right side
for I := ARect.Top + 1 to ARect.Bottom - 1 do
begin
if Mark then
ACanvas.Pixels[ARect.Right - 1, I] := clBlack;
Mark := not Mark;
end;
// Bottom side
for I := ARect.Right - 2 downto ARect.Left do
begin
if Mark then
ACanvas.Pixels[I, ARect.Bottom - 1] := clBlack;
Mark := not Mark;
end;
// Left side
for I := ARect.Bottom - 2 downto ARect.Top + 1 do
begin
if Mark then
ACanvas.Pixels[ARect.Left, I] := clBlack;
Mark := not Mark;
end;
ACanvas.Pen.Mode := OldPenMode;
end;
procedure TJvTFDays.DrawFancyRowHdrs(ACanvas: TCanvas);
var
I, J, MajorTickLength, MinorTickLength, TickLength: Integer;
LRect: TRect;
Lbl: string;
PrevHour, CurrentHour: Word;
// FirstMajor,
Selected, PrevHrSel, CurrHrSel, Switch: Boolean;
begin
MajorTickLength := GetMajorTickLength;
MinorTickLength := GetMinorTickLength;
// FirstMajor := True;
PrevHour := RowToHour(TopRow);
PrevHrSel := False;
CurrHrSel := False;
for I := TopRow to BottomRow do
begin
CurrentHour := RowToHour(I);
Switch := (CurrentHour <> PrevHour) or (I = BottomRow);
if Switch then
begin
PrevHrSel := CurrHrSel;
CurrHrSel := False;
end;
// Determine if this row is selected
Selected := False;
J := 0;
while (J < Cols.Count) and not Selected do
if CellIsSelected(Point(J, I)) then
Selected := True
else
Inc(J);
CurrHrSel := CurrHrSel or Selected;
LRect := CellRect(-1, I);
Lbl := GetMinorLabel(I);
if not RowEndsHour(I) then
TickLength := MinorTickLength
else
TickLength := MajorTickLength;
DrawMinor(ACanvas, LRect, I, Lbl, TickLength, Selected);
// Draw Major if needed
if Switch and (Granularity <> 60) then
begin
if I <> TopRow + 1 then
begin
{$IFDEF Jv_TIMEBLOCKS}
// ok
LRect.Left := CalcBlockHdrWidth;
LRect.Right := LRect.Left + RowHdrWidth - MinorTickLength;
{$ELSE}
// remove
//LRect.Left := 0;
//LRect.Right := RowHdrWidth - MinorTickLength;
{$ENDIF Jv_TIMEBLOCKS}
LRect.Top := VirtualCellRect(-1, HourStartRow(PrevHour)).Top;
//group if LRect.Top < ColHdrHeight then
//group LRect.Top := ColHdrHeight;
if LRect.Top < CalcGroupColHdrsHeight then
LRect.Top := CalcGroupColHdrsHeight;
LRect.Bottom := VirtualCellRect(-1, HourEndRow(PrevHour)).Bottom - 1;
if LRect.Bottom > ClientHeight then
LRect.Bottom := ClientHeight;
if FancyRowHdrAttr.Hr2400 then
Lbl := IntToStr(PrevHour)
else
begin
if PrevHour = 0 then
Lbl := '12'
else
if PrevHour > 12 then
Lbl := IntToStr(PrevHour - 12)
else
Lbl := IntToStr(PrevHour);
if (PrevHour = 0) or (PrevHour = 12) then
if PrevHour < 12 then
Lbl := Lbl + 'a'
else
Lbl := Lbl + 'p';
end;
if PrevHrSel then
ACanvas.Font.Assign(SelFancyRowHdrAttr.MajorFont)
else
ACanvas.Font.Assign(FancyRowHdrAttr.MajorFont);
ACanvas.Brush.Style := bsClear;
DrawText(ACanvas.Handle, PChar(Lbl), -1, LRect,
DT_NOPREFIX or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
if Assigned(FOnDrawMajorRowHdr) then
FOnDrawMajorRowHdr(Self, ACanvas, LRect, I - 1, PrevHrSel);
// FirstMajor := False;
end;
if Switch then
PrevHour := CurrentHour;
end;
end;
end;
procedure TJvTFDays.DrawMinor(ACanvas: TCanvas; ARect: TRect; RowNum: Integer;
const LabelStr: string; TickLength: Integer; Selected: Boolean);
var
Attr: TJvTFDaysFancyRowHdrAttr;
MinorRect, TxtRect: TRect;
begin
// do the background shading
ACanvas.Brush.Color := FancyRowHdrAttr.Color;
ACanvas.FillRect(ARect);
MinorRect := ARect;
MinorRect.Left := MinorRect.Right - GetMinorTickLength;
if Selected then
begin
Attr := SelFancyRowHdrAttr;
// Shade the minor rect if selected
ACanvas.Brush.Color := Attr.Color;
ACanvas.FillRect(MinorRect);
end
else
Attr := FancyRowHdrAttr;
with ACanvas do
begin
// draw the right border line
Pen.Color := Attr.TickColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
// now draw the tick
MoveTo(ARect.Right - 5, ARect.Bottom - 1);
LineTo(ARect.Right - 5 - TickLength, ARect.Bottom - 1);
end;
// set up a 2 pel margin on the right and bottom sides
TxtRect := ARect;
TxtRect.Right := TxtRect.Right - 6;
TxtRect.Bottom := TxtRect.Bottom - 2;
// now draw the LabelStr right aligned
ACanvas.Brush.Style := bsClear;
ACanvas.Font.Assign(Attr.MinorFont);
// draw the focus rect if needed
if (RowNum = FocusedRow) and Focused and ShowFocus and (LabelStr <> '') then
begin
MinorRect := TxtRect;
InflateRect(MinorRect, 0, -1);
inc(MinorRect.Right, 2);
MinorRect.Left := TxtRect.Right - ACanvas.TextWidth(LabelStr) - 2;
ManualFocusRect(ACanvas, MinorRect);
end;
DrawText(ACanvas.Handle, PChar(LabelStr), -1, TxtRect,
DT_SINGLELINE or DT_RIGHT or DT_NOPREFIX or DT_VCENTER);
if Assigned(FOnDrawMinorRowHdr) then
FOnDrawMinorRowHdr(Self, ACanvas, ARect, RowNum, Selected);
end;
function TJvTFDays.GetMinorLabel(RowNum: Integer): string;
const
Full24 = 'h:nn';
FullAP = 'h:nna/p';
MinOnly = 'nn';
var
FirstHourRow: Integer;
TimeFmt: string;
RowTime: TTime;
// LastFullRow, LastHourStart: Integer;
// LastHour: Word;
begin
if Granularity = 60 then begin
if FancyRowHdrAttr.Hr2400 then
TimeFmt := Full24
else
TimeFmt := FullAP
end else
TimeFmt := MinOnly;
// else
// if (RowNum = TopRow) and (not RowStartsHour(RowNum) or (PossVisibleRows = 1)) then
// TimeFmt := Full24
// else
// begin
// LastFullRow := TopRow + FullVisibleRows - 1;
// LastHour := RowToHour(LastFullRow);
// LastHourStart := HourStartRow(LastHour);
//
// if (RowNum = LastHourStart) or
// ((LastHourStart = TopRow) and (RowNum = TopRow)) then
// TimeFmt := Full24
// else
// TimeFmt := MinOnly;
// end;
// Get the Row Time
RowTime := RowToTime(RowNum);
if (FancyRowHdrAttr.OnlyShow00Minutes and (ExtractMins(RowTime) = 0)) or
(not FancyRowHdrAttr.OnlyShow00Minutes) then
begin
if (not FancyRowHdrAttr.Hr2400) and (Granularity < 60) then
begin
// Get the first row with a 00 hour
FirstHourRow := TopRow;
while (FirstHourRow < BottomRow) and (ExtractMins(RowToTime(FirstHourRow)) <> 0) do
Inc(FirstHourRow);
if RowTime = 0 then
Result := FormatSettings.TimeAMString
else
if RowTime = 0.50 then
Result := FormatSettings.TimePMString
else
if (RowNum = FirstHourRow) and (ExtractMins(RowTime) = 0) then
begin
if RowTime < 0.50 then
Result := FormatSettings.TimeAMString
else
Result := FormatSettings.TimePMString;
end
else
Result := FormatDateTime(TimeFmt, RowTime);
end
else
Result := FormatDateTime(TimeFmt, RowTime);
end
else
Result := '';
end;
function TJvTFDays.GetMinorTickLength: Integer;
var
TempFont: TFont;
begin
TempFont := TFont.Create;
try
TempFont.Assign(Canvas.Font);
Canvas.Font.Assign(FancyRowHdrAttr.MinorFont);
Result := Canvas.TextWidth('00') + 6;
Canvas.Font.Assign(TempFont);
finally
TempFont.Free;
end;
end;
function TJvTFDays.GetMajorTickLength: Integer;
begin
Result := RowHdrWidth - 8;
end;
procedure TJvTFDays.Resize;
var
ColsResized: Boolean;
begin
if Editing then
FinishEditAppt;
AlignScrollBars;
if not (csLoading in ComponentState) then
begin
if RowHeight > GetDataHeight then
RowHeight := GetDataHeight;
Cols.EnsureMaxColWidth;
if AutoSizeCols then
begin
ColsResized := CheckSBVis;
if not (vsbHorz in VisibleScrollBars) and not ColsResized then
Cols.ResizeCols;
end
else
CheckSBVis;
end;
CheckSBParams;
inherited Resize;
end;
procedure TJvTFDays.WMEraseBkgnd(var Msg: TLMessage);
begin
Msg.Result := LRESULT(False);
end;
procedure TJvTFDays.CMFontChanged(var Msg: TLMessage);
begin
HdrAttr.ParentFontChanged;
SelHdrAttr.ParentFontChanged;
ApptAttr.ParentFontChanged;
SelApptAttr.ParentFontChanged;
inherited;
end;
procedure TJvTFDays.CMEnabledChanged(var Msg: TLMessage);
begin
FVScrollBar.Enabled := Enabled;
FHScrollBar.Enabled := Enabled;
Invalidate;
if Enabled and FNeedCheckSBParams then
begin
// This is needed because of a TScrollBar bug. If the Max or LargeChange
// properties are changed while the scrollbar is disabled, the
// scrollbar will magically enable itself. Very frustrating. Anyway...
// This check and call to CheckSBParams will work around the problem.
// See TJvTFDays.CheckSBParams for other part of workaround.
FNeedCheckSBParams := False;
CheckSBParams;
end;
end;
procedure TJvTFDays.WMSetCursor(var Msg: TLMSetCursor);
var
Cur: HCURSOR;
Coord: TJvTFDaysCoord;
begin
exit;
Cur := 0;
with Msg do
if HitTest = HTCLIENT then
begin
Coord := PtToCell(FHitTest.X, FHitTest.Y);
case CanDragWhat(Coord) of
agsSizeCol, agsSizeRowHdr:
Cur := Screen.Cursors[crHSplit];
agsSizeRow, agsSizeColHdr:
Cur := Screen.Cursors[crVSplit];
agsSizeAppt:
Cur := Screen.Cursors[crSizeNS];
agsMoveAppt:
Cur := Screen.Cursors[crDrag];
end;
end;
if Cur <> 0 then
SetCursor(Cur)
else
inherited;
end;
procedure TJvTFDays.WMNCHitTest(var Msg: TLMNCHitTest);
begin
DefaultHandler(Msg);
FHitTest := ScreenToClient(SmallPointToPoint(Msg.Pos));
end;
procedure TJvTFDays.CMDesignHitTest(var Msg: TCMDesignHitTest);
var
TempState: TJvTFDaysState;
Coord: TJvTFDaysCoord;
begin
Coord := PtToCell(Msg.Pos.X, Msg.Pos.Y);
TempState := CanDragWhat(Coord);
Msg.Result := LRESULT(Ord(TempState <> agsNormal));
end;
procedure TJvTFDays.CNRequestRefresh(var Msg: TCNRequestRefresh);
var
I: Integer;
begin
for I := 0 to Cols.Count - 1 do
if (Cols[I].Schedule = Msg.Schedule) or (Msg.Schedule = nil) then
Cols[I].RefreshMap;
inherited;
end;
procedure TJvTFDays.Loaded;
var
I: Integer;
begin
FHScrollBar.Position := LeftCol;
FVScrollBar.Position := TopRow;
inherited Loaded;
CheckSBVis;
CheckSBParams;
Template.UpdateGrid;
Cols.FOldCount := Cols.Count;
for I := 0 to Cols.Count - 1 do
Cols[I].Connect;
AlignScrollBars;
end;
procedure TJvTFDays.RefreshControl;
var
I: Integer;
begin
for I := 0 to Cols.Count - 1 do
// Should do some additional checking here (which is commented out)
//if (Cols[I].Schedule = Msg.Schedule) or (Msg.Schedule = nil) then
Cols[I].RefreshMap;
inherited RefreshControl;
end;
procedure TJvTFDays.UpdateDesigner;
var
ParentForm: TCustomForm;
begin
if (csDesigning in ComponentState) and HandleAllocated and
not (csUpdating in ComponentState) then
begin
ParentForm := GetParentForm(Self);
if Assigned(ParentForm) and Assigned(ParentForm.Designer) then
ParentForm.Designer.Modified;
end;
end;
procedure TJvTFDays.CheckSBParams;
var
I, TempWidth, lRightCol: Integer;
begin
if not Enabled then
begin
// This is needed because of a TScrollBar bug. if the Max or LargeChange
// properties are changed while the scrollbar is disabled, the
// scrollbar will magically enable itself. Very frustrating. Anyway...
// This check and exit will workaround the problem.
// See TJvTFDays.CMEnabledChanged for other part of workaround.
FNeedCheckSBParams := True;
Exit;
end;
if vsbVert in VisibleScrollBars then
with FVScrollBar do
begin
Max := RowCount - FullVisibleRows; //RowCount - 2;
LargeChange := FullVisibleRows;
end;
if vsbHorz in VisibleScrollBars then
with FHScrollBar do
begin
Max := Cols.Count - 1;
lRightCol := LeftCol + VisibleCols - 1;
TempWidth := 0;
for I := LeftCol to lRightCol do
Inc(TempWidth, Cols[I].Width);
if TempWidth <= RectWidth(GetDataAreaRect) then
LargeChange := VisibleCols
else
LargeChange := VisibleCols - 1;
end;
end;
procedure TJvTFDays.ScrollBarScroll(Sender: TObject;
ScrollCode: TScrollCode; var ScrollPos: Integer);
var
SB: TJvTFDaysScrollBar;
I, TempWidth: Integer;
begin
if csLoading in ComponentState then
Exit;
if not (csDesigning in ComponentState) then
SetFocus;
if Editing then
FinishEditAppt;
SB := TJvTFDaysScrollBar(Sender);
case ScrollCode of
scLineUp, scLineDown, scPageUp, scPageDown, scTrack:
if SB.Kind = sbVertical then
begin
if (ScrollCode = scLineDown) or (ScrollCode = scPageDown) then
ScrollPos := Lesser(ScrollPos, RowCount - FullVisibleRows);
TopRow := ScrollPos;
UpdateDesigner;
end
else
begin
if ScrollPos > LeftCol then
begin
TempWidth := 0;
for I := LeftCol to Cols.Count - 1 do
Inc(TempWidth, Cols[I].Width);
if TempWidth <= GetDataWidth then
ScrollPos := LeftCol;
end;
LeftCol := ScrollPos;
UpdateDesigner;
end;
end;
end;
procedure TJvTFDays.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
GridCoord: TJvTFDaysCoord;
DragWhat: TJvTFDaysState;
begin
if not Enabled then
Exit;
FHint.ReleaseHandle;
inherited;
if ssDouble in Shift then
Exit;
if not (csDesigning in ComponentState) then
SetFocus;
GridCoord := PtToCell(X, Y);
if ssLeft in Shift then
with GridCoord do
begin
SetSelAppt(Appt);
// need to recalculate GridCoord here because component user may have
// freed the appt (esp. in a multi-user environment).
GridCoord := PtToCell(X, Y);
if Col > gcHdr then
FocusedCol := Col;
if Row > gcHdr then
FocusedRow := Row;
if (Col > gcHdr) and (Row > gcHdr) then
SelStart := Point(Col, Row)
else
if (Col = gcHdr) and (Row > gcHdr) then
SelStart := Point(FocusedCol, Row)
else
if (Col > gcHdr) and (Row = gcHdr) then
SelStart := Point(Col, FocusedRow);
end;
if (State = agsNormal) and (ssLeft in Shift) then
begin
DragWhat := CanDragWhat(GridCoord);
case DragWhat of
agsSizeCol, agsSizeRow, agsSizeColHdr, agsSizeRowHdr,
agsMoveCol, agsSizeAppt:
BeginDragging(GridCoord, DragWhat, GridCoord.Appt);
agsMoveAppt:
BeginDrag(False);
agsNormal:
if Assigned(SelAppt) then
EditAppt(GridCoord.Col, SelAppt);
end;
if DragWhat in [agsSizeAppt, agsMoveAppt, agsNormal] then
begin
FAutoScrollDir := asdNowhere;
FLiveTimer := True;
SetTimer(Handle, 1, 60, nil);
end;
end;
end;
procedure TJvTFDays.MouseMove(Shift: TShiftState; X, Y: Integer);
var
GridCoord: TJvTFDaysCoord;
AutoScrollMargin: TRect;
SelStartDate, SelEndDate: TDate;
SelStartTime, SelEndTime: TTime;
OldFSelEnd, HintTopLeft: TPoint;
FSelEndChanged: Boolean;
procedure UpdateAutoScroll;
begin
AutoScrollMargin := GetDataAreaRect;
//Windows.InflateRect(AutoScrollMargin, -10, -10);
if Y < AutoScrollMargin.Top then
FAutoScrollDir := asdUp
else
if Y > AutoScrollMargin.Bottom then
FAutoScrollDir := asdDown
else
if X < AutoScrollMargin.Left then
FAutoScrollDir := asdLeft
else
if X > AutoScrollMargin.Right then
FAutoScrollDir := asdRight
else
FAutoScrollDir := asdNowhere;
end;
begin
if not Enabled then
Exit;
inherited MouseMove(Shift, X, Y);
GridCoord := PtToCell(X, Y);
if State = agsNormal then
if Assigned(GridCoord.Appt) then
DoApptHint(GridCoord)
else
DoCellHint(GridCoord);
if not Focused and not (csDesigning in ComponentState) then
Exit;
FMouseMovePt := Point(X, Y);
FMouseMoveState := Shift;
case State of
agsNormal:
if ssLeft in Shift then
begin
with GridCoord do
begin
if Col > gcHdr then
FocusedCol := Col
else
FocusedCol := LeftCol;
if Row > gcHdr then
FocusedRow := Lesser(Row, Lesser(RowCount - 1, BottomRow + 1))
else
if FAutoScrollDir = asdDown then
FocusedRow := RowCount - 1
else
FocusedRow := TopRow;
end;
OldFSelEnd := FSelEnd;
SelEnd := Point(FocusedCol, FocusedRow);
FSelEndChanged := (OldFSelEnd.X <> FSelEnd.X) or
(OldFSelEnd.Y <> FSelEnd.Y);
if (agoShowSelHint in Options) and
(SelStart.X > gcHdr) and (SelStart.Y > gcHdr) and
(SelEnd.X > gcHdr) and (SelEnd.Y > gcHdr) and
((SelStart.X <> SelEnd.X) or (SelStart.Y <> SelEnd.Y)) then
begin
HintTopLeft := CellRect(GridCoord.Col, GridCoord.Row).TopLeft;
if FSelEndChanged then
begin
SelStartDate := Cols[SelStart.X].SchedDate;
SelStartTime := RowToTime(SelStart.Y);
SelEndDate := Cols[SelEnd.X].SchedDate;
SelEndTime := RowToTime(SelEnd.Y) +
EncodeTime(0, Granularity - 1, 0, 0);
FHint.StartEndHint(SelStartDate, SelEndDate, SelStartTime,
SelEndTime, HintTopLeft.X,
HintTopLeft.Y, True);
end
end
else
FHint.ReleaseHandle;
UpdateAutoScroll;
end;
agsSizeCol..agsMoveCol:
ContinueDragging(GridCoord, nil);
agsSizeAppt:
begin
UpdateAutoScroll;
if Y > GetDataAreaRect.Bottom then
GridCoord.Row := Lesser(BottomRow + 1, RowCount - 1);
if FAutoScrollDir = asdNowhere then
ContinueDragging(GridCoord, nil);
end;
end;
end;
procedure TJvTFDays.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
GridCoord: TJvTFDaysCoord;
begin
if not Enabled then
Exit;
inherited MouseUp(Button, Shift, X, Y);
if not Focused and not (csDesigning in ComponentState) then
Exit;
KillAutoScrollTimer;
GridCoord := PtToCell(X, Y);
case State of
agsSizeCol..agsSizeAppt:
EndDragging(GridCoord, nil);
agsNormal:
FHint.ReleaseHandle;
end;
end;
procedure TJvTFDays.DblClick;
begin
if Editing then
FinishEditAppt;
inherited DblClick;
end;
procedure TJvTFDays.DoStartDrag(var DragObject: TDragObject);
begin
if Editing then
FinishEditAppt;
inherited DoStartDrag(DragObject);
FDragInfo.Appt := SelAppt;
if FocusedCol > gcHdr then
FDragInfo.Schedule := Cols[FocusedCol].Schedule;
end;
procedure TJvTFDays.DragOver(Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
var
GridCoord: TJvTFDaysCoord;
Appt: TJvTFAppt;
SrcDragInfo: TJvTFDragInfo;
AutoScrollMargin: TRect;
procedure UpdateAutoScroll;
begin
AutoScrollMargin := GetDataAreaRect;
InflateRect(AutoScrollMargin, -10, -10);
if Y < AutoScrollMargin.Top then
FAutoScrollDir := asdUp
else
if Y > AutoScrollMargin.Bottom then
FAutoScrollDir := asdDown
else
if X < AutoScrollMargin.Left then
FAutoScrollDir := asdLeft
else
if X > AutoScrollMargin.Right then
FAutoScrollDir := asdRight
else
FAutoScrollDir := asdNowhere;
end;
begin
inherited DragOver(Source, X, Y, State, Accept);
if Source is TJvTFControl then
begin
SrcDragInfo := TJvTFControl(Source).DragInfo;
GridCoord := PtToCell(X, Y);
Accept := GridCoord.DragAccept;
Appt := SrcDragInfo.Appt;
case State of
dsDragEnter:
begin
if not Assigned(FDragInfo) then
FDragInfo := SrcDragInfo;
BeginDragging(GridCoord, agsMoveAppt, Appt);
end;
dsDragLeave:
begin
EndDragging(GridCoord, Appt);
if FDragInfo.ApptCtrl <> Self then
FDragInfo := nil;
end;
dsDragMove:
begin
FMouseMovePt := Point(X, Y);
UpdateAutoScroll;
if Y > GetDataAreaRect.Bottom then
GridCoord.Row := Lesser(BottomRow + 1, RowCount - 1);
if FAutoScrollDir = asdNowhere then
ContinueDragging(GridCoord, Appt);
end;
end;
end;
end;
procedure TJvTFDays.DoEndDrag(Target: TObject; X, Y: Integer);
begin
KillAutoScrollTimer;
FState := agsNormal;
inherited DoEndDrag(Target, X, Y);
end;
procedure TJvTFDays.DropAppt(ADragInfo: TJvTFDragInfo; X, Y: Integer);
const
cClassName = 'TJvTFCustomGlance';
var
Appt: TJvTFAppt;
Coord: TJvTFDaysCoord;
Confirm, SchedNameChange, StartDateChange, Share: Boolean;
NewSchedName: string;
NewStartDate, NewEndDate: TDate;
NewStartTime: TTime;
NewEndTime: TDateTime;
NewStartDT, NewEndDT: TDateTime;
begin
FHint.ReleaseHandle;
// APPOINTMENT CAN ONLY BE DROPPED IN THE DATA AREA !!!
Appt := ADragInfo.Appt;
// Calc new info
// DragAppt.Shift --> Ctrl = share, Shift = keep dates, Alt = keep times
Coord := PtToCell(X, Y);
NewSchedName := Cols[Coord.Col].SchedName;
CalcMoveStartEnd(Appt, Coord, ssShift in ADragInfo.Shift,
ssAlt in ADragInfo.Shift, NewStartDT, NewEndDT);
NewStartDate := Trunc(NewStartDT);
NewStartTime := Frac(NewStartDT);
NewEndDate := Trunc(NewEndDT);
NewEndTime := Frac(NewEndDT);
// Do a confirm drop event
Confirm := True;
if Assigned(FOnDropAppt) then
FOnDropAppt(Appt, NewSchedName, NewStartDate, NewStartTime,
NewEndDate, NewEndTime, ssCtrl in ADragInfo.Shift, Confirm);
if Confirm then
begin
//SchedNameChange := NewSchedName <> ADragInfo.Schedule.SchedName;
SchedNameChange := IsClassByName(ADragInfo.ApptCtrl, cClassName) or
(NewSchedName <> ADragInfo.Schedule.SchedName);
StartDateChange := (Trunc(NewStartDate) <> Trunc(Appt.StartDate)) or
(Trunc(NewEndDate) <> Trunc(Appt.EndDate));
Share := ssCtrl in ADragInfo.Shift;
Appt.BeginUpdate;
try
if (SchedNameChange and not StartDateChange and not Share) or
(not SchedNameChange and StartDateChange and not Share) or
(SchedNameChange and StartDateChange and not Share) or
(not SchedNameChange and StartDateChange and Share) or
(SchedNameChange and StartDateChange and Share) then
begin
if ADragInfo.ApptCtrl is TJvTFDays then
Appt.RemoveSchedule(ADragInfo.Schedule.SchedName)
else
if IsClassByName(ADragInfo.ApptCtrl, cClassName) then
Appt.ClearSchedules;
// THE FOLLOWING CODE SHOULD NOT BE NECESSARY.
// Make sure the old schedules get refreshed
{
aDate := Appt.StartDate;
while Trunc(aDate) <= Trunc(Appt.EndDate) do
begin
Sched := ScheduleManager.FindSchedule(ADragInfo.Schedule.SchedName, aDate);
if Assigned(Sched) then
ScheduleManager.RefreshConnections(Sched);
aDate := aDate + 1;
end;
}
end;
// Now we set the new StartEnd
Appt.SetStartEnd(NewStartDate, NewStartTime, NewEndDate, NewEndTime);
// if there's a change in SchedName then add the appt to the schedule
Appt.AddSchedule(NewSchedName);
// THE FOLLOWING CODE SHOULD NOT BE NECESSARY.
//ScheduleManager.RefreshConnections(Appt);
finally
Appt.EndUpdate;
end;
end;
if ADragInfo.ApptCtrl <> Self then
FState := agsNormal;
end;
procedure TJvTFDays.BeginDragging(Coord: TJvTFDaysCoord;
DragWhat: TJvTFDaysState; Appt: TJvTFAppt);
begin
Update;
FState := DragWhat;
FBeginDraggingCoord := Coord;
FDraggingCoord := Coord;
if (State <> agsMoveAppt) or Coord.DragAccept then
DrawDrag(Coord, Appt, False);
end;
procedure TJvTFDays.DrawDrag(Coord: TJvTFDaysCoord; AAppt: TJvTFAppt;
AClear: Boolean);
var
OldPen: TPen;
DragRect: TRect;
I, LineLeft, StartRow, EndRow, DragRectHt: Integer;
Sched: TJvTFSched;
StartDT, EndDT: TDateTime;
SchedName: string;
procedure InternalDrawFrame(ARect: TRect);
begin
Canvas.MoveTo(ARect.Left, ARect.Top);
Canvas.LineTo(ARect.Right - 2, ARect.Top);
Canvas.LineTo(ARect.Right - 2, ARect.Bottom - 2);
Canvas.LineTo(ARect.Left, ARect.Bottom - 2);
Canvas.LineTo(ARect.Left, ARect.Top);
end;
begin
if ((State = agsSizeAppt) and not Assigned(Coord.Schedule)) or
((State = agsMoveAppt) and ((Coord.Row < 0) or (Coord.Col < 0))) then
Exit;
OldPen := TPen.Create;
try
with Canvas, Coord do
begin
OldPen.Assign(Pen);
Pen.Style := psDot;
Pen.Mode := pmXOR;
Pen.Width := 1;
case State of
agsSizeCol, agsSizeRowHdr:
begin
MoveTo(AbsX, 0);
LineTo(AbsX, ClientHeight);
end;
agsSizeRow, agsSizeColHdr:
begin
MoveTo(0, AbsY);
LineTo(ClientWidth, AbsY);
end;
agsMoveCol:
begin
Pen.Mode := pmNotXOR;
Pen.Style := psSolid;
Pen.Width := 3;
LineLeft := AbsX - CellX;
if FDraggingCoord.Col > FBeginDraggingCoord.Col then
Inc(LineLeft, Cols[FDraggingCoord.Col].Width);
MoveTo(LineLeft, 0);
LineTo(LineLeft, ClientHeight);
end;
agsSizeAppt:
begin
Pen.Style := psSolid;
Pen.Mode := pmNotXOR;
AAppt := FBeginDraggingCoord.Appt;
CalcSizeEndTime(AAppt, EndDT);
if AClear and FHint.HandleAllocated then
begin
FHint.ReleaseHandle;
// Control must be updated here. if not, drag lines will
// not be drawn properly.
Update;
end;
SchedName := Coord.Schedule.SchedName;
for I := 0 to Cols.Count - 1 do
begin
Sched := Cols[I].Schedule;
if Assigned(Sched) and (Sched.SchedName = SchedName) and
((Trunc(Sched.SchedDate) >= Trunc(AAppt.StartDate)) and
(Trunc(Sched.SchedDate) <= Trunc(EndDT))) then
begin
//Calc Start and end rows
if Trunc(Sched.SchedDate) = Trunc(AAppt.StartDate) then
StartRow := TimeToRow(AAppt.StartTime)
else
StartRow := 0;
if Trunc(Sched.SchedDate) = Trunc(EndDT) then
EndRow := TimeToRow(AdjustEndTime(EndDT))
else
EndRow := RowCount - 1;
DragRectHt := (EndRow - StartRow + 1) * RowHeight;
DragRect := VirtualCellRect(I, StartRow);
DragRect.Bottom := DragRect.Top + DragRectHt;
DragRect.Top := Greater(DragRect.Top, GetDataAreaRect.Top);
DragRect.Bottom := Lesser(DragRect.Bottom, GetDataAreaRect.Bottom);
InternalDrawFrame(DragRect);
end;
end;
if not AClear and (agoShowApptHints in Options) then
FHint.StartEndHint(AAppt.StartDate, Trunc(EndDT),
AAppt.StartTime, Frac(EndDT), DragRect.Left + 2,
DragRect.Bottom + 2, True);
end;
agsMoveAppt:
begin
Pen.Style := psSolid;
Pen.Mode := pmNotXOR;
Coord.Row := Greater(0, Greater(Coord.Row, TopRow - 1));
CalcMoveStartEnd(AAppt, Coord, ssShift in FDragInfo.Shift,
ssAlt in FDragInfo.Shift, StartDT, EndDT);
if AClear and FHint.HandleAllocated then
begin
FHint.ReleaseHandle;
Update;
end;
if Assigned(Coord.Schedule) then
SchedName := Coord.Schedule.SchedName;
DragRect := Classes.Rect(-1, -1, -1, -1); // Used to not show hint if outside a valid day.
for I := 0 to Cols.Count - 1 do
begin
Sched := Cols[I].Schedule;
if Assigned(Sched) and (Sched.SchedName = SchedName) and
((Trunc(Sched.SchedDate) >= Trunc(StartDT)) and
(Trunc(Sched.SchedDate) <= Trunc(EndDT))) then
begin
//Calc Start and end rows
if Trunc(Sched.SchedDate) = Trunc(StartDT) then
StartRow := TimeToRow(StartDT)
else
StartRow := 0;
if Trunc(Sched.SchedDate) = Trunc(EndDT) then
EndRow := TimeToRow(AdjustEndTime(EndDT))
else
EndRow := RowCount - 1;
DragRectHt := (EndRow - StartRow + 1) * RowHeight;
DragRect := VirtualCellRect(I, StartRow);
DragRect.Bottom := DragRect.Top + DragRectHt;
DragRect.Top := Greater(DragRect.Top, GetDataAreaRect.Top);
InternalDrawFrame(DragRect);
end;
end;
if not AClear and (agoShowApptHints in Options) and
(DragRect.Top <> -1) and (DragRect.Left <> -1) and
(DragRect.Right <> -1) and (DragRect.Bottom <> -1) then
FHint.StartEndHint(Trunc(StartDT), Trunc(EndDT),
Frac(StartDT), Frac(EndDT),
DragRect.Right + 2, DragRect.Top + 2,
True);
end;
end;
end;
finally
Canvas.Pen.Assign(OldPen);
OldPen.Free;
end;
end;
procedure TJvTFDays.ContinueDragging(Coord: TJvTFDaysCoord; Appt: TJvTFAppt);
var
ValidDrag, SameSchedName, ValidEnd, DiffCoord: Boolean;
SameDateLaterTime, LaterDate, DoDrawDrag: Boolean;
OldLeft, NewLeft: Integer;
begin
if State = agsSizeAppt then
begin
Coord.Row := Greater(Coord.Row, TopRow);
Coord.Row := Lesser(Coord.Row, BottomRow);
end;
DoDrawDrag := False;
case State of
agsSizeCol, agsSizeRowHdr, agsSizeRow, agsSizeColHdr:
DoDrawDrag := True;
agsMoveCol:
begin
OldLeft := FDraggingCoord.AbsX - FDraggingCoord.CellX;
NewLeft := Coord.AbsX - Coord.CellX;
DoDrawDrag := (OldLeft <> NewLeft) and
(Coord.Row = gcHdr) and (Coord.Col > gcHdr);
end;
agsSizeAppt:
begin
SameSchedName := False;
ValidEnd := False;
DiffCoord := False;
ValidDrag := Assigned(FBeginDraggingCoord.Schedule) and
Assigned(FDraggingCoord.Schedule) and Assigned(Coord.Schedule);
if ValidDrag then
begin
SameSchedName :=
FDraggingCoord.Schedule.SchedName = FBeginDraggingCoord.Schedule.SchedName;
LaterDate := (Trunc(Coord.Schedule.SchedDate) > Trunc(FBeginDraggingCoord.Appt.StartDate)) and
(Coord.Row >= 0);
SameDateLaterTime :=
(Trunc(Coord.Schedule.SchedDate) = Trunc(FBeginDraggingCoord.Appt.StartDate)) and
(Coord.Row >= TimeToRow(FBeginDraggingCoord.Appt.StartTime));
ValidEnd := LaterDate or SameDateLaterTime;
DiffCoord := not ((Coord.Row = FDraggingCoord.Row) and (Coord.Col = FDraggingCoord.Col));
end;
DoDrawDrag := ValidDrag and SameSchedName and ValidEnd and DiffCoord;
end;
agsMoveAppt:
DoDrawDrag := (Coord.Col <> FDraggingCoord.Col) or (Coord.Row <> FDraggingCoord.Row);
end;
if DoDrawDrag then
begin
if (State <> agsMoveAppt) or FDraggingCoord.DragAccept then
DrawDrag(FDraggingCoord, Appt, True); // clear old line
FDraggingCoord := Coord;
if (State <> agsMoveAppt) or FDraggingCoord.DragAccept then
DrawDrag(FDraggingCoord, Appt, False); // draw new line
end;
end;
procedure TJvTFDays.EndDragging(Coord: TJvTFDaysCoord; Appt: TJvTFAppt);
var
Confirm: Boolean;
ColNum, DeltaSize, NewSize: Integer;
NewEndDT: TDateTime;
begin
Confirm := True;
try
if (State <> agsMoveAppt) or FDraggingCoord.DragAccept then
DrawDrag(FDraggingCoord, Appt, True); // clear old line
case State of
agsSizeCol:
begin
ColNum := FBeginDraggingCoord.Col;
DeltaSize := Coord.AbsX - FBeginDraggingCoord.AbsX;
NewSize := Cols[ColNum].Width + DeltaSize;
if Assigned(FOnSizeCol) then
FOnSizeCol(Self, ColNum, NewSize, Confirm);
if Confirm then
begin
Cols[ColNum].Width := NewSize;
UpdateDesigner;
end;
end;
agsSizeRow:
begin
DeltaSize := Coord.AbsY - FBeginDraggingCoord.AbsY;
NewSize := RowHeight + DeltaSize;
if Assigned(FOnSizeRow) then
FOnSizeRow(Self, 0, NewSize, Confirm);
if Confirm then
begin
RowHeight := NewSize;
UpdateDesigner;
end;
end;
agsSizeColHdr:
begin
DeltaSize := Coord.AbsY - FBeginDraggingCoord.AbsY;
NewSize := ColHdrHeight + DeltaSize;
if Assigned(FOnSizeColHdr) then
FOnSizeColHdr(Self, 0, NewSize, Confirm);
if Confirm then
begin
ColHdrHeight := NewSize;
UpdateDesigner;
end;
end;
agsSizeRowHdr:
begin
DeltaSize := Coord.AbsX - FBeginDraggingCoord.AbsX;
NewSize := RowHdrWidth + DeltaSize;
if Assigned(FOnSizeRowHdr) then
FOnSizeRowHdr(Self, 0, NewSize, Confirm);
if Confirm then
begin
RowHdrWidth := NewSize;
UpdateDesigner;
end;
end;
agsMoveCol:
begin
NewSize := FDraggingCoord.Col;
if Assigned(FOnMoveCol) then
FOnMoveCol(Self, FBeginDraggingCoord.Col, NewSize, Confirm);
if Confirm then
begin
Cols.MoveCol(FBeginDraggingCoord.Col, NewSize);
UpdateDesigner;
end;
end;
agsSizeAppt:
begin
FHint.ReleaseHandle;
Appt := FBeginDraggingCoord.Appt;
CalcSizeEndTime(Appt, NewEndDT);
if Assigned(FOnSizeAppt) then
FOnSizeAppt(Self, Appt, NewEndDT, Confirm);
if Confirm then
begin
// WHY AM I CALLING RefreshControls HERE?????
ScheduleManager.RefreshConnections(Appt);
Appt.SetStartEnd(Appt.StartDate, Appt.StartTime,
Trunc(NewEndDT), Frac(NewEndDT));
ScheduleManager.RefreshConnections(Appt);
end;
end;
//agsMoveAppt: nothing special here - see DropAppt method
end;
finally
// Don't reset state if moving appt. State will be reset in DoEndDrag
// and/or DropAppt methods. Resetting State here will cause problems when
// dragging between multiple appt controls.
if State <> agsMoveAppt then
FState := agsNormal;
end;
end;
function TJvTFDays.CanDragWhat(Coord: TJvTFDaysCoord): TJvTFDaysState;
var
TopHandleRect, BottomHandleRect: TRect;
begin
case State of
agsSizeCol, agsSizeRow, agsSizeColHdr, agsSizeRowHdr,
agsMoveCol, agsSizeAppt, agsMoveAppt:
begin
Result := State;
Exit;
end;
else
Result := agsNormal;
end;
with Coord do
begin
if ((agoSizeCols in Options) or (csDesigning in ComponentState)) and
(Row = gcHdr) and (Col > gcHdr) and
(CellX > Cols[Col].Width - SizingThreshold) then
begin
Result := agsSizeCol;
Exit;
end;
if ((agoSizeRows in Options) or (csDesigning in ComponentState)) and
(Row > gcHdr) and (Col = gcHdr) and
(CellY > RowHeight - SizingThreshold) then
begin
Result := agsSizeRow;
Exit;
end;
if ((agoSizeColHdr in Options) or (csDesigning in ComponentState)) and
(Row = gcHdr) and (Col > gcUndef) and
(CellY > ColHdrHeight - SizingThreshold) then
begin
Result := agsSizeColHdr;
Exit;
end;
if ((agoSizeRowHdr in Options) or (csDesigning in ComponentState)) and
(Row > gcUndef) and (Col = gcHdr) and
(CellX > RowHdrWidth - SizingThreshold) then
begin
Result := agsSizeRowHdr;
Exit;
end;
if ((agoMoveCols in Options) or (csDesigning in ComponentState)) and
(Coord.Row = gcHdr) and (Coord.Col > gcHdr) and
not (Template.ActiveTemplate = agtLinear) and
((State = agsNormal) or (State = agsMoveCol)) and
(Cols.Count > 1) then
begin
Result := agsMoveCol;
Exit;
end;
// move grab handles
if Assigned(SelAppt) then
begin
TopHandleRect := GetTopGrabHandleRect(Col, SelAppt);
BottomHandleRect := GetBottomGrabHandleRect(Col, SelAppt);
if PtInRect(TopHandleRect, Point(AbsX, AbsY)) and
(agoMoveAppt in Options) then
Result := agsMoveAppt
else
if PtInRect(BottomHandleRect, Point(AbsX, AbsY)) and
(agoSizeAppt in Options) then
Result := agsSizeAppt;
end;
// if ((agoSizeAppt in Options) or (agoMoveAppt in Options)) and
// Assigned(Appt) and (Appt = SelAppt) then
// begin
// ApptRect := GetApptRect(Col, Appt);
// if (AbsY <= ApptRect.Top + GrabHandles.Height - 1) and
// (agoMoveAppt in Options) then
// begin
// Result := agsMoveAppt;
// Exit;
// end
// else
// if (AbsY >= ApptRect.Bottom - GrabHandles.Height + 1) and
// (agoSizeAppt in Options) then
// begin
// Result := agsSizeAppt;
// Exit;
// end;
// end;
end;
end;
procedure TJvTFDays.CalcSizeEndTime(Appt: TJvTFAppt; out NewEndDT: TDateTime);
var
TimeOffset: TTime;
Sched: TJvTFSched;
begin
Sched := FDraggingCoord.Schedule;
if (Sched.SchedName = FBeginDraggingCoord.Schedule.SchedName) and
(Trunc(Sched.SchedDate) >= Trunc(Appt.StartDate)) then
if agoSnapSize in Options then
if FDraggingCoord.Row <> RowCount - 1 then
NewEndDT := Trunc(Sched.SchedDate) + Frac(RowToTime(FDraggingCoord.Row + 1))
else
NewEndDT := Trunc(Sched.SchedDate) + Frac(RowEndTime(FDraggingCoord.Row))
else
begin
TimeOffset := Frac(Appt.EndTime) -
Frac(RowToTime(TimeToRow(AdjustEndTime(Appt.EndTime))));
NewEndDT := Trunc(Sched.SchedDate) +
Frac(RowToTime(FDraggingCoord.Row)) + TimeOffset;
end
else
NewEndDT := Trunc(Appt.EndDate) + Frac(Appt.EndTime);
end;
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
procedure TJvTFDays.CalcMoveStartEnd(Appt: TJvTFAppt; Coord: TJvTFDaysCoord;
KeepDates, KeepTimes: Boolean; var StartDT, EndDT: TDateTime);
var
NewStart,
NewEnd: TDateTime;
begin
NewStart := Trunc(Cols[Coord.Col].SchedDate) + Frac(RowToTime(Coord.Row));
if not (agoSnapMove in Options) then
NewStart := NewStart +
Frac(Appt.StartTime) - RowToTime(TimeToRow(Appt.StartTime));
NewEnd := (Trunc(Appt.EndDate) + Frac(Appt.EndTime)) -
(Trunc(Appt.StartDate) + Frac(Appt.StartTime)) +
NewStart;
if KeepDates then
begin
NewStart := Trunc(Appt.StartDate) + Frac(NewStart);
NewEnd := Trunc(Appt.EndDate) + Frac(NewEnd);
end;
if KeepTimes then
begin
NewStart := Trunc(NewStart) + Frac(Appt.StartTime);
NewEnd := Trunc(NewEnd) + Frac(Appt.EndTime);
end;
StartDT := NewStart;
EndDT := NewEnd;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDays.CalcMoveStartEnd(Appt: TJvTFAppt; Coord: TJvTFDaysCoord;
KeepDates, KeepTimes: Boolean; out StartDT, EndDT: TDateTime);
var
NewStart, NewEnd: TDateTime;
TimeBlockIndex, BlockStartRow, BlockEndRow: Integer;
BlockStartTime, BlockEndTime: TTime;
H, M, S, MS: Word;
begin
TimeBlockIndex := RowToTimeBlock(Coord.Row);
if TimeBlockProps.SnapMove and (TimeBlockIndex > -1) then
begin
GetTimeBlockStartEnd(TimeBlockIndex, BlockStartRow, BlockEndRow);
BlockStartTime := RowToTime(BlockStartRow);
BlockEndTime := RowEndTime(BlockEndRow);
NewStart := Trunc(Cols[Coord.Col].SchedDate) + Frac(BlockStartTime);
NewEnd := Trunc(NewStart) + Frac(BlockEndTime);
end
else
begin
NewStart := Trunc(Cols[Coord.Col].SchedDate) + Frac(RowToTime(Coord.Row));
if not (agoSnapMove in Options) then
NewStart := NewStart +
Frac(Appt.StartTime) - RowToTime(TimeToRow(Appt.StartTime));
NewEnd := (Trunc(Appt.EndDate) + Frac(Appt.EndTime)) -
(Trunc(Appt.StartDate) + Frac(Appt.StartTime)) +
NewStart;
// NewEnd cannot fall exactly on midnight. Bad things happen.
DecodeTime(NewEnd, H, M, S, MS);
if (H = 0) and (M = 0) and (S = 0) then
NewEnd := NewEnd - ONE_SECOND;
if KeepDates then
begin
NewStart := Trunc(Appt.StartDate) + Frac(NewStart);
NewEnd := Trunc(Appt.EndDate) + Frac(NewEnd);
end;
if KeepTimes then
begin
NewStart := Trunc(NewStart) + Frac(Appt.StartTime);
NewEnd := Trunc(NewEnd) + Frac(Appt.EndTime);
end;
end;
StartDT := NewStart;
EndDT := NewEnd;
end;
{$ENDIF Jv_TIMEBLOCKS}
procedure TJvTFDays.EnsureCol(ACol: Integer);
begin
if (ACol < 0) or (ACol > Cols.Count - 1) then
raise EJvTFDaysError.CreateRes(@RsEColumnIndexOutOfBounds);
end;
procedure TJvTFDays.EnsureRow(ARow: Integer);
begin
if (ARow < 0) or (ARow > RowCount - 1) then
raise EJvTFDaysError.CreateRes(@RsERowIndexOutOfBounds);
end;
procedure TJvTFDays.KeyDown(var Key: Word; Shift: TShiftState);
var
H: Word;
Handled: Boolean;
procedure DoSel;
begin
if ssShift in Shift then
SelEnd := Point(FocusedCol, FocusedRow)
else
SelStart := Point(FocusedCol, FocusedRow);
ColInView(FocusedCol);
RowInView(FocusedRow);
end;
begin
Handled := True;
inherited KeyDown(Key, Shift);
case Key of
VK_RETURN:
if ssAlt in Shift then
EditAppt(FocusedCol, SelAppt);
VK_UP:
if ssCtrl in Shift then
ScrollDays(-7)
else
if ssAlt in Shift then
SelPrevAppt
else
begin
FocusedRow := Greater(FocusedRow - 1, 0);
DoSel;
end;
VK_DOWN:
if ssCtrl in Shift then
ScrollDays(7)
else
if ssAlt in Shift then
SelNextAppt
else
begin
FocusedRow := Lesser(FocusedRow + 1, RowCount - 1);
DoSel;
end;
VK_RIGHT:
if ssCtrl in Shift then
NextDate
else
if ssAlt in Shift then
SelFirstApptNextCol
else
begin
FocusedCol := Lesser(FocusedCol + 1, Cols.Count - 1);
DoSel;
end;
VK_LEFT:
if ssCtrl in Shift then
PrevDate
else
if ssAlt in Shift then
SelFirstApptPrevCol
else
begin
FocusedCol := Greater(FocusedCol - 1, 0);
DoSel;
end;
VK_PRIOR:
if ssCtrl in Shift then
ScrollMonths(-1)
else
begin
TopRow := Greater(TopRow - FullVisibleRows, 0);
FocusedRow := Greater(FocusedRow - FullVisibleRows, TopRow);
DoSel;
end;
VK_NEXT:
if ssCtrl in Shift then
ScrollMonths(1)
else
begin
TopRow := Lesser(TopRow + FullVisibleRows, RowCount - FullVisibleRows);
FocusedRow := Lesser(FocusedRow + FullVisibleRows, RowCount - 1);
DoSel;
end;
VK_HOME:
if ssCtrl in Shift then
TopRow := TimeToRow(PrimeTime.StartTime)
else
begin
TopRow := 0;
FocusedRow := 0;
DoSel;
end;
VK_END:
if ssCtrl in Shift then
RowInView(TimeToRow(AdjustEndTime(PrimeTime.EndTime)))
else
begin
RowInView(RowCount - 1);
FocusedRow := RowCount - 1;
DoSel;
end;
VK_F1..VK_F12:
if ssCtrl in Shift then
begin
H := Key - VK_F1 + 1;
if ssShift in Shift then
Inc(H, 12);
if Key = VK_F12 then
Dec(H, 12);
RowInView(TimeToRow(EncodeTime(H, 0, 0, 0)));
end;
VK_INSERT:
if Shift = [ssCtrl] then
case Granularity of
2:
Granularity := 1;
3:
Granularity := 2;
4:
Granularity := 3;
5:
Granularity := 4;
6:
Granularity := 5;
10:
Granularity := 6;
12:
Granularity := 10;
15:
Granularity := 12;
20:
Granularity := 15;
30:
Granularity := 20;
60:
Granularity := 30;
end
else
if Shift = [ssShift] then
DoInsertSchedule
else
if Shift = [] then
DoInsertAppt;
VK_DELETE:
if Shift = [ssCtrl] then
case Granularity of
1:
Granularity := 2;
2:
Granularity := 3;
3:
Granularity := 4;
4:
Granularity := 5;
5:
Granularity := 6;
6:
Granularity := 10;
10:
Granularity := 12;
12:
Granularity := 15;
15:
Granularity := 20;
20:
Granularity := 30;
30:
Granularity := 60;
end
else
if Shift = [ssShift] then
DoDeleteSchedule
else
if Shift = [] then
DoDeleteAppt;
else
Handled := False;
end;
if Handled then
Key := 0;
end;
procedure TJvTFDays.KeyPress(var Key: Char);
begin
inherited KeyPress(Key);
QuickEntry(Key);
end;
procedure TJvTFDays.DoInsertSchedule;
begin
if Assigned(FOnInsertSchedule) then
FOnInsertSchedule(Self);
end;
procedure TJvTFDays.DoInsertAppt;
begin
if Assigned(FOnInsertAppt) then
FOnInsertAppt(Self);
end;
procedure TJvTFDays.DoDeleteAppt;
begin
if Assigned(FOnDeleteAppt) then
FOnDeleteAppt(Self);
end;
procedure TJvTFDays.DoDeleteSchedule;
begin
if Assigned(FOnDeleteSchedule) then
FOnDeleteSchedule(Self);
end;
function TJvTFDays.DoMouseWheelDown(Shift: TShiftState;
MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelDown(Shift, MousePos);
if not Result then
begin
if TopRow < RowCount - FullVisibleRows then
TopRow := TopRow + 1;
Result := True;
end;
end;
function TJvTFDays.DoMouseWheelUp(Shift: TShiftState;
MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelUp(Shift, MousePos);
if not Result then
begin
if TopRow > 0 then
TopRow := TopRow - 1;
Result := True;
end;
end;
procedure TJvTFDays.DestroyApptNotification(AAppt: TJvTFAppt);
begin
if AAppt = SelAppt then
SelAppt := nil;
inherited DestroyApptNotification(AAppt);
end;
procedure TJvTFDays.CMMouseLeave(var Msg: TLMessage);
begin
FHint.ReleaseHandle;
inherited;
end;
procedure TJvTFDays.DoEnter;
begin
inherited DoEnter;
if Assigned(FOnFocusedColChanged) then
FOnFocusedColChanged(Self);
if Assigned(FOnFocusedRowChanged) then
FOnFocusedRowChanged(Self);
Invalidate;
end;
procedure TJvTFDays.DoExit;
begin
if Assigned(FOnFocusedColChanged) then
FOnFocusedColChanged(Self);
if Assigned(FOnFocusedRowChanged) then
FOnFocusedRowChanged(Self);
Invalidate;
inherited DoExit;
end;
function TJvTFDays.GetSelStart: TPoint;
begin
// This routine will always return the start of the selection regardless
// of whether FSelStart and FSelEnd are in the correct order or not.
if FFromToSel then
if (FSelStart.X < FSelEnd.X) or
((FSelStart.X = FSelEnd.X) and (FSelStart.Y < FSelEnd.Y)) then
Result := FSelStart
else
Result := FSelEnd
else
Result := Point(Lesser(FSelStart.X, FSelEnd.X),
Lesser(FSelStart.Y, FSelEnd.Y));
end;
function TJvTFDays.GetSelEnd: TPoint;
begin
// This routine will always return the end of the selection regardless
// of whether FSelStart and FSelEnd are in the correct order or not.
if FFromToSel then
if (FSelStart.X < FSelEnd.X) or
((FSelStart.X = FSelEnd.X) and (FSelStart.Y < FSelEnd.Y)) then
Result := FSelEnd
else
Result := FSelStart
else
Result := Point(Greater(FSelStart.X, FSelEnd.X),
Greater(FSelStart.Y, FSelEnd.Y));
end;
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
procedure TJvTFDays.SetSelStart(Value: TPoint);
begin
FSelStart := Value;
FSelEnd := Value;
DoNavigate;
Invalidate;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDays.SetSelStart(Value: TPoint);
var
TimeBlock: Integer;
StartRow: Integer = -1; // to silence the compiler
EndRow: Integer = -1; // dto.
begin
TimeBlock := RowToTimeBlock(Value.Y);
if (TimeBlock = -1) and (TimeBlocks.Count > 0) then
Exit;
FSelStart := Value;
FSelEnd := Value;
if TimeBlock > -1 then
begin
GetTimeBlockStartEnd(TimeBlock, StartRow, EndRow);
FSelStart.Y := StartRow;
FSelEnd.Y := EndRow;
end;
// DoNavigate;
Invalidate;
end;
{$ENDIF Jv_TIMEBLOCKS}
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
procedure TJvTFDays.SetSelEnd(Value: TPoint);
var
SameName,
Consecutive: Boolean;
I,
TestStart,
TestEnd,
DateDiff: Integer;
begin
/////////////////////////////////////////////////////////////////////
// This routine enforces the rules by which cells can be selected.
// There are two different types of selection:
// 1. From/To - As mouse moves from cell(1, 4) to cell(2, 8)...
// Cell(1, 4) through cell(1, LastRow) is selected, AND
// Cell(2, TopRow) through cell(2, 8) is selected.
// 2. Block - As mouse moves from cell(1, 4) to cell(2, 8)...
// Cell(1, 4) through cell(1, 8) is selected, AND
// Cell(2, 4) through cell(2, 8) is selected.
//
// There are six different cases that are possible:
// 1. Same SchedName (resource), contiguous dates ==> From/To selection
// (Mike - 1/1/99 and Mike - 1/2/99)
// 2. Same name, non-contiguous dates ==> Selection not allowed
// (Mike - 1/1/99 and Mike - 2/1/99)
// 3. Same name, same date ==> Block selection
// (Mike - 1/1/99 and Mike - 1/1/99)
// 4. Different name, contiguous dates ==> Selection not allowed
// (Mike - 1/1/99 and Jennifer - 1/2/99)
// 5. Different name, non-contiguous dates ==> Selection not allowed
// (Mike - 1/1/99 and Jennifer - 2/1/99)
// 6. Different name, same date ==> Block selection
// (Mike - 1/1/99 and Jennifer - 1/1/99)
///////////////////////////////////////////////////////////////////////
// Check for different end value
if (FSelEnd.X <> Value.X) or (FSelEnd.Y <> Value.Y) then
begin
// Check for valid end
if (FSelStart.X > gcHdr) and (Value.X > gcHdr) and (FSelEnd.X > gcHdr) and
(FSelStart.Y > gcHdr) and (Value.Y > gcHdr) and (FSelEnd.Y > gcHdr) then
begin
// FFromToSel flag needed for drawing selection frame when
// SelCellAttr.Style = scsFrame. Frame is drawn in DrawDataCell.
//FFromToSel := False;
// We need a two-level check. First check new end (Value) against
// old end (FSelEnd). if that is NOT a valid end then check
// new end (Value) against start (FSelStart).
// IMPORTANT NOTE: When in a case #1 and selection moves up or down
// within the same column, the code below will interpret that as
// Case #3. This is not exactly correct, but it still yields the
// correct results.
// First check new end against old end
SameName := Cols[FSelEnd.X].SchedName = Cols[Value.X].SchedName;
DateDiff := Abs(Trunc(Cols[FSelEnd.X].SchedDate) -
Trunc(Cols[Value.X].SchedDate));
if ( SameName and (DateDiff = 1)) or // Case #1
( SameName and (DateDiff = 0)) or // Case #3
(not SameName and (DateDiff = 0)) then // Case #6
begin
FFromToSel := (SameName and (DateDiff = 1)) or
(FFromToSel and (SameName and (DateDiff = 0)));
FSelEnd := Value;
DoNavigate;
Invalidate;
end
else
// if first check fails then check new end against start
begin
SameName := Cols[FSelStart.X].SchedName = Cols[Value.X].SchedName;
DateDiff := Abs(Trunc(Cols[FSelStart.X].SchedDate) -
Trunc(Cols[Value.X].SchedDate));
if ( SameName and (DateDiff = 1)) or // Case #1
( SameName and (DateDiff = 0)) or // Case #3
(not SameName and (DateDiff = 0)) then // Case #6
begin
FFromToSel := (SameName and (DateDiff = 1)) or
(FFromToSel and (SameName and (DateDiff = 0)));
FSelEnd := Value;
DoNavigate;
Invalidate;
end
else
// Do a third check for "lagging selection"
// (Sometimes mouse loses selection, especially when speed
// threshold is exceeded.)
begin
// Check for consecutive dates
TestStart := Lesser(SelStart.X, Value.X);
TestEnd := Greater(SelStart.X, Value.X);
I := TestStart;
Consecutive := True;
while (I < TestEnd) and Consecutive do
if Trunc(Cols[I + 1].SchedDate) -
Trunc(Cols[I].SchedDate) <> 1 then
Consecutive := False
else
Inc(I);
if Consecutive then
begin
FFromToSel := True;
FSelEnd := Value;
DoNavigate;
Invalidate;
end
else
FFromToSel := False;
end;
end;
end;
end;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDays.SetSelEnd(Value: TPoint);
var
SameName, Consecutive, InTimeBlock: Boolean;
I, TestStart, TestEnd, DateDiff, TimeBlock: Integer;
SelStartTimeBlock, StartRow, EndRow: Integer;
procedure CheckFollowMouse;
begin
if (TimeBlocks.Count > 0) and SameName and (DateDiff = 1) and
(Value.X <> SelStart.X) then
SelStart := Point(Value.X, SelStart.Y);
end;
begin
{
This routine enforces the rules by which cells can be selected.
There are two different types of selection:
1. From/To - As mouse moves from cell(1, 4) to cell(2, 8)...
Cell(1, 4) through cell(1, LastRow) is selected, AND
Cell(2, TopRow) through cell(2, 8) is selected.
2. Block - As mouse moves from cell(1, 4) to cell(2, 8)...
Cell(1, 4) through cell(1, 8) is selected, AND
Cell(2, 4) through cell(2, 8) is selected.
NOTE: The Block selection type should not be confused with
Time Blocks. They are two different things. The only
type of allowable selection when using Time Blocks is
Block, however a Block selection can exist without
the use of Time Blocks.
There are six different cases that are possible:
1. Same SchedName (resource), contiguous dates ==> From/To selection
(Mike - 1/1/99 and Mike - 1/2/99)
2. Same name, non-contiguous dates ==> Selection not allowed
(Mike - 1/1/99 and Mike - 2/1/99)
3. Same name, same date ==> Block selection
(Mike - 1/1/99 and Mike - 1/1/99)
4. Different name, contiguous dates ==> Selection not allowed
(Mike - 1/1/99 and Jennifer - 1/2/99)
5. Different name, non-contiguous dates ==> Selection not allowed
(Mike - 1/1/99 and Jennifer - 2/1/99)
6. Different name, same date ==> Block selection
(Mike - 1/1/99 and Jennifer - 1/1/99)
}
// Do a time block check and adjust Value.Y if necessary to always
// select the entire time block.
TimeBlock := RowToTimeBlock(Value.Y);
if (TimeBlock = -1) and (TimeBlocks.Count > 0) then
Exit;
SelStartTimeBlock := RowToTimeBlock(SelStart.Y);
InTimeBlock := (TimeBlock > -1) or (SelStartTimeBlock > -1);
if InTimeBlock then
begin
if TimeBlock > -1 then
begin
GetTimeBlockStartEnd(TimeBlock, StartRow, EndRow);
SelStart := Point(SelStart.X, StartRow);
end
else
SelStart := Point(SelStart.X, Value.Y);
Value.Y := EndRow;
end;
// Check for different end value
if (FSelEnd.X <> Value.X) or (FSelEnd.Y <> Value.Y) then
begin
// Check for valid end
if (FSelStart.X > gcHdr) and (Value.X > gcHdr) and (FSelEnd.X > gcHdr) and
(FSelStart.Y > gcHdr) and (Value.Y > gcHdr) and (FSelEnd.Y > gcHdr) then
begin
// FFromToSel flag needed for drawing selection frame when
// SelCellAttr.Style = scsFrame. Frame is drawn in DrawDataCell.
//FFromToSel := False;
// We need a two-level check. First check new end (Value) against
// old end (FSelEnd). if that is NOT a valid end then check
// new end (Value) against start (FSelStart).
// IMPORTANT NOTE: When in a case #1 and selection moves up or down
// within the same column, the code below will interpret that as
// Case #3. This is not exactly correct, but it still yields the
// correct results.
// First check new end against old end
SameName := Cols[FSelEnd.X].SchedName = Cols[Value.X].SchedName;
DateDiff := Abs(Trunc(Cols[FSelEnd.X].SchedDate) -
Trunc(Cols[Value.X].SchedDate));
CheckFollowMouse;
if (SameName and (DateDiff = 1) and (TimeBlocks.Count = 0)) or // Case #1 only if no timeblocks
(SameName and (DateDiff = 0)) or // Case #3
(not SameName and (DateDiff = 0)) then // Case #6
begin
FFromToSel := (SameName and (DateDiff = 1)) or
(FFromToSel and (SameName and (DateDiff = 0)));
FSelEnd := Value;
// DoNavigate;
Invalidate;
end
else
// if first check fails then check new end against start
begin
SameName := Cols[FSelStart.X].SchedName = Cols[Value.X].SchedName;
DateDiff := Abs(Trunc(Cols[FSelStart.X].SchedDate) -
Trunc(Cols[Value.X].SchedDate));
CheckFollowMouse;
if (SameName and (DateDiff = 1) and (TimeBlocks.Count = 0)) or // Case #1 only if no timeblocks
(SameName and (DateDiff = 0)) or // Case #3
(not SameName and (DateDiff = 0)) then // Case #6
begin
FFromToSel := (SameName and (DateDiff = 1)) or
(FFromToSel and (SameName and (DateDiff = 0)));
FSelEnd := Value;
// DoNavigate;
Invalidate;
end
else
// Do a third check for "lagging selection"
// (Sometimes mouse loses selection, especially when speed
// threshold is exceeded.)
begin
// Check for consecutive dates
TestStart := Lesser(SelStart.X, Value.X);
TestEnd := Greater(SelStart.X, Value.X);
I := TestStart;
Consecutive := False;
while (I < TestEnd) and Consecutive do
if Trunc(Cols[I + 1].SchedDate) -
Trunc(Cols[I].SchedDate) <> 1 then
Consecutive := False
else
Inc(I);
if Consecutive then
begin
FFromToSel := True;
FSelEnd := Value;
// DoNavigate;
Invalidate;
end
else
FFromToSel := False;
end;
end;
end;
end;
end;
{$ENDIF Jv_TIMEBLOCKS}
procedure TJvTFDays.QuickEntry(Key: Char);
var
Appt: TJvTFAppt;
ApptStartDate, ApptEndDate: TDate;
ApptStartTime, ApptEndTime: TTime;
I: Integer;
ID: string;
Confirm: Boolean;
begin
// Ord(key) must be >= 32 to quick entry an appt.
if (Ord(Key) >= 32) and ValidSelection and not Assigned(SelAppt) and
(agoQuickEntry in Options) and (agoEditing in Options) and CanEdit then
begin
// Calc the appt's start and end info
ApptStartDate := Cols[SelStart.X].SchedDate;
ApptEndDate := Cols[SelEnd.X].SchedDate;
ApptStartTime := RowToTime(SelStart.Y);
// subtract one min from granularity and then add it back in. This
// avoids min overflow when granularity = 60.
ApptEndTime := RowToTime(SelEnd.Y) +
EncodeTime(0, Granularity - 1, 0, 0) +
EncodeTime(0, 1, 0, 0);
// if we're on the last row make sure end time is not = 0 (12am next day)
// This avoids InvalidStartEnd exception when calling Appt.SetStartEnd
if SelEnd.Y = RowCount - 1 then
ApptEndTime := ApptEndTime - EncodeTime(0, 0, 1, 0);
ID := '';
Confirm := True;
if Assigned(FOnCreateQuickEntry) then
FOnCreateQuickEntry(Self, ID, ApptStartDate, ApptStartTime,
ApptEndDate, ApptEndTime, Confirm);
if Confirm and Assigned(ScheduleManager) then
begin
Appt := ScheduleManager.dbNewAppt(ID);
Appt.Persistent := True;
// Set the Start/end info
Appt.SetStartEnd(ApptStartDate, ApptStartTime, ApptEndDate, ApptEndTime);
// Set the Schedule (resource) names
for I := SelStart.X to SelEnd.X do
if ColIsSelected(I) then
Appt.AddSchedule(Cols[I].SchedName);
Appt.Persistent := False;
SetSelAppt(Appt);
EditAppt(SelStart.X, SelAppt);
// Put the Key in the editor and set the caret
FEditor.Text := Key;
FEditor.SelStart := 1;
FEditor.QuickCreate := True;
if Assigned(FOnQuickEntry) then
FOnQuickEntry(Self);
end;
end;
end;
function TJvTFDays.GetAdjClientRect: TRect;
begin
Result := GetClientRect;
if Assigned(FVScrollBar) and FVScrollBar.Visible then
Dec(Result.Right, FVScrollBar.Width);
if Assigned(FHScrollBar) and FHScrollBar.Visible then
Dec(Result.Bottom, FHScrollBar.Height);
end;
function TJvTFDays.GetDataAreaRect: TRect;
begin
Result := GetAdjClientRect;
{$IFDEF Jv_TIMEBLOCKS}
// ok
Inc(Result.Left, CalcBlockRowHdrsWidth);
{$ELSE}
// remove
//Inc(Result.Left, RowHdrWidth);
{$ENDIF Jv_TIMEBLOCKS}
//group Inc(Result.Top, ColHdrHeight);
Inc(Result.Top, CalcGroupColHdrsHeight);
end;
function TJvTFDays.GetDataWidth: Integer;
begin
Result := RectWidth(GetDataAreaRect);
end;
function TJvTFDays.GetDataHeight: Integer;
begin
Result := RectHeight(GetDataAreaRect);
end;
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
function TJvTFDays.PtToCell(X, Y: Integer): TJvTFDaysCoord;
Var
ColNum,
RowNum,
AdjX,
AdjY,
Temp,
TotalWidth,
SegCount,
MapCol: Integer;
Done: Boolean;
ApptRect: TRect;
begin
With Result do
begin
Col := gcUndef;
Row := gcUndef;
CellX := -100;
CellY := -100;
AbsX := X;
AbsY := Y;
Schedule := nil;
Appt := nil;
end;
if X < RowHdrWidth then
begin
Result.Col := gcHdr;
Result.CellX := X;
end
else
if LeftCol > -1 then
begin
// Find the col that PtX falls in
ColNum := LeftCol;
AdjX := X - RowHdrWidth;
Done := False;
Temp := 0;
while (ColNum < Cols.Count) and not Done do
begin
Inc(Temp, Cols[ColNum].Width);
if AdjX < Temp then
begin
Done := True;
Result.Col := ColNum;
Result.CellX := AdjX - (Temp - Cols[ColNum].Width);
end
else
Inc(ColNum);
end;
end;
if Y < CalcGroupHdrHeight then
begin
Result.Row := gcGroupHdr;
Result.CellY := Y;
end
//else
//if Y < ColHdrHeight then
else
if Y < CalcGroupColHdrsHeight then
begin
Result.Row := gcHdr;
Result.CellY := Y - CalcGroupHdrHeight;
end
else
if TopRow > -1 then
begin
RowNum := TopRow;
//group AdjY := Y - ColHdrHeight;
AdjY := Y - CalcGroupColHdrsHeight;
Done := False;
Temp := 0;
while (RowNum < RowCount) and not Done do
begin
Inc(Temp, RowHeight);
if AdjY < Temp then
begin
Done := True;
Result.Row := RowNum;
Result.CellY := AdjY - (Temp - RowHeight);
end
else
Inc(RowNum);
end;
end;
if Result.Col > gcHdr then
begin
Result.Schedule := Cols[Result.Col].Schedule;
if (Result.Row > gcHdr) and Assigned(Result.Schedule) then
begin
TotalWidth := Cols[Result.Col].Width;
SegCount := Cols[Result.Col].MapColCount(Result.Row);
if SegCount > 0 then
begin
MapCol := LocateDivCol(Result.CellX, TotalWidth, SegCount);
Result.Appt := Cols[Result.Col].MapLocation(MapCol, Result.Row);
ApptRect := GetApptRect(Result.Col, Result.Appt);
if not Windows.PtInRect(ApptRect, Point(X, Y)) then
Result.Appt := nil;
end;
end;
end;
Result.DragAccept := (Result.Row > gcHdr) and (Result.Col > gcHdr);
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
function TJvTFDays.PtToCell(X, Y: Integer): TJvTFDaysCoord;
var
ColNum, RowNum, AdjX, AdjY, Temp, TotalWidth, SegCount, MapCol: Integer;
Done: Boolean;
ApptRect: TRect;
begin
with Result do
begin
Col := gcUndef;
Row := gcUndef;
CellX := -100;
CellY := -100;
AbsX := X;
AbsY := Y;
Schedule := nil;
Appt := nil;
end;
if X < CalcBlockHdrWidth then
begin
// POSSIBLE BUG!!
//Result.Row := gcGroupHdr; // WRONG CODE
Result.Col := gcGroupHdr; // UNTESTED - CORRECT CODE
Result.CellX := X;
end
//block if X < RowHdrWidth then
else
if X < CalcBlockRowHdrsWidth then
begin
Result.Col := gcHdr;
Result.CellX := X - CalcBlockHdrWidth;
end
else
if LeftCol > -1 then
begin
// Find the col that PtX falls in
ColNum := LeftCol;
//block AdjX := X - RowHdrWidth;
AdjX := X - CalcBlockRowHdrsWidth;
Done := False;
Temp := 0;
while (ColNum < Cols.Count) and not Done do
begin
Inc(Temp, Cols[ColNum].Width);
if AdjX < Temp then
begin
Done := True;
Result.Col := ColNum;
Result.CellX := AdjX - (Temp - Cols[ColNum].Width);
end
else
Inc(ColNum);
end;
if not Done then
begin
Result.Col := Cols.Count-1;
Result.CellX := AdjX - (Temp - Cols[Cols.Count-1].Width);
end;
end;
if Y < CalcGroupHdrHeight then
begin
Result.Row := gcGroupHdr;
Result.CellY := Y;
end
//else if Y < ColHdrHeight then
else
if Y < CalcGroupColHdrsHeight then
begin
Result.Row := gcHdr;
Result.CellY := Y - CalcGroupHdrHeight;
end
else
if TopRow > -1 then
begin
RowNum := TopRow;
//group AdjY := Y - ColHdrHeight;
AdjY := Y - CalcGroupColHdrsHeight;
Done := False;
Temp := 0;
while (RowNum < RowCount) and not Done do
begin
Inc(Temp, RowHeight);
if AdjY < Temp then
begin
Done := True;
Result.Row := RowNum;
Result.CellY := AdjY - (Temp - RowHeight);
end
else
Inc(RowNum);
end;
if not Done then
begin
Result.Row := RowCount-1;
Result.CellY := AdjY - (Temp - RowHeight);
end;
end;
if Result.Col > gcHdr then
begin
Result.Schedule := Cols[Result.Col].Schedule;
// move grab handles
if PtInTopHandle(Point(X, Y), Result.Col, SelAppt) then
Result.Appt := SelAppt
else
if PtInBottomHandle(Point(X, Y), Result.Col, SelAppt) then
Result.Appt := SelAppt
else
if (Result.Row > gcHdr) and Assigned(Result.Schedule) then
begin
TotalWidth := Cols[Result.Col].Width;
SegCount := Cols[Result.Col].MapColCount(Result.Row);
if SegCount > 0 then
begin
MapCol := LocateDivCol(Result.CellX, TotalWidth, SegCount);
Result.Appt := Cols[Result.Col].MapLocation(MapCol, Result.Row);
ApptRect := GetApptRect(Result.Col, Result.Appt);
if not PtInRect(ApptRect, Point(X, Y)) then
Result.Appt := nil;
end;
end;
end;
Result.DragAccept := (Result.Row > gcHdr) and (Result.Col > gcHdr);
end;
{$ENDIF Jv_TIMEBLOCKS}
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
function TJvTFDays.CellRect(Col, Row: Integer): TRect;
Var
I: Integer;
VisGrpHdrRect: TRect;
begin
if (Row = gcGroupHdr) and (Col > gcHdr) then
begin
VisGrpHdrRect := Classes.Rect(RowHdrWidth, 0, RowHdrWidth + GetDataWidth,
CalcGroupHdrHeight);
Windows.IntersectRect(Result, VisGrpHdrRect, VirtualGroupHdrRect(Col));
end
else
if Col < 0 then // Row hdr
if Row < 0 then
//group Result := Classes.Rect(0, 0, RowHdrWidth, ColHdrHeight) // origin cell
Result := Classes.Rect(0, 0, RowHdrWidth, CalcGroupColHdrsHeight) // origin cell
else
if (Row >= TopRow) and (Row <= BottomRow) then
// Row Hdr for visible data row
begin
Result.Left := 0;
//group Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
Result.Right := RowHdrWidth;
Result.Bottom := Result.Top + RowHeight;
end
else
// Row Hdr for non-visible data row
Result := EmptyRect
else
if (Col >= LeftCol) and (Col <= RightCol) then // visible data col
if Row < 0 then
// Col hdr for visible data col
begin
Result.Left := RowHdrWidth;
For I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
//group Top := 0;
Result.Top := CalcGroupHdrHeight;
//group Bottom := ColHdrHeight;
Result.Bottom := CalcGroupColHdrsHeight;
end
else
if (Row >= TopRow) and (Row <= BottomRow) then
// visible data cell
begin
Result.Left := RowHdrWidth;
For I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
//group Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
Result.Bottom := Result.Top + RowHeight;
end
else
// non-visible data cell (visible col, but non-visible row)
Result := EmptyRect
else // non-visible data col
Result := EmptyRect;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
function TJvTFDays.CellRect(Col, Row: Integer): TRect;
var
I: Integer;
VisGrpHdrRect: TRect;
begin
Result := EmptyRect;
if (Col = gcGroupHdr) and (Row > gcHdr) then
begin
VisGrpHdrRect := Classes.Rect(0, CalcGroupColHdrsHeight, CalcBlockRowHdrsWidth,
CalcGroupColHdrsHeight + GetDataHeight);
IntersectRect(Result, VisGrpHdrRect, VirtualBlockHdrRect(Row));
end
else
if (Row = gcGroupHdr) and (Col > gcHdr) then
begin
//block VisGrpHdrRect := Classes.Rect(RowHdrWidth, 0, RowHdrWidth + GetDataWidth,
// CalcGroupHdrHeight);
VisGrpHdrRect := Classes.Rect(CalcBlockRowHdrsWidth, 0,
CalcBlockRowHdrsWidth + GetDataWidth, CalcGroupHdrHeight);
IntersectRect(Result, VisGrpHdrRect, VirtualGroupHdrRect(Col));
end
else
if Col < 0 then // Row hdr
if Row < 0 then
//group Result := Classes.Rect(0, 0, RowHdrWidth, ColHdrHeight) // origin cell
//block Result := Classes.Rect(0, 0, RowHdrWidth, CalcGroupColHdrsHeight) // origin cell
Result := Classes.Rect(0, 0, CalcBlockRowHdrsWidth, CalcGroupColHdrsHeight)
else
if (Row >= TopRow) and (Row <= BottomRow) then
// Row Hdr for visible data row
begin
//block Left := 0;
Result.Left := CalcBlockHdrWidth;
//group Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
//block Right := RowHdrWidth;
Result.Right := Result.Left + RowHdrWidth;
Result.Bottom := Result.Top + RowHeight;
end
else
// Row Hdr for non-visible data row
Result := EmptyRect
else
if (Col >= LeftCol) and (Col <= RightCol) then // visible data col
if Row < 0 then
// Col hdr for visible data col
begin
//block Result.Left := RowHdrWidth;
Result.Left := CalcBlockRowHdrsWidth;
for I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
//group Result.Top := 0;
Result.Top := CalcGroupHdrHeight;
//group Result.Bottom := ColHdrHeight;
Result.Bottom := CalcGroupColHdrsHeight;
end
else
if (Row >= TopRow) and (Row <= BottomRow) then
// visible data cell
begin
//block Result.Left := RowHdrWidth;
Result.Left := CalcBlockRowHdrsWidth;
for I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
//group Result.Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
Result.Bottom := Result.Top + RowHeight;
end
else
// non-visible data cell (visible col, but non-visible row)
Result := EmptyRect
else // non-visible data col
Result := EmptyRect;
end;
{$ENDIF Jv_TIMEBLOCKS}
{$IFNDEF Jv_TIMEBLOCKS}
// remove
{
function TJvTFDays.VirtualCellRect(Col, Row: Integer): TRect;
Var
I: Integer;
begin
if Row = gcGroupHdr then
Result := VirtualGroupHdrRect(Col)
else
begin
if Col > -1 then
begin
Result.Left := RowHdrWidth;
// At most, only one of the following For loops will execute
// depending on whether Col is to the left or to the right of LeftCol
For I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
For I := LeftCol - 1 downto Col do
Dec(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
end
else
begin
Result.Left := 0;
Result.Right := RowHdrWidth;
end;
if Row > -1 then
begin
//group Result.Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
Result.Bottom := Result.Top + RowHeight;
end
else
begin
//group Result.Top := 0;
Result.Top := CalcGroupHdrHeight;
Result.Bottom := Result.Top + ColHdrHeight;
end;
end;
end;
}
{$ENDIF !Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// ok
function TJvTFDays.VirtualCellRect(Col, Row: Integer): TRect;
var
I: Integer;
begin
if (Col = gcGroupHdr) and (Row > gcHdr) then
Result := VirtualBlockHdrRect(Row)
else
if (Row = gcGroupHdr) and (Col > gcHdr) then
Result := VirtualGroupHdrRect(Col)
else
begin
if Col > -1 then
begin
//block Result.Left := RowHdrWidth;
Result.Left := CalcBlockRowHdrsWidth;
// At most, only one of the following For loops will execute
// depending on whether Col is to the Result.Left or to the Result.Right of LeftCol
for I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
for I := LeftCol - 1 downto Col do
Dec(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
end
else
begin
//block Result.Left := 0;
Result.Left := CalcBlockHdrWidth;
//block Result.Right := RowHdrWidth;
Result.Right := Result.Left + RowHdrWidth;
end;
if Row > -1 then
begin
//group Result.Top := ColHdrHeight + (Row - TopRow) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + (Row - TopRow) * RowHeight;
Result.Bottom := Result.Top + RowHeight;
end
else
begin
//group Result.Top := 0;
Result.Top := CalcGroupHdrHeight;
Result.Bottom := Result.Top + ColHdrHeight;
end;
end;
end;
{$ENDIF Jv_TIMEBLOCKS}
function TJvTFDays.GetApptRect(Col: Integer; Appt: TJvTFAppt): TRect;
var
MapCol, MapColCount, Base, MakeUp, BaseWidth, MakeUpWidth: Integer;
BaseCount, GridColWidth, ApptWidth, StartRow, EndRow: Integer;
VirtCellRect: TRect;
begin
if not Assigned(Appt) then
begin
Result := EmptyRect;
Exit;
end;
CalcStartEndRows(Appt, Cols[Col].SchedDate, StartRow, EndRow);
if (StartRow < 0) and (EndRow >= 0) then
StartRow := 0;
// if the above condition fails and the StartRow is STILL invalid then
// let the 'Map col not found' catch the error.
EndRow := Lesser(EndRow, RowCount - 1);
MapCol := Cols[Col].LocateMapCol(Appt, StartRow);
if MapCol < 1 then
begin
//Cols[Col].DumpMap;
raise EJvTFDaysError.CreateRes(@RsEMapColNotFoundForAppointment);
end;
MapColCount := Cols[Col].MapColCount(StartRow);
if MapColCount < 1 then
begin
//Cols[Col].FMap.Dump('corrupt dump.txt'); !!! FOR DEBUGGING ONLY !!!!
//Cols[Col].DumpMap;
raise EJvTFDaysError.CreateRes(@RsECorruptAppointmentMap);
end;
// Col guaranteed to be partially visible
VirtCellRect := VirtualCellRect(Col, StartRow);
GridColWidth := RectWidth(VirtCellRect);
// The Base* and MakeUp* code that follows calcs the appt width and Result.Left
// and takes into account a total width that isn't evenly divisible by
// the map col count. If there is a discrepancy then that discrepancy
// is divided up among the cols working Result.Left to Result.Right.
//
// Example: Total width = 113, col count = 5
// col 1 = 23
// col 2 = 23
// col 3 = 23
// col 4 = 22
// col 5 = 22
// Total = 113
//
// As opposed to:
// width of all cols = Total div colcount = 22
// ==> Total = 22 * 5 = 110 [110 <> 113]
Base := GridColWidth div MapColCount;
MakeUp := GridColWidth mod MapColCount;
MakeUpWidth := Lesser(MapCol - 1, MakeUp) * (Base + 1);
BaseCount := MapCol - 1 - MakeUp;
if BaseCount > 0 then
BaseWidth := BaseCount * Base
else
BaseWidth := 0;
ApptWidth := Base;
if MapCol <= MakeUp then
Inc(ApptWidth);
Result.Left := VirtCellRect.Left + MakeUpWidth + BaseWidth;
Result.Right := Result.Left + ApptWidth - ApptBuffer;
Result.Top := VirtCellRect.Top - 1;
Result.Bottom := VirtualCellRect(Col, EndRow).Bottom;
end;
function TJvTFDays.LocateDivCol(X, TotalWidth, SegCount: Integer): Integer;
var
Base, MakeUp, ApproxSeg, MakeUpWidth: Integer;
BaseCount, BaseWidth, SegWidth, NextSegStart: Integer;
begin
if X <= 0 then
Result := 1
else
if X >= TotalWidth then
Result := SegCount
else
begin
Base := TotalWidth div SegCount;
// Protect against div by zero
if Base < 1 then
Base := 1;
MakeUp := TotalWidth mod SegCount;
ApproxSeg := X div Base;
MakeUpWidth := Lesser(ApproxSeg - 1, MakeUp) * (Base + 1);
BaseCount := ApproxSeg - 1 - MakeUp;
if BaseCount > 0 then
BaseWidth := BaseCount * Base
else
BaseWidth := 0;
SegWidth := Base;
if ApproxSeg <= MakeUp then
Inc(SegWidth);
NextSegStart := MakeUpWidth + BaseWidth + SegWidth;
if X < NextSegStart then
Result := ApproxSeg
else
Result := ApproxSeg + 1;
end;
end;
procedure TJvTFDays.EditAppt(Col: Integer; Appt: TJvTFAppt);
var
Schedule: TJvTFSched;
ApptRect, EditorRect: TRect;
// EditHeightThreshold, EditWidthThreshold: Integer;
FailEditor: Boolean;
PicsHeight, PicsWidth, FrameOffset: Integer;
DrawList: TList;
CanDrawText, CanDrawPics: Boolean;
DrawInfo: TJvTFDaysApptDrawInfo;
AllowEdit: Boolean;
begin
FEditor.QuickCreate := False;
EnsureCol(Col);
Schedule := Cols[Col].Schedule;
if not Assigned(Schedule) or not Assigned(Appt) or
not (agoEditing in Options) or not CanEdit then
Exit;
AllowEdit := True;
if Assigned(FOnBeginEdit) then
FOnBeginEdit(Self, Appt, AllowEdit);
if not AllowEdit then
Exit;
DrawInfo := TJvTFDaysApptDrawInfo.Create;
try
GetApptDrawInfo(DrawInfo, Appt, SelApptAttr);
FrameOffset := DrawInfo.FrameWidth div 2 * 2;
Canvas.Font := DrawInfo.Font;
FEditor.Font := DrawInfo.Font;
FEditor.Color := DrawInfo.Color;
finally
DrawInfo.Free;
end;
ApptRect := GetApptRect(Col, Appt);
InflateRect(ApptRect, -FrameOffset, -FrameOffset);
if ApptBar.Visible then
Inc(ApptRect.Left, ApptBar.Width);
AdjustForMargins(ApptRect);
DrawList := TList.Create;
try
CreatePicDrawList(ApptRect, Appt, DrawList);
FilterPicDrawList(ApptRect, DrawList, PicsHeight, PicsWidth);
CanDrawWhat(Canvas, ApptRect, PicsHeight, CanDrawText, CanDrawPics);
finally
ClearPicDrawList(DrawList);
DrawList.Free;
end;
if CanDrawPics then
Inc(ApptRect.Left, PicsHeight);
IntersectRect(EditorRect{%H-}, GetDataAreaRect, ApptRect);
// Commented out by Tim - No longer required since no editor failure.
// EditHeightThreshold := CanvasMaxTextHeight(Canvas) * Thresholds.EditHeight;
// EditWidthThreshold := Canvas.TextWidth('Bi') div 2 * Thresholds.EditWidth;
// Commented out by Tim - The editor should no longer ever fail.
// FailEditor := (RectHeight(EditorRect) < EditHeightThreshold) or
// (RectWidth(EditorRect) < EditWidthThreshold);
FailEditor := False;
if FailEditor then
begin
if Assigned(FOnFailEditor) then
FOnFailEditor(Self, Col, Appt, EditorRect, FailEditor);
if not FailEditor then
FEditor.BorderStyle := bsSingle;
end
else
FEditor.BorderStyle := bsNone;
if not FailEditor then
with FEditor do
begin
FEditor.LinkedAppt := Appt;
BoundsRect := EditorRect;
if agoFormattedDesc in Options then
Text := Appt.Description
else
Text := StripCRLF(Appt.Description);
Self.Update; // not calling update here increases flicker
Visible := True;
if not (csDesigning in ComponentState) and CanFocus then
SetFocus;
SelLength := 0;
SelStart := 0;
end;
end;
procedure TJvTFDays.FinishEditAppt;
begin
if Assigned(FEditor.LinkedAppt) then
FEditor.LinkedAppt.Description := FEditor.Text;
FEditor.Visible := False;
end;
function TJvTFDays.Editing: Boolean;
begin
Result := (FEditor <> nil) and FEditor.Visible;
end;
function TJvTFDays.CanEdit: Boolean;
begin
Result := agoShowText in Options;
end;
function TJvTFDays.RowsPerHour: Integer;
begin
Result := 60 div Granularity;
end;
function TJvTFDays.RowCount: Integer;
var
Adjustment, H, M, S, MS: Word;
WorkTime: TTime;
begin
WorkTime := GridEndTime;
DecodeTime(WorkTime, H, M, S, MS);
Adjustment := 0;
if (H = 0) and (M = 0) then
begin
WorkTime := EncodeTime(23, 59, 59, 999);
Adjustment := 1;
end;
//DecodeTime(GridEndTime - GridStartTime, H, M, S, MS);
DecodeTime(WorkTime - GridStartTime, H, M, S, MS);
Result := (H * 60 + M) div Granularity + Adjustment;
end;
function TJvTFDays.PossVisibleRows: Integer;
var
DataHt: Integer;
begin
//group DataHt := GetAdjClientRect.Bottom - ColHdrHeight;
DataHt := GetAdjClientRect.Bottom - CalcGroupColHdrsHeight;
Result := DataHt div RowHeight;
if DataHt mod RowHeight <> 0 then
Inc(Result);
end;
function TJvTFDays.VisibleRows: Integer;
begin
Result := Lesser(PossVisibleRows, RowCount - TopRow);
end;
function TJvTFDays.FullVisibleRows: Integer;
var
Poss, Vis: Integer;
begin
Poss := PossVisibleRows;
Vis := VisibleRows;
if Poss = Vis then
if GetDataHeight mod RowHeight = 0 then
Result := Vis
else
Result := Vis - 1
else
Result := Vis;
end;
function TJvTFDays.VisibleCols: Integer;
var
DataWidth, ColNum, TempColWidths: Integer;
begin
if Cols.Count > 0 then
begin
// Calc the width of the data area
DataWidth := GetDataWidth;
// loop through cols until sum of col widths is >= width of data area
TempColWidths := 0;
ColNum := LeftCol;
repeat
Inc(TempColWidths, Cols[ColNum].Width);
Inc(ColNum);
until (TempColWidths >= DataWidth) or (ColNum = Cols.Count);
Result := ColNum - LeftCol;
end
else
Result := 0;
end;
function TJvTFDays.FullVisibleCols: Integer;
var
I, lRightCol, TempWidth: Integer;
begin
// sum the widths of all visible cols
lRightCol := LeftCol + VisibleCols - 1;
TempWidth := 0;
for I := LeftCol to lRightCol do
Inc(TempWidth, Cols[I].Width);
// if TempWidth > Data width then fully vis cols = one less the visible cols
if TempWidth <= GetDataWidth then
Result := VisibleCols
else
Result := VisibleCols - 1;
end;
function TJvTFDays.RowToTime(RowNum: Integer): TTime;
var
TotalMins: Integer;
WorkHours, WorkMins: Word;
H, M, S, MS: Word;
Offset: Integer;
begin
EnsureRow(RowNum);
DecodeTime(GridStartTime, H, M, S, MS);
Offset := H * 60 + M;
TotalMins := RowNum * Granularity + Offset;
WorkHours := TotalMins div 60;
WorkMins := TotalMins mod 60;
if WorkHours < 24 then
Result := EncodeTime(WorkHours, WorkMins, 0, 0)
else
Result := EncodeTime(23, 59, 59, 999);
end;
function TJvTFDays.TimeToRow(ATime: TTime): Integer;
var
TotalMins: Integer;
WorkHours, WorkMins, WorkSecs, WorkMSecs: Word;
H, M, S, MS: Word;
Offset: Integer;
begin
DecodeTime(ATime, WorkHours, WorkMins, WorkSecs, WorkMSecs);
// Convert the given time to minutes
DecodeTime(GridStartTime, H, M, S, MS);
Offset := H * 60 + M;
TotalMins := WorkHours * 60 + WorkMins - Offset;
// Find the row number by dividing the time in minutes by the granularity
Result := TotalMins div Granularity;
if (TotalMins < 0) and (TotalMins mod Granularity <> 0) then
Dec(Result);
end;
procedure TJvTFDays.TimeToTop(ATime: TTime);
begin
TopRow := TimeToRow(ATime);
end;
function TJvTFDays.AdjustEndTime(ATime: TTime): TTime;
begin
Result := Frac(Frac(ATime) - Frac(EncodeTime(0, 0, 1, 0)));
end;
function TJvTFDays.RowStartsHour(RowNum: Integer): Boolean;
var
H, M, S, MS: Word;
begin
EnsureRow(RowNum);
DecodeTime(RowToTime(RowNum), H, M, S, MS);
Result := M = 0;
end;
function TJvTFDays.RowEndsHour(RowNum: Integer): Boolean;
var
H, M, S, MS: Word;
TempTime: TTime;
begin
EnsureRow(RowNum);
TempTime := RowToTime(RowNum) + EncodeTime(0, Granularity - 1, 0, 0);
DecodeTime(TempTime, H, M, S, MS);
Result := M = 59;
end;
function TJvTFDays.RowEndTime(RowNum: Integer): TTime;
begin
Result := RowToTime(RowNum) +
Granularity * EncodeTime(0, 1, 0, 0) - EncodeTime(0, 0, 1, 0);
end;
function TJvTFDays.RowToHour(RowNum: Integer): Word;
var
H, M, S, MS: Word;
begin
DecodeTime(RowToTime(RowNum), H, M, S, MS);
Result := H;
end;
function TJvTFDays.HourStartRow(Hour: Word): Integer;
begin
Result := TimeToRow(EncodeTime(Hour, 0, 0, 0));
end;
function TJvTFDays.HourEndRow(Hour: Word): Integer;
begin
Result := TimeToRow(EncodeTime(Hour, 59, 0, 0));
end;
function TJvTFDays.BottomRow: Integer;
begin
Result := TopRow + VisibleRows - 1;
end;
function TJvTFDays.RightCol: Integer;
begin
Result := LeftCol + VisibleCols - 1;
end;
procedure TJvTFDays.DragDrop(Source: TObject; X, Y: Integer);
begin
if Source is TJvTFControl then
DropAppt(TJvTFControl(Source).DragInfo, X, Y);
inherited DragDrop(Source, X, Y);
end;
procedure TJvTFDays.CalcStartEndRows(AAppt: TJvTFAppt; SchedDate: TDate;
out StartRow, EndRow: Integer);
begin
if Trunc(AAppt.StartDate) = Trunc(SchedDate) then
StartRow := TimeToRow(AAppt.StartTime)
else
StartRow := 0;
if Trunc(AAppt.EndDate) = Trunc(SchedDate) then
EndRow := TimeToRow(AdjustEndTime(AAppt.EndTime))
else
EndRow := RowCount - 1;
end;
function TJvTFDays.CurrentDate: TDate;
begin
case Template.ActiveTemplate of
agtLinear:
Result := Template.LinearStartDate;
agtComparative:
Result := Template.CompDate;
end;
end;
procedure TJvTFDays.PrevDate;
begin
case Template.ActiveTemplate of
agtLinear:
Template.LinearStartDate := Template.LinearStartDate - 1;
agtComparative:
Template.CompDate := Template.CompDate - 1;
end;
end;
procedure TJvTFDays.NextDate;
begin
case Template.ActiveTemplate of
agtLinear:
Template.LinearStartDate := Template.LinearStartDate + 1;
agtComparative:
Template.CompDate := Template.CompDate + 1;
end;
end;
procedure TJvTFDays.GotoDate(aDate: TDate);
begin
case Template.ActiveTemplate of
agtLinear:
Template.LinearStartDate := aDate;
agtComparative:
Template.CompDate := aDate;
end;
end;
procedure TJvTFDays.ScrollDays(NumDays: Integer);
var
OldDate: TDate;
CanScroll: Boolean;
begin
CanScroll := True;
OldDate := Template.LinearStartDate;
case Template.ActiveTemplate of
agtLinear:
OldDate := Template.LinearStartDate;
agtComparative:
OldDate := Template.CompDate;
else
CanScroll := False;
end;
if CanScroll then
GotoDate(OldDate + NumDays);
end;
procedure TJvTFDays.ScrollMonths(NumMonths: Integer);
var
OldDate, EOM: TDate;
CanScroll: Boolean;
Y, M, D, EOMY, EOMM, EOMD, DeltaY, DeltaM: Word;
begin
CanScroll := True;
OldDate := Template.LinearStartDate;
case Template.ActiveTemplate of
agtLinear: OldDate := Template.LinearStartDate;
agtComparative: OldDate := Template.CompDate;
else
CanScroll := False;
end;
if CanScroll then
begin
DecodeDate(OldDate, Y, M, D);
DeltaY := NumMonths div 12;
DeltaM := NumMonths mod 12;
M := M + DeltaM;
if M < 1 then
begin
Dec(DeltaY);
M := 12 + M;
end
else
if M > 12 then
begin
Inc(DeltaY);
M := M - 12;
end;
Y := Y + DeltaY;
EOM := EndOfMonth(EncodeDate(Y, M, 1));
DecodeDate(EOM, EOMY, EOMM, EOMD);
D := Lesser(D, EOMD);
GotoDate(EncodeDate(Y, M, D));
end;
end;
procedure TJvTFDays.ScrollYears(NumYears: Integer);
var
OldDate, EOM: TDate;
Y, M, D, EOMY, EOMM, EOMD: Word;
CanScroll: Boolean;
begin
CanScroll := True;
OldDate := Template.LinearStartDate;
case Template.ActiveTemplate of
agtLinear:
OldDate := Template.LinearStartDate;
agtComparative:
OldDate := Template.CompDate;
else
CanScroll := False;
end;
if CanScroll then
begin
DecodeDate(OldDate, Y, M, D);
Inc(Y, NumYears);
EOM := EndOfMonth(EncodeDate(Y, M, 1));
DecodeDate(EOM, EOMY, EOMM, EOMD);
D := Lesser(D, EOMD);
GotoDate(EncodeDate(Y, M, D));
end;
end;
procedure TJvTFDays.ReleaseSchedule(const SchedName: string; SchedDate: TDate);
var
Used: Boolean;
I: Integer;
Col: TJvTFDaysCol;
begin
// Only release schedule if not used by any grid cols
Used := False;
for I := 0 to Cols.Count - 1 do
begin
Col := Cols[I];
if (Col.SchedName = SchedName) and
(Trunc(Col.SchedDate) = Trunc(SchedDate)) and Col.Connected then
Used := True and not (csDestroying in ScheduleManager.ComponentState);
end;
if not Used then
inherited ReleaseSchedule(SchedName, SchedDate);
end;
procedure TJvTFDays.RowInView(ARow: Integer);
begin
EnsureRow(ARow);
if ARow < TopRow then
TopRow := ARow
else
if ARow > TopRow + FullVisibleRows - 1 then
TopRow := Greater(ARow - FullVisibleRows + 1, 0);
end;
procedure TJvTFDays.ColInView(ACol: Integer);
var
I, ColSizes: Integer;
DataWidth: Integer;
begin
EnsureCol(ACol);
if ACol < LeftCol then
LeftCol := ACol
else
if ACol > RightCol then
begin
ColSizes := 0;
DataWidth := RectWidth(GetDataAreaRect);
I := ACol + 1;
while (ColSizes < DataWidth) and (I >= 0) do
begin
Dec(I);
Inc(ColSizes, Cols[I].Width);
end;
LeftCol := I + 1;
end;
end;
function TJvTFDays.CellIsSelected(ACell: TPoint): Boolean;
var
SelSameName, SelSameDate: Boolean;
NameList: TStringList;
I, TestStart, TestEnd: Integer;
TestDate: TDate;
function PointInDataArea(APoint: TPoint): Boolean;
begin
Result := (APoint.X > gcHdr) and (APoint.Y > gcHdr);
end;
begin
Result := False;
if PointInDataArea(SelStart) and PointInDataArea(SelEnd) and PointInDataArea(ACell) then
begin
SelSameName := Cols[SelStart.X].SchedName = Cols[SelEnd.X].SchedName;
SelSameDate := Trunc(Cols[SelStart.X].SchedDate) =
Trunc(Cols[SelEnd.X].SchedDate);
if SelSameName and SelSameDate then
begin
if (Cols[ACell.X].SchedName = Cols[SelStart.X].SchedName) and
(Trunc(Cols[ACell.X].SchedDate) = Trunc(Cols[SelStart.X].SchedDate)) then
Result := (ACell.Y >= SelStart.Y) and (ACell.Y <= SelEnd.Y)
end
else
if SelSameName then
begin
if Cols[ACell.X].SchedName = Cols[SelStart.X].SchedName then
begin
TestDate := Cols[ACell.X].SchedDate;
if Trunc(TestDate) = Trunc(Cols[SelStart.X].SchedDate) then
Result := ACell.Y >= SelStart.Y
else
if (Trunc(TestDate) > Trunc(Cols[SelStart.X].SchedDate)) and
(Trunc(TestDate) < Trunc(Cols[SelEnd.X].SchedDate)) then
Result := True
else
if Trunc(TestDate) = Trunc(Cols[SelEnd.X].SchedDate) then
Result := ACell.Y <= SelEnd.Y;
end
end
else
if SelSameDate then
begin
NameList := TStringList.Create;
NameList.Sorted := True;
NameList.Duplicates := dupIgnore;
try
for I := SelStart.X to SelEnd.X do
NameList.Add(Cols[I].SchedName);
if (NameList.IndexOf(Cols[ACell.X].SchedName) > -1) and
(Trunc(Cols[SelStart.X].SchedDate) = Trunc(Cols[ACell.X].SchedDate)) then
begin
TestStart := Lesser(SelStart.Y, SelEnd.Y);
TestEnd := Greater(SelStart.Y, SelEnd.Y);
Result := (ACell.Y >= TestStart) and (ACell.Y <= TestEnd);
end;
finally
NameList.Free;
end;
end;
end;
end;
function TJvTFDays.ColIsSelected(ACol: Integer): Boolean;
var
SelSameName, SelSameDate: Boolean;
I: Integer;
StartCol, EndCol, TestCol: TJvTFDaysCol;
begin
Result := False;
if (SelStart.X > gcHdr) and (SelEnd.X > gcHdr) then
// Don't know if we really should be doing the follow check
//and (ACol >= SelStart.X) and (ACol <= SelEnd.X) then
begin
// Determine type of selection (case)
StartCol := Cols[SelStart.X];
EndCol := Cols[SelEnd.X];
TestCol := Cols[ACol];
SelSameName := StartCol.SchedName = EndCol.SchedName;
SelSameDate := Trunc(StartCol.SchedDate) = Trunc(EndCol.SchedDate);
if SelSameName and SelSameDate then
Result := (TestCol.SchedName = StartCol.SchedName) and
(Trunc(TestCol.SchedDate) = Trunc(StartCol.SchedDate))
else
if SelSameName then
Result := (TestCol.SchedName = StartCol.SchedName) and
(Trunc(TestCol.SchedDate) >= Trunc(StartCol.SchedDate)) and
(Trunc(TestCol.SchedDate) <= Trunc(EndCol.SchedDate))
else
if SelSameDate then
if Trunc(TestCol.SchedDate) = Trunc(StartCol.SchedDate) then
begin
I := SelStart.X;
while (I <= SelEnd.X) and not Result do
if TestCol.SchedName = Cols[I].SchedName then
Result := True
else
Inc(I);
end;
end;
end;
function TJvTFDays.RowIsSelected(ARow: Integer): Boolean;
var
SelSameName, SelSameDate: Boolean;
StartCol, EndCol: TJvTFDaysCol;
begin
Result := False;
if (SelStart.Y > gcHdr) and (SelEnd.Y > gcHdr) and
(SelStart.X > gcHdr) and (SelEnd.X > gcHdr) then
begin
StartCol := Cols[SelStart.X];
EndCol := Cols[SelEnd.X];
SelSameName := StartCol.SchedName = EndCol.SchedName;
SelSameDate := Trunc(StartCol.SchedDate) = Trunc(EndCol.SchedDate);
if (SelSameName and SelSameDate) or SelSameDate then
Result := (ARow >= SelStart.Y) and (ARow <= SelEnd.Y)
else
if SelSameName then
Result := (ARow >= SelStart.Y) or (ARow <= SelEnd.Y);
end;
end;
procedure TJvTFDays.ClearSelection;
begin
SelStart := Point(-1, -1);
end;
function TJvTFDays.ValidSelection: Boolean;
begin
Result := (SelStart.X > gcHdr) and (SelStart.Y > gcHdr) and
(SelEnd.X > gcHdr) and (SelEnd.Y > gcHdr);
end;
function TJvTFDays.EnumSelCells: TDynPointArray;
var
SelSameName, SelSameDate: Boolean;
NameList: TStringList;
NextEntry, ACol, ARow: Integer;
TestDate: TDate;
procedure AddToArray(X, Y: Integer);
begin
Result[NextEntry] := Point(X, Y);
Inc(NextEntry);
end;
procedure BumpLength(Bump: Integer);
begin
SetLength(Result, Length(Result) + Bump);
end;
begin
SetLength(Result, 0);
NextEntry := 0;
// EXIT IF NOTHING SELECTED
if (SelStart.X <= gcHdr) or (SelStart.Y <= gcHdr) or
(SelEnd.X <= gcHdr) or (SelEnd.Y <= gcHdr) then
Exit;
SelSameName := Cols[SelStart.X].SchedName = Cols[SelEnd.X].SchedName;
SelSameDate := Trunc(Cols[SelStart.X].SchedDate) =
Trunc(Cols[SelEnd.X].SchedDate);
if SelSameName and SelSameDate then
for ACol := 0 to Cols.Count - 1 do
begin
if (Cols[ACol].SchedName = Cols[SelStart.X].SchedName) and
(Trunc(Cols[ACol].SchedDate) = Trunc(Cols[SelStart.X].SchedDate)) then
begin
BumpLength(SelEnd.Y - SelStart.Y + 1);
for ARow := SelStart.Y to SelEnd.Y do
AddToArray(ACol, ARow);
end;
end
else
if SelSameName then
// only have to go to SelEnd.X??
// What about if two cols have same SchedName and SchedDate??
for ACol := 0 to Cols.Count - 1 do
begin
if Cols[ACol].SchedName = Cols[SelStart.X].SchedName then
begin
TestDate := Cols[ACol].SchedDate;
if Trunc(TestDate) = Trunc(Cols[SelStart.X].SchedDate) then
begin
BumpLength(RowCount - SelStart.Y);
for ARow := SelStart.Y to RowCount - 1 do
AddToArray(ACol, ARow);
end
else
if (Trunc(TestDate) > Trunc(Cols[SelStart.X].SchedDate)) and
(Trunc(TestDate) < Trunc(Cols[SelEnd.X].SchedDate)) then
begin
BumpLength(RowCount);
for ARow := 0 to RowCount - 1 do
AddToArray(ACol, ARow);
end
else
if Trunc(TestDate) = Trunc(Cols[SelEnd.X].SchedDate) then
begin
BumpLength(SelEnd.Y + 1);
for ARow := 0 to SelEnd.Y do
AddToArray(ACol, ARow);
end;
end;
end
else
if SelSameDate then
begin
NameList := TStringList.Create;
NameList.Sorted := True;
NameList.Duplicates := dupIgnore;
TestDate := Cols[SelStart.X].SchedDate;
try
for ACol := SelStart.X to SelEnd.X do
NameList.Add(Cols[ACol].SchedName);
for ACol := 0 to Cols.Count - 1 do
if (NameList.IndexOf(Cols[ACol].SchedName) > -1) and
(Trunc(Cols[ACol].SchedDate) = Trunc(TestDate)) then
begin
BumpLength(SelEnd.Y - SelStart.Y + 1);
for ARow := SelStart.Y to SelEnd.Y do
AddToArray(ACol, ARow);
end;
finally
NameList.Free;
end;
end;
end;
function TJvTFDays.EnumSelCols: TDynIntArray;
var
SelSameName, SelSameDate: Boolean;
I: Integer;
TempList: TStringList;
StartCol, EndCol, TestCol: TJvTFDaysCol;
procedure AddToArray(ACol: Integer);
begin
SetLength(Result, Length(Result) + 1);
Result[Length(Result) - 1] := ACol;
end;
begin
SetLength(Result, 0);
if (SelStart.X > gcHdr) and (SelEnd.X > gcHdr) then
begin
StartCol := Cols[SelStart.X];
EndCol := Cols[SelEnd.X];
SelSameName := StartCol.SchedName = EndCol.SchedName;
SelSameDate := Trunc(StartCol.SchedDate) = Trunc(EndCol.SchedDate);
if SelSameName and SelSameDate then
for I := 0 to Cols.Count - 1 do
begin
TestCol := Cols[I];
if (TestCol.SchedName = StartCol.SchedName) and
(Trunc(TestCol.SchedDate) = Trunc(StartCol.SchedDate)) then
AddToArray(I);
end
else
if SelSameName then
for I := 0 to Cols.Count - 1 do
begin
TestCol := Cols[I];
if (TestCol.SchedName = StartCol.SchedName) and
((Trunc(TestCol.SchedDate) >= Trunc(StartCol.SchedDate)) and
(Trunc(TestCol.SchedDate) <= Trunc(EndCol.SchedDate))) then
AddToArray(I);
end
else
if SelSameDate then
begin
TempList := TStringList.Create;
TempList.Sorted := True;
TempList.Duplicates := dupIgnore;
try
for I := SelStart.X to SelEnd.X do
TempList.Add(Cols[I].SchedName);
for I := 0 to Cols.Count - 1 do
begin
TestCol := Cols[I];
if (Trunc(TestCol.SchedDate) = Trunc(StartCol.SchedDate)) and
(TempList.IndexOf(TestCol.SchedName) > -1) then
AddToArray(I);
end;
finally
TempList.Free;
end;
end;
end;
end;
function TJvTFDays.EnumSelRows: TDynIntArray;
var
SelSameName, SelSameDate: Boolean;
StartCol, EndCol: TJvTFDaysCol;
I: Integer;
procedure AddToArray(ACol: Integer);
begin
SetLength(Result, Length(Result) + 1);
Result[Length(Result) - 1] := ACol;
end;
begin
SetLength(Result, 0);
if (SelStart.Y > gcHdr) and (SelEnd.Y > gcHdr) and
(SelStart.X > gcHdr) and (SelEnd.X > gcHdr) then
begin
StartCol := Cols[SelStart.X];
EndCol := Cols[SelEnd.X];
SelSameName := StartCol.SchedName = EndCol.SchedName;
SelSameDate := Trunc(StartCol.SchedDate) = Trunc(EndCol.SchedDate);
if (SelSameName and SelSameDate) or SelSameDate then
for I := SelStart.Y to SelEnd.Y do
AddToArray(I)
else
if SelSameName then
for I := 0 to RowCount - 1 do
if (I >= SelStart.Y) or (I <= SelEnd.Y) then
AddToArray(I);
end;
end;
function TJvTFDays.GetApptDispColor(Appt: TJvTFAppt; Selected: Boolean): TColor;
begin
if Selected then
if SelApptAttr.Color = clDefault then
if Appt.Color = clDefault then
Result := ApptAttr.Color
else
Result := Appt.Color
else
Result := SelApptAttr.Color
else
if Appt.Color = clDefault then
Result := ApptAttr.Color
else
Result := Appt.Color;
end;
procedure TJvTFDays.ReqSchedNotification(Schedule: TJvTFSched);
var
I: Integer;
Col: TJvTFDaysCol;
begin
inherited ReqSchedNotification(Schedule);
for I := 0 to Cols.Count - 1 do
begin
Col := Cols[I];
if (Col.SchedName = Schedule.SchedName) and
(Trunc(Col.SchedDate) = Trunc(Schedule.SchedDate)) then
Col.Connect;
end;
end;
procedure TJvTFDays.SelFirstAppt;
var
FirstAppt: TJvTFAppt;
RefCol: Integer;
begin
RefCol := 0;
FirstAppt := nil;
while not Assigned(FirstAppt) and (RefCol < Cols.Count) do
begin
FirstAppt := Cols[RefCol].GetFirstAppt;
Inc(RefCol);
end;
if Assigned(FirstAppt) then
begin
SelAppt := FirstAppt;
// The actual Reference Col will be one less than RefCol coming out of
// the above loop.
ApptInView(FirstAppt, RefCol - 1);
SelApptCell(FirstAppt, RefCol - 1);
end;
end;
procedure TJvTFDays.SelLastAppt;
var
LastAppt: TJvTFAppt;
RefCol: Integer;
begin
RefCol := Cols.Count - 1;
LastAppt := nil;
while not Assigned(LastAppt) and (RefCol > -1) do
begin
LastAppt := Cols[RefCol].GetLastAppt;
Dec(RefCol);
end;
if Assigned(LastAppt) then
begin
SelAppt := LastAppt;
ApptInView(LastAppt, RefCol + 1);
SelApptCell(LastAppt, RefCol + 1);
end;
{
if Cols.Count > 0 then
LastAppt := Cols[Cols.Count - 1].GetLastAppt;
if not Assigned(LastAppt) and (Cols.Count > 1) then
begin
RefCol := Cols.Count - 2;
while not Assigned(LastAppt) and (RefCol >= 0) do
begin
LastAppt := Cols[RefCol].GetLastAppt;
Dec(RefCol);
end;
if Assigned(LastAppt) then
Inc(RefCol);
end;
SelAppt := LastAppt;
ApptInView(LastAppt, RefCol);
SelApptCell(LastAppt, RefCol);
}
end;
procedure TJvTFDays.SelNextAppt;
var
RefAppt, NextAppt: TJvTFAppt;
RefCol: Integer;
begin
RefAppt := SelAppt;
RefCol := FocusedCol;
if RefCol < 0 then
RefCol := 0;
NextAppt := nil;
while not Assigned(NextAppt) and (RefCol < Cols.Count) do
begin
NextAppt := Cols[RefCol].GetNextAppt(RefAppt);
Inc(RefCol);
end;
if Assigned(NextAppt) then
begin
SelAppt := NextAppt;
ApptInView(NextAppt, RefCol - 1);
SelApptCell(NextAppt, RefCol - 1);
end;
{
RefAppt := SelAppt;
RefCol := Greater(FocusedCol, 0);
if Assigned(RefAppt) then
NextAppt := Cols[RefCol].GetNextAppt(RefAppt)
else
NextAppt := Cols[RefCol].GetFirstAppt;
if not Assigned(NextAppt) then
begin
NextCol := RefCol + 1;
if NextCol = Cols.Count then
NextCol := 0;
while not Assigned(NextAppt) and (NextCol <> RefCol) do
begin
NextAppt := Cols[NextCol].GetFirstAppt;
if not Assigned(NextAppt) then
begin
Inc(NextCol);
if NextCol = Cols.Count then
NextCol := 0;
end;
end;
RefCol := NextCol;
end;
SelAppt := NextAppt;
ApptInView(NextAppt, RefCol);
SelApptCell(NextAppt, RefCol);
}
end;
procedure TJvTFDays.SelPrevAppt;
var
RefAppt, PrevAppt: TJvTFAppt;
RefCol: Integer;
begin
RefAppt := SelAppt;
RefCol := FocusedCol;
if RefCol < 0 then
RefCol := Cols.Count - 1;
PrevAppt := nil;
while not Assigned(PrevAppt) and (RefCol > -1) do
begin
PrevAppt := Cols[RefCol].GetPrevAppt(RefAppt);
Dec(RefCol);
end;
if Assigned(PrevAppt) then
begin
SelAppt := PrevAppt;
ApptInView(PrevAppt, RefCol + 1);
SelApptCell(PrevAppt, RefCol + 1);
end;
{
if Assigned(RefAppt) then
PrevAppt := Cols[RefCol].GetPrevAppt(RefAppt)
else
PrevAppt := Cols[RefCol].GetFirstAppt;
if not Assigned(PrevAppt) then
begin
PrevCol := RefCol - 1;
if PrevCol = -1 then
PrevCol := Cols.Count - 1;
while not Assigned(PrevAppt) and (PrevCol <> RefCol) do
begin
PrevAppt := Cols[PrevCol].GetLastAppt;
if not Assigned(PrevAppt) then
begin
Dec(PrevCol);
if PrevCol = -1 then
PrevCol := Cols.Count - 1;
end;
end;
RefCol := PrevCol;
end;
SelAppt := PrevAppt;
ApptInView(PrevAppt, RefCol);
SelApptCell(PrevAppt, RefCol);
}
end;
procedure TJvTFDays.ApptInView(AAppt: TJvTFAppt; ACol: Integer);
var
StartRow, EndRow: Integer;
begin
if Assigned(AAppt) and Assigned(Cols[ACol].Schedule) then
begin
CalcStartEndRows(AAppt, Cols[ACol].Schedule.SchedDate, StartRow, EndRow);
RowInView(StartRow);
ColInView(ACol);
//TopRow := StartRow;
//LeftCol := ACol;
end;
end;
procedure TJvTFDays.SelApptCell(AAppt: TJvTFAppt; ACol: Integer);
var
StartRow, EndRow: Integer;
begin
if Assigned(AAppt) and Assigned(Cols[ACol].Schedule) and
(Cols[ACol].Schedule.ApptByID(AAppt.ID) <> nil) then
begin
CalcStartEndRows(AAppt, Cols[ACol].Schedule.SchedDate, StartRow, EndRow);
SelStart := Point(ACol, StartRow);
FocusedCol := ACol;
FocusedRow := StartRow;
end;
end;
procedure TJvTFDays.SetGrouping(Value: TJvTFDaysGrouping);
var
CheckSB: Boolean;
begin
if Value <> FGrouping then
begin
CheckSB := (Value = grNone) or (FGrouping = grNone);
FGrouping := Value;
Cols.UpdateTitles;
if CheckSB then
begin
AlignScrollBars;
if not (csLoading in ComponentState) then
begin
CheckSBVis;
CheckSBParams;
end;
end;
Invalidate;
end;
end;
{
procedure TJvTFDays.SetGroupTitles;
var
I: Integer;
begin
Case Grouping of
grNone :
For I := 0 to Cols.Count - 1 do
begin
Cols[I].GroupTitle := '';
//Cols[I].UpdateTitle;
Cols[I].UpdateTitles;
end;
grDate :
For I := 0 to Cols.Count - 1 do
begin
Cols[I].GroupTitle := FormatDateTime(DateFormat, Cols[I].SchedDate);
Cols[I].Title := Cols[I].SchedName;
end;
grResource :
For I := 0 to Cols.Count - 1 do
begin
Cols[I].GroupTitle := Cols[I].SchedName;
Cols[I].Title := FormatDateTime(DateFormat, Cols[I].SchedDate);
end;
grCustom :
For I := 0 to Cols.Count - 1 do
begin
Cols[I].GroupTitle := '';
end;
end;
end;
}
procedure TJvTFDays.SetTFHintProps(Value: TJvTFHintProps);
begin
FHintProps.Assign(Value);
end;
procedure TJvTFDays.DrawDither(ACanvas: TCanvas; ARect: TRect;
Color1, Color2: TColor);
var
DitherBitmap: TBitmap;
I, J: Integer;
begin
DitherBitmap := TBitmap.Create;
try
// create dithered bitmap
DitherBitmap.Width := 8;
DitherBitmap.Height := 8;
for I := 0 to DitherBitmap.Width - 1 do
for J := 0 to DitherBitmap.Height - 1 do
if (I + J) mod 2 = 0 then
DitherBitmap.Canvas.Pixels[I, J] := Color1
else
DitherBitmap.Canvas.Pixels[I, J] := Color2;
ACanvas.Brush.Bitmap := DitherBitmap;
ACanvas.FillRect(ARect);
finally
DitherBitmap.Free;
end;
end;
procedure TJvTFDays.SelFirstApptNextCol;
var
FirstAppt: TJvTFAppt;
RefCol: Integer;
begin
RefCol := FocusedCol + 1;
FirstAppt := nil;
while not Assigned(FirstAppt) and (RefCol < Cols.Count) do
begin
FirstAppt := Cols[RefCol].GetFirstAppt;
Inc(RefCol);
end;
if Assigned(FirstAppt) then
begin
SelAppt := FirstAppt;
// The actual Reference Col will be one less than RefCol coming out of
// the above loop.
ApptInView(FirstAppt, RefCol - 1);
SelApptCell(FirstAppt, RefCol - 1);
end;
end;
procedure TJvTFDays.SelFirstApptPrevCol;
var
FirstAppt: TJvTFAppt;
RefCol: Integer;
begin
if Cols.Count = 0 then
Exit;
RefCol := FocusedCol - 1;
if RefCol < 0 then
RefCol := 0;
FirstAppt := nil;
while not Assigned(FirstAppt) and (RefCol > -1) do
begin
FirstAppt := Cols[RefCol].GetFirstAppt;
Dec(RefCol);
end;
if Assigned(FirstAppt) then
begin
SelAppt := FirstAppt;
ApptInView(FirstAppt, RefCol + 1);
SelApptCell(FirstAppt, RefCol + 1);
end;
end;
procedure TJvTFDays.SetGroupHdrHeight(Value: Integer);
begin
if Value > RectHeight(GetAdjClientRect) then
Value := RectHeight(GetAdjClientRect);
if Value < 0 then
Value := 0;
if Value <> FGroupHdrHeight then
begin
FGroupHdrHeight := Value;
AlignScrollBars;
if not (csLoading in ComponentState) then
begin
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
end;
function TJvTFDays.IsStoredGroupHdrHeight: Boolean;
begin
Result := FGroupHdrHeight <> Scale96ToFont(DEFAULT_GROUP_HDR_HEIGHT);
end;
procedure TJvTFDays.DrawGroupHdrs(ACanvas: TCanvas);
var
CurrGroup: string;
I: Integer;
begin
if (CalcGroupHdrHeight > 0) and (Cols.Count > 0) then
begin
CurrGroup := Cols[LeftCol].GroupTitle;
DrawColGroupHdr(ACanvas, LeftCol, True);
for I := LeftCol + 1 to RightCol do
if Cols[I].GroupTitle <> CurrGroup then
begin
CurrGroup := Cols[I].GroupTitle;
DrawColGroupHdr(ACanvas, I, True);
end;
end;
end;
function TJvTFDays.CalcGroupColHdrsHeight: Integer;
begin
Result := CalcGroupHdrHeight + ColHdrHeight;
end;
function TJvTFDays.CalcGroupHdrHeight: Integer;
begin
if Grouping = grNone then
Result := 0
else
Result := GroupHdrHeight;
end;
function TJvTFDays.VirtualGroupHdrRect(Col: Integer): TRect;
var
GroupStartCol: Integer = -1; // to silence the compiler
GroupEndCol: Integer = -1; // dto.
I, GroupWidth: Integer;
begin
EnsureCol(Col);
Result.Top := 0;
Result.Bottom := CalcGroupHdrHeight;
GetGroupStartEndCols(Col, GroupStartCol, GroupEndCol);
GroupWidth := 0;
for I := GroupStartCol to GroupEndCol do
Inc(GroupWidth, Cols[I].Width);
{$IFDEF Jv_TIMEBLOCKS}
// ok
Result.Left := CalcBlockRowHdrsWidth;
{$ELSE}
// remove
//Result.Left := RowHdrWidth;
{$ENDIF Jv_TIMEBLOCKS}
// At most, only one of the following For loops will execute
// depending on whether Col is to the left or to the right of LeftCol
for I := LeftCol - 1 downto GroupStartCol do
Dec(Result.Left, Cols[I].Width);
for I := LeftCol to GroupStartCol - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + GroupWidth;
end;
procedure TJvTFDays.GetGroupStartEndCols(Col: Integer;
var StartCol, EndCol: Integer);
var
I: Integer;
begin
EnsureCol(Col);
// find group start col
I := Col;
while (I >= 0) and (Cols[I].GroupTitle = Cols[Col].GroupTitle) do
begin
StartCol := I;
Dec(I);
end;
// find group end col
I := Col;
while (I < Cols.Count) and (Cols[I].GroupTitle = Cols[Col].GroupTitle) do
begin
EndCol := I;
Inc(I);
end;
end;
(*
procedure TJvTFDays.DrawGroupHdr(ACanvas: TCanvas; ACol: Integer);
var
ARect: TRect;
Attr: TJvTFDaysHdrAttr;
begin
ARect := VirtualGroupHdrRect(ACol);
if GroupHdrIsSelected(ACol) then
Attr := SelGroupHdrAttr
else
Attr := GroupHdrAttr;
With ACanvas do
begin
Font.Assign(Attr.Font);
Brush.Color := Attr.Color;
FillRect(ARect);
{
Brush.Color := clWhite;
FillRect(ARect);
Pen.Color := clBlack;
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom - 1);
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Left, ARect.Bottom - 1);
}
{
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom - 1);
LineTo(ARect.Left, ARect.Bottom - 1);
}
{ end;
end;
*)
procedure TJvTFDays.SetGroupHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FGroupHdrAttr.Assign(Value);
Invalidate;
end;
procedure TJvTFDays.SetSelGroupHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FSelGroupHdrAttr.Assign(Value);
Invalidate;
end;
function TJvTFDays.GroupHdrIsSelected(ACol: Integer): Boolean;
var
I: Integer;
GroupStartCol: Integer = -1; // to silence the compiler
GroupEndCol: Integer = -1; // dto.
begin
GetGroupStartEndCols(ACol, GroupStartCol, GroupEndCol);
Result := False;
I := GroupStartCol;
while (I <= GroupEndCol) and not Result do
begin
if ColIsSelected(I) then
Result := True;
Inc(I);
end;
end;
procedure TJvTFDays.DrawColGroupHdr(ACanvas: TCanvas; Index: Integer;
IsGroupHdr: Boolean);
var
ARect, TxtRect, CalcRect, TxtBounds: TRect;
Txt: string;
PTxt: PChar;
UseAttr: TJvTFDaysHdrAttr;
Flags: UINT;
TxtHt, TxtRectHt: Integer;
begin
if IsGroupHdr then
begin
ARect := VirtualGroupHdrRect(Index);
ARect.Left := Greater(ARect.Left, GetDataAreaRect.Left);
Txt := Copy(Cols[Index].GroupTitle, 1, Length(Cols[Index].GroupTitle));
if GroupHdrIsSelected(Index) then
UseAttr := SelGroupHdrAttr
else
UseAttr := GroupHdrAttr;
end
else
begin
ARect := CellRect(Index, -1);
//Txt := Copy(Cols[Index].Title, 1, Length(Cols[Index].Title));
Txt := Copy(Cols[Index].Title, 1, Length(Cols[Index].Title));
if ColIsSelected(Index) then
UseAttr := SelHdrAttr
else
UseAttr := HdrAttr;
end;
ACanvas.Brush.Color := UseAttr.Color;
ACanvas.Font.Assign(UseAttr.Font);
Flags := DT_NOPREFIX or DT_CENTER;
case ColTitleStyle of
ctsSingleClip:
Flags := Flags or DT_SINGLELINE or DT_VCENTER;
ctsSingleEllipsis:
Flags := Flags or DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER;
ctsMultiClip:
Flags := Flags or DT_WORDBREAK;
ctsMultiEllipsis:
Flags := Flags or DT_END_ELLIPSIS or DT_WORDBREAK or DT_EDITCONTROL;
ctsHide:
Flags := Flags or DT_SINGLELINE or DT_VCENTER;
end;
ACanvas.FillRect(ARect);
TxtRect := ARect;
InflateRect(TxtRect, -2, -2);
CalcRect := TxtRect;
// Allocate length of Txt + 4 chars
// (1 char for null terminator, 3 chars for ellipsis)
// Ahh, what the hell. Allocate + dozen chars for good measure.
// (This is continuing to give me problems and I don't know why.)
//PTxt := StrAlloc((Length(Txt) + 4) * SizeOf(Char));
PTxt := StrAlloc((Length(Txt) + 12) * SizeOf(Char));
try
StrPCopy(PTxt, Txt);
if (ColTitleStyle = ctsMultiClip) or (ColTitleStyle = ctsMultiEllipsis) then
begin
TxtHt := DrawText(ACanvas.Handle, PTxt, -1, CalcRect,
Flags or DT_CALCRECT);
// "reset" PTxt
StrPCopy(PTxt, Txt);
if TxtHt < RectHeight(TxtRect) then
begin
// we need to vertically center the text
TxtRectHt := RectHeight(TxtRect);
TxtRect.Top := TxtRect.Top + RectHeight(TxtRect) div 2 - TxtHt div 2;
TxtRect.Bottom := Lesser(TxtRect.Top + TxtRectHt, TxtRect.Bottom);
end;
end
else
if ColTitleStyle = ctsHide then
begin
DrawText(ACanvas.Handle, PTxt, -1, CalcRect, Flags or DT_CALCRECT);
if RectWidth(CalcRect) > RectWidth(TxtRect) then
StrPCopy(PTxt, '');
end
{$IFDEF Jv_TIMEBLOCKS}
// okay to leave
else
if ColTitleStyle = ctsRotated then
//DrawAngleText(ACanvas, TxtRect, UseAttr.TitleRotation, Txt);
DrawAngleText(ACanvas, TxtRect, TxtBounds, UseAttr.TitleRotation,
taCenter, vaCenter, Txt);
{$ELSE}
// remove
//; // semi-colon needed to terminate last end
{$ENDIF Jv_TIMEBLOCKS}
{$IFDEF Jv_TIMEBLOCKS}
// okay to leave
if ColTitleStyle <> ctsRotated then
DrawText(ACanvas.Handle, PTxt, -1, TxtRect, Flags);
{$ELSE}
// remove
//Windows.DrawText(ACanvas.Handle, PTxt, -1, TxtRect, Flags);
{$ENDIF Jv_TIMEBLOCKS}
finally
StrDispose(PTxt);
end;
if not IsGroupHdr and (Index = FocusedCol) and Focused then
begin
CalcRect := ARect;
InflateRect(CalcRect, -2, -2);
ManualFocusRect(ACanvas, CalcRect);
{
if Windows.IsRectEmpty(TxtRect) then
Windows.InflateRect(TxtRect, 5, 5);
ManualFocusRect(ACanvas, TxtRect);
}
end;
{$IFDEF Jv_TIMEBLOCKS}
// okay to leave
DrawFrame(ACanvas, ARect, UseAttr.Frame3D, UseAttr.FrameColor);
{$ELSE}
// remove
//DrawFrame(ACanvas, ARect, UseAttr.Frame3D);
{$ENDIF Jv_TIMEBLOCKS}
if IsGroupHdr then
begin
if Assigned(FOnDrawGroupHdr) then
FOnDrawGroupHdr(Self, ACanvas, ARect, Index, GroupHdrIsSelected(Index));
end
else
if Assigned(FOnDrawColHdr) then
FOnDrawColHdr(Self, ACanvas, ARect, Index, ColIsSelected(Index));
end;
{$IFDEF Jv_TIMEBLOCKS}
// ok
procedure TJvTFDays.SetTimeBlocks(Value: TJvTFDaysTimeBlocks);
begin
FTimeBlocks.Assign(Value);
end;
procedure TJvTFDays.SetTimeBlockProps(Value: TJvTFDaysBlockProps);
begin
FTimeBlockProps.Assign(Value);
end;
procedure TJvTFDays.SetWeekend(Value: TTFDaysOfWeek);
begin
if Value <> FWeekend then
begin
FWeekend := Value;
Invalidate;
end;
end;
procedure TJvTFDays.SetWeekendColor(Value: TColor);
begin
if Value <> FWeekendColor then
begin
FWeekendColor := Value;
UpdateWeekendFillPic;
Invalidate;
end;
end;
procedure TJvTFDays.UpdateWeekendFillPic;
begin
FWeekendFillPic.Canvas.Brush.Color := WeekendColor;
FWeekendFillPic.Canvas.FillRect(Classes.Rect(0, 0, FWeekendFillPic.Width,
FWeekendFillPic.Height));
end;
procedure TJvTFDays.DrawBlockHdr(ACanvas: TCanvas; BlockIndex: Integer);
var
StartRow: Integer = -1;
EndRow: Integer = -1;
ARect, HdrPicRect, TxtBounds: TRect;
ClipIt: Boolean;
Attr: TJvTFDaysHdrAttr;
TimeBlock: TJvTFDaysTimeBlock;
HdrPic: TBitmap;
begin
TimeBlock := TimeBlocks[BlockIndex];
GetTimeBlockStartEnd(BlockIndex, StartRow, EndRow);
//ARect := VirtualBlockHdrRect(StartRow);
ARect := CellRect(gcGroupHdr, StartRow);
HdrPicRect := VirtualBlockHdrRect(StartRow);
ClipIt := HdrPicRect.Top < ARect.Top;
OffsetRect(HdrPicRect, -HdrPicRect.Left, -HdrPicRect.Top);
HdrPic := TBitmap.Create;
try
HdrPic.Width := RectWidth(HdrPicRect);
HdrPic.Height := RectHeight(HdrPicRect);
if BlockHdrIsSelected(StartRow) then
Attr := TimeBlockProps.SelBlockHdrAttr
else
Attr := TimeBlockProps.BlockHdrAttr;
//With ACanvas do
with HdrPic.Canvas do
begin
Brush.Color := Attr.Color;
FillRect(HdrPicRect);
Font.Assign(Attr.Font);
//DrawAngleText(HdrPic.Canvas, HdrPicRect, Attr.TitleRotation,
//TimeBlock.Title);
DrawAngleText(HdrPic.Canvas, HdrPicRect, TxtBounds, Attr.TitleRotation,
taCenter, vaCenter, TimeBlock.Title);
if Attr.Frame3D then
DrawFrame(HdrPic.Canvas, HdrPicRect, True, Attr.FrameColor)
else
begin
Pen.Color := Attr.FrameColor;
MoveTo(HdrPicRect.Right - 1, HdrPicRect.Top);
LineTo(HdrPicRect.Right - 1, HdrPicRect.Bottom);
MoveTo(HdrPicRect.Left, HdrPicRect.Bottom - 1);
LineTo(HdrPicRect.Right, HdrPicRect.Bottom - 1);
end;
end;
if ClipIt then
HdrPicRect.Top := HdrPicRect.Bottom - RectHeight(ARect);
BitBlt(ACanvas.Handle, ARect.Left, ARect.Top, RectWidth(ARect),
RectHeight(ARect), HdrPic.Canvas.Handle, 0, HdrPicRect.Top, SRCCOPY);
finally
HdrPic.Free;
end;
end;
procedure TJvTFDays.FillBlockHdrDeadSpace(ACanvas: TCanvas);
var
ARect: TRect;
StartRow: Integer = -1;
EndRow: Integer = -1;
procedure FillIt;
begin
with ACanvas do
begin
//Brush.Color := TimeBlockProps.BlockHdrAttr.Color;
Brush.Color := TimeBlockProps.OffTimeColor;
FillRect(ARect);
Pen.Color := TimeBlockProps.BlockHdrAttr.FrameColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
end;
end;
begin
if TimeBlocks.Count = 0 then
Exit;
ARect.Left := 0;
ARect.Right := CalcBlockHdrWidth;
GetTimeBlockStartEnd(0, StartRow, EndRow);
if StartRow > TopRow then
begin
ARect.Top := CalcGroupColHdrsHeight;
ARect.Bottom := Lesser(VirtualBlockHdrRect(StartRow).Top,
GetDataAreaRect.Bottom);
FillIt;
end;
GetTimeBlockStartEnd(TimeBlocks.Count - 1, StartRow, EndRow);
if EndRow < BottomRow then
begin
ARect.Top := Greater(VirtualBlockHdrRect(EndRow).Bottom,
GetDataAreaRect.Top);
ARect.Bottom := GetDataAreaRect.Bottom;
FillIt;
end;
end;
//////////////////////////////////////////////////////////////////
// Credit for the CalcTextPos routine goes to Joerg Lingner. //
// It comes from his JLLabel component (freeware - Torry's). //
// It is used here with his permission. Thanks Joerg! //
// He can be reached at jlingner att t-online dott de //
//////////////////////////////////////////////////////////////////
{
procedure TJvTFDays.CalcTextPos(var ARect: TRect; aAngle: Integer;
aTxt: string);
//==========================================================================
// Calculate text pos. depend. on: Font, Escapement, Alignment and length
//--------------------------------------------------------------------------
var
DC : HDC;
hSavFont: HFont;
Size : TSize;
x,y : Integer;
cStr : array [0..255] of Char;
SaveRect: TRect;
begin
aAngle := aAngle div 10;
SaveRect := ARect;
StrPCopy(cStr, aTxt);
DC := GetDC(HWND_DESKTOP);
hSavFont := SelectObject(DC, Font.Handle);
GetTextExtentPoint32(DC, cStr, Length(aTxt), Size);
SelectObject(DC, hSavFont);
ReleaseDC(HWND_DESKTOP, DC);
x := 0;
y := 0;
if aAngle<=90 then
begin // 1.Quadrant
x := 0;
y := Trunc(Size.cx * sin(aAngle*Pi/180));
end
else
if aAngle<=180 then
begin // 2.Quadrant
x := Trunc(Size.cx * -cos(aAngle*Pi/180));
y := Trunc(Size.cx * sin(aAngle*Pi/180) + Size.cy * cos((180-aAngle)*Pi/180));
end
else
if aAngle<=270 then
begin // 3.Quadrant
x := Trunc(Size.cx * -cos(aAngle*Pi/180) + Size.cy * sin((aAngle-180)*Pi/180));
y := Trunc(Size.cy * sin((270-aAngle)*Pi/180));
end
else
if aAngle<=360 then
begin // 4.Quadrant
x := Trunc(Size.cy * sin((360-aAngle)*Pi/180));
y := 0;
end;
ARect.Top := ARect.Top + y;
ARect.Left := ARect.Left + x;
x := Abs(Trunc(Size.cx * cos(aAngle*Pi/180))) + Abs(Trunc(Size.cy * sin(aAngle*Pi/180)));
y := Abs(Trunc(Size.cx * sin(aAngle*Pi/180))) + Abs(Trunc(Size.cy * cos(aAngle*Pi/180)));
//Mike:
ARect.Left := ARect.Left + ((RectWidth(SaveRect) - X) div 2); // align center
//ARect.Left := ARect.Left + RectWidth(SaveRect) - X; // align right
ARect.Top := ARect.Top + ((RectHeight(SaveRect) - Y) div 2); // align center
//ARect.Top := ARect.Top + RectHeight(SaveRect) - Y; // align bottom
end;
}
{
procedure TJvTFDays.DrawAngleText(ACanvas: TCanvas; ARect: TRect;
aAngle: Integer; aTxt: string);
var
LogFont: TLogFont;
TxtRect: TRect;
Flags: UINT;
PTxt: PChar;
ClipRgn: HRgn;
begin
TxtRect := ARect;
CalcTextPos(TxtRect, aAngle, aTxt);
Windows.GetObject(ACanvas.Font.Handle, SizeOf(LogFont), @LogFont);
LogFont.lfEscapement := aAngle;
LogFont.lfOrientation := LogFont.lfEscapement;
ACanvas.Font.Handle := CreateFontIndirect(LogFont);
Flags := DT_NOPREFIX or DT_LEFT or DT_TOP or DT_NOCLIP or DT_SINGLELINE;
PTxt := StrAlloc((Length(aTxt) + 4) * SizeOf(Char));
StrPCopy(PTxt, aTxt);
ClipRgn := Windows.CreateRectRgn(ARect.Left, ARect.Top,
ARect.Right, ARect.Bottom);
Windows.SelectClipRgn(ACanvas.Handle, ClipRgn);
Windows.DrawText(ACanvas.Handle, PTxt, -1, TxtRect, Flags);
Windows.SelectClipRgn(ACanvas.Handle, 0);
Windows.DeleteObject(ClipRgn);
StrDispose(PTxt);
ACanvas.Font.Handle := 0;
end;
}
procedure TJvTFDays.EnsureBlockRules(GridGran, BlockGran: Integer;
DayStart: TTime);
var
GridHrs, GridMins, BlockHrs, BlockMins, S, MS: Word;
RowStartTime: TTime;
begin
if TimeBlocks.Count > 0 then
begin
if GridGran > BlockGran then
raise EJvTFBlockGranError.CreateRes(@RsEGridGranularityCannotBeGreater);
if (BlockGran mod GridGran) <> 0 then
raise EJvTFBlockGranError.CreateRes(@RsETimeBlockGranularityMustBeEvenly);
DecodeTime(DayStart, BlockHrs, BlockMins, S, MS);
RowStartTime := RowToTime(TimeToRow(DayStart));
DecodeTime(RowStartTime, GridHrs, GridMins, S, MS);
if (BlockHrs <> GridHrs) or (BlockMins <> GridMins) then
raise EJvTFBlockGranError.CreateRes(@RsETimeBlocksMustBeginExactlyOn);
end;
end;
function TJvTFDays.ValidateBlockRules(GridGran, BlockGran: Integer;
DayStart: TTime): Boolean;
var
GridHrs, GridMins, BlockHrs, BlockMins, S, MS: Word;
RowStartTime: TTime;
begin
Result := True;
if TimeBlocks.Count > 0 then
begin
if GridGran > BlockGran then
Result := False;
if (BlockGran mod GridGran) <> 0 then
Result := False;
DecodeTime(DayStart, BlockHrs, BlockMins, S, MS);
RowStartTime := RowToTime(TimeToRow(DayStart));
DecodeTime(RowStartTime, GridHrs, GridMins, S, MS);
if (BlockHrs <> GridHrs) or (BlockMins <> GridMins) then
Result := False;
end;
end;
function TJvTFDays.RowToTimeBlock(ARow: Integer): Integer;
var
I: Integer;
BlockStart: Integer = -1;
BlockEnd: Integer = -1;
begin
Result := -1;
if TimeBlocks.Count = 0 then
Exit;
I := 0;
repeat
GetTimeBlockStartEnd(I, BlockStart, BlockEnd);
if (BlockStart <= ARow) and (ARow <= BlockEnd) then
Result := I;
Inc(I);
until (I = TimeBlocks.Count) or (Result <> -1);
end;
procedure TJvTFDays.GetTimeBlockStartEnd(ATimeBlock: Integer;
out BlockStart, BlockEnd: Integer);
var
I: Integer;
begin
if ATimeBlock < 0 then
begin
BlockStart := -1;
BlockEnd := -1;
Exit;
end;
BlockStart := TimeToRow(TimeBlockProps.DayStart);
I := 0;
while (I < ATimeBlock) do
begin
//Inc(BlockStart, TimeBlocks[I].Length);
Inc(BlockStart, TimeBlocks[I].GridLength);
Inc(I);
end;
//BlockEnd := BlockStart + TimeBlocks[ATimeBlock].Length - 1;
BlockEnd := BlockStart + TimeBlocks[ATimeBlock].GridLength - 1;
end;
function TJvTFDays.CalcBlockHdrWidth: Integer;
begin
if TimeBlocks.Count > 0 then
Result := TimeBlockProps.BlockHdrWidth
else
Result := 0;
end;
function TJvTFDays.CalcBlockRowHdrsWidth: Integer;
begin
Result := CalcBlockHdrWidth + RowHdrWidth;
end;
procedure TJvTFDays.GetBlockStartEndRows(Row: Integer;
out StartRow, EndRow: Integer);
begin
GetTimeBlockStartEnd(RowToTimeBlock(Row), StartRow, EndRow);
end;
function TJvTFDays.VirtualBlockHdrRect(Row: Integer): TRect;
var
BlockStartRow: Integer = -1;
BlockEndRow: Integer = -1;
BlockHeight: Integer;
begin
EnsureRow(Row);
Result.Left := 0;
Result.Right := CalcBlockHdrWidth;
GetBlockStartEndRows(Row, BlockStartRow, BlockEndRow);
BlockHeight := (BlockEndRow - BlockStartRow + 1) * RowHeight;
Result.Top := CalcGroupColHdrsHeight + ((BlockStartRow - TopRow) * RowHeight);
Result.Bottom := Result.Top + BlockHeight;
end;
function TJvTFDays.IsWeekend(ColIndex: Integer): Boolean;
begin
Result := BorlToDOW(DayOfWeek(Cols[ColIndex].SchedDate)) in Weekend;
end;
function TJvTFDays.BlockHdrIsSelected(ARow: Integer): Boolean;
var
I: Integer;
StartRow: Integer = -1;
EndRow: Integer = -1;
begin
GetBlockStartEndRows(ARow, StartRow, EndRow);
Result := False;
I := StartRow;
while (I <= EndRow) and not Result do
begin
if RowIsSelected(I) then
Result := True;
Inc(I);
end;
end;
procedure TJvTFDays.DrawFrame(ACanvas: TCanvas; ARect: TRect; Draw3D: Boolean;
FrameColour: TColor);
var
OldPenColor: TColor;
begin
with ACanvas, ARect do
begin
OldPenColor := Pen.Color;
if Draw3D then
Pen.Color := clBtnShadow
else
Pen.Color := FrameColour;
MoveTo(Right - 1, Top);
LineTo(Right - 1, Bottom);
MoveTo(Left, Bottom - 1);
LineTo(Right, Bottom - 1);
if Draw3D then
begin
Pen.Color := clBtnHighlight;
MoveTo(Left, Top);
LineTo(Right, Top);
MoveTo(Left, Top);
LineTo(Left, Bottom);
end;
Pen.Color := OldPenColor;
end;
end;
{$ENDIF Jv_TIMEBLOCKS}
procedure TJvTFDays.SetGridEndTime(Value: TTime);
var
I, NewTopRow: Integer;
TopTime: TTime;
WorkEnd: TTime;
H, M, S, MS: Word;
begin
WorkEnd := Value;
DecodeTime(WorkEnd, H, M, S, MS);
if (H = 0) and (M = 0) then
WorkEnd := EncodeTime(23, 59, 59, 999);
if not (csLoading in ComponentState) and (WorkEnd <= GridStartTime) then
raise EJvTFDaysError.CreateRes(@RsEGridEndTimeCannotBePriorToGridStart);
TopTime := RowToTime(TopRow);
FGridEndTime := Value;
ClearSelection;
if not (csLoading in ComponentState) then
begin
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
//TopRow := TimeToRow(TopTime);
if RowCount <= PossVisibleRows then
TopRow := 0
else
begin
if TopTime < GridStartTime then
NewTopRow := 0
else
NewTopRow := TimeToRow(TopTime);
TopRow := Lesser(NewTopRow, RowCount - 1 - VisibleRows + 1);
end;
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
procedure TJvTFDays.SetGridStartTime(Value: TTime);
var
I, NewTopRow: Integer;
TopTime: TTime;
WorkEnd: TTime;
H, M, S, MS: Word;
begin
WorkEnd := GridEndTime;
DecodeTime(WorkEnd, H, M, S, MS);
if (H = 0) and (M = 0) then
WorkEnd := EncodeTime(23, 59, 59, 999);
if not (csLoading in ComponentState) and (Value >= WorkEnd) then
raise EJvTFDaysError.CreateRes(@RsEGridStartTimeCannotBeAfterGridEndTi);
TopTime := RowToTime(TopRow);
FGridStartTime := Value;
ClearSelection;
if not (csLoading in ComponentState) then
begin
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
//TopRow := TimeToRow(TopTime);
if RowCount <= PossVisibleRows then
TopRow := 0
else
begin
if TopTime < GridStartTime then
NewTopRow := 0
else
NewTopRow := TimeToRow(TopTime);
TopRow := Lesser(NewTopRow, RowCount - 1 - VisibleRows + 1);
end;
CheckSBVis;
CheckSBParams;
Invalidate;
end;
end;
procedure TJvTFDays.WMTimer(var Msg: TLMTimer);
var
I, TempWidth: Integer;
PtInfo: TJvTFDaysCoord;
OldTopRow, OldLeftCol: Integer;
X, Y: Integer;
begin
if Cols.Count = 0 then
Exit;
OldTopRow := TopRow;
OldLeftCol := LeftCol;
case FAutoScrollDir of
asdUp:
TopRow := Greater(TopRow - 1, 0);
asdDown:
TopRow := Lesser(TopRow + 1, RowCount - FullVisibleRows);
asdLeft:
LeftCol := Greater(LeftCol - 1, 0);
asdRight:
begin
TempWidth := 0;
for I := LeftCol to Cols.Count - 1 do
Inc(TempWidth, Cols[I].Width);
if TempWidth > GetDataWidth then
LeftCol := LeftCol + 1;
end;
end;
if (FAutoScrollDir <> asdNowhere) and
((TopRow <> OldTopRow) or (LeftCol <> OldLeftCol)) then
begin
X := FMouseMovePt.X;
Y := FMouseMovePt.Y;
if State <> agsMoveAppt then
MouseMove(FMouseMoveState, X, Y);
Update;
PtInfo := PtToCell(FMouseMovePt.X, FMouseMovePt.Y);
if Y >= GetDataAreaRect.Bottom then
PtInfo.Row := Lesser(BottomRow + 1, RowCount - 1);
if State = agsSizeAppt then
begin
DrawDrag(PtInfo, nil, False);
ContinueDragging(PtInfo, nil);
end
else
if State = agsMoveAppt then
begin
DrawDrag(PtInfo, FDragInfo.Appt, False);
FDraggingCoord.Row := PtInfo.Row;
end;
end;
end;
procedure TJvTFDays.KillAutoScrollTimer;
begin
if FLiveTimer then
begin
FLiveTimer := False;
KillTimer(Handle, 1);
end;
end;
procedure TJvTFDays.Navigate(AControl: TJvTFControl;
SchedNames: TStringList; Dates: TJvTFDateList);
var
I, J: Integer;
ACol: TJvTFDaysCol;
begin
inherited Navigate(AControl, SchedNames, Dates);
if not Template.IgnoreNav and (Dates.Count > 0) then
case Template.ActiveTemplate of
agtLinear:
Template.LinearStartDate := Dates[0];
agtComparative:
Template.CompDate := Dates[0];
agtNone:
begin
Cols.BeginUpdate;
try
Cols.Clear;
if Grouping = grDate then
for I := 0 to Dates.Count - 1 do
for J := 0 to SchedNames.Count - 1 do
begin
ACol := Cols.Add;
ACol.SchedName := SchedNames[J];
ACol.SchedDate := Dates[I];
end
else
for I := 0 to SchedNames.Count - 1 do
for J := 0 to Dates.Count - 1 do
begin
ACol := Cols.Add;
ACol.SchedName := SchedNames[I];
ACol.SchedDate := Dates[J];
end;
finally
Cols.EndUpdate;
end;
end;
end;
end;
{
procedure TJvTFDays.ReorderCols;
var
NewList: TStringList;
I, Slot: Integer;
ColToAdd: TJvTFDaysCol;
function SortCompare: Boolean;
var
CurrCol: TJvTFDaysCol;
begin
CurrCol := TJvTFDaysCol(NewList.Objects[Slot]);
if Grouping = grDate then
Result := Trunc(CurrCol.SchedDate) > Trunc(ColToAdd.SchedDate)
else
if Grouping = grResource then
Result := CurrCol.SchedName > ColToAdd.SchedName
else
Result := True;
end;
begin
NewList := TStringList.Create;
Try
For I := 0 to Cols.Count - 1 do
begin
ColToAdd := Cols[I];
Slot := 0;
while (Slot < NewList.Count) and not SortCompare do
Inc(Slot);
NewList.InsertObject(Slot, '', ColToAdd);
end;
For I := 0 to NewList.Count - 1 do
TJvTFDaysCol(NewList.Objects[I]).Index := I;
Finally
NewList.Free;
end;
end;
}
//procedure TJvTFDays.DoNavigate;
//var
// SchedNameList: TStringList;
// DateList: TJvTFDateList;
// I,
// SMIndex: Integer;
// ACol: TJvTFDaysCol;
//begin
// if not Assigned(Navigator) then
// Exit;
//
// SchedNameList := TStringList.Create;
// DateList := TJvTFDateList.Create;
// try
// for I := 0 to Cols.Count - 1 do
// begin
// ACol := Cols[I];
// if ColIsSelected(I) then
// begin
// SMIndex := SchedNameList.IndexOf(ACol.SchedName);
// if SMIndex = -1 then
// SchedNameList.Add(ACol.SchedName);
// DateList.Add(ACol.SchedDate);
// end;
// end;
//
// Navigator.Navigate(Self, SchedNameList, DateList);
// finally
// SchedNameList.Free;
// DateList.Free;
// end;
//end;
function TJvTFDays.GetTFHintClass: TJvTFHintClass;
begin
Result := TJvTFHint;
end;
procedure TJvTFDays.DoApptHint(GridCoord: TJvTFDaysCoord);
var
ApptRect, VisApptRect: TRect;
begin
if Assigned(GridCoord.Appt) and not Editing and (agoShowApptHints in Options) then
begin
VisApptRect := EmptyRect;
ApptRect := GetApptRect(GridCoord.Col, GridCoord.Appt);
IntersectRect(VisApptRect, ApptRect, GetDataAreaRect);
FHint.ApptHint(GridCoord.Appt, VisApptRect.Left + 2,
VisApptRect.Bottom + 2, True, True,
agoFormattedDesc in Options);
end;
end;
procedure TJvTFDays.DoCellHint(GridCoord: TJvTFDaysCoord);
var
ColHdrRect: TRect;
HintText: string;
begin
if csDesigning in ComponentState then
Exit;
if (GridCoord.Row = -1) and (GridCoord.Col > -1) and (agoShowColHdrHints in Options) then
HintText := Cols[GridCoord.Col].Title
else
HintText := '';
ColHdrRect := CellRect(GridCoord.Col, GridCoord.Row);
FHint.CellHint(GridCoord.Row, GridCoord.Col, HintText, ColHdrRect);
end;
procedure TJvTFDays.GetApptDrawInfo(DrawInfo: TJvTFDaysApptDrawInfo;
AAppt: TJvTFAppt; Attr: TJvTFDaysApptAttr);
begin
DrawInfo.Color := GetApptDispColor(AAppt, AAppt = SelAppt);
DrawInfo.FrameColor := Attr.FrameColor;
DrawInfo.FrameWidth := Attr.FrameWidth;
DrawInfo.Font := Attr.Font;
DrawInfo.Visible := True;
if Assigned(FOnGetApptDrawInfo) then
FOnGetApptDrawInfo(Self, AAppt, DrawInfo);
end;
// move grab handles
//function TJvTFDays.GetBottomGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
//begin
// Result := Classes.Rect(0, 0, 0, 0);
// if (Col = FocusedCol) and (Col > gcHdr) and Assigned(Appt) and
// Cols[Col].ApptInCol(Appt) then
// begin
// Result := GetApptRect(Col, Appt);
// Result.Top := Result.Bottom - GrabHandles.Height;
// Windows.OffsetRect(Result, 0, GrabHandles.Height);
// end;
//end;
//
//// move grab handles
//function TJvTFDays.GetTopGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
//begin
// Result := Classes.Rect(0, 0, 0, 0);
// if (Col = FocusedCol) and (Col > gcHdr) and Assigned(Appt) and
// Cols[Col].ApptInCol(Appt) then
// begin
// Result := GetApptRect(Col, Appt);
// Result.Bottom := Result.Top + GrabHandles.Height;
// Windows.OffsetRect(Result, 0, -GrabHandles.Height);
// end;
//end;
// move grab handles
function TJvTFDays.GetBottomGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
begin
Result := Classes.Rect(0, 0, 0, 0);
// if (Col = FocusedCol) and (Col > gcHdr) and Assigned(Appt) and
if (Col > gcHdr) and Assigned(Appt) and Cols[Col].ApptInCol(Appt) then
begin
Result := GetApptRect(Col, Appt);
Result.Top := Result.Bottom - GrabHandles.Height;
OffsetRect(Result, 0, GrabHandles.Height);
end;
end;
// move grab handles
function TJvTFDays.GetTopGrabHandleRect(Col: Integer; Appt: TJvTFAppt): TRect;
begin
Result := Classes.Rect(0, 0, 0, 0);
// if (Col = FocusedCol) and (Col > gcHdr) and Assigned(Appt) and
if (Col > gcHdr) and Assigned(Appt) and Cols[Col].ApptInCol(Appt) then
begin
Result := GetApptRect(Col, Appt);
Result.Bottom := Result.Top + GrabHandles.Height;
OffsetRect(Result, 0, -GrabHandles.Height);
end;
end;
function TJvTFDays.PtInBottomHandle(APoint: TPoint; Col: Integer;
Appt: TJvTFAppt): Boolean;
var
HandleRect: TRect;
begin
Result := False;
// move grab handles
if Assigned(Appt) and Cols[Col].ApptInCol(Appt) then
begin
HandleRect := GetBottomGrabHandleRect(Col, Appt);
Result := PtInRect(HandleRect, APoint) and
(agoSizeAppt in Options);
end;
end;
function TJvTFDays.PtInTopHandle(APoint: TPoint; Col: Integer;
Appt: TJvTFAppt): Boolean;
var
HandleRect: TRect;
begin
Result := False;
// move grab handles
if Assigned(Appt) and Cols[Col].ApptInCol(Appt) then
begin
HandleRect := GetTopGrabHandleRect(Col, Appt);
Result := PtInRect(HandleRect, APoint) and
(agoMoveAppt in Options);
end;
end;
procedure TJvTFDays.SetDitheredBackground(const Value: Boolean);
begin
FDitheredBackground := Value;
Refresh;
end;
procedure TJvTFDays.SetShowFocus(const Value: Boolean);
begin
if FShowFocus <> Value then
begin
FShowFocus := Value;
Invalidate;
end;
end;
class function TJvTFDays.GetControlClassDefaultSize: TSize;
begin
Result.CX := 500;
Result.CY := 300;
end;
//=== { TJvTFDaysPrinter } ===================================================
constructor TJvTFDaysPrinter.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FGroupHdrHeight := 25;
FPageInfoList := TStringList.Create;
FApptAttr := TJvTFDaysApptAttr.Create(nil);
FApptBar := TJvTFDaysApptBar.Create(nil);
FCols := TJvTFDaysCols.CreateForPrinter(Self);
FFancyRowHdrAttr := TJvTFDaysFancyRowHdrAttr.Create(nil);
FHdrAttr := TJvTFDaysHdrAttr.Create(nil);
FGroupHdrAttr := TJvTFDaysHdrAttr.Create(nil);
FPrimeTime := TJvTFDaysPrimeTime.Create(nil);
FThresholds := TJvTFDaysThresholds.Create(nil);
end;
destructor TJvTFDaysPrinter.Destroy;
begin
FCols.Free;
FApptAttr.Free;
FApptBar.Free;
FFancyRowHdrAttr.Free;
FHdrAttr.Free;
FGroupHdrAttr.Free;
FPrimeTime.Free;
FThresholds.Free;
// ClearPageInfo *MUST* be called here. FreeDoc will not call ClearPageInfo
// since we are freeing FPageInfoList here and the inherited Destroy calls
// FreeDoc. (That call to FreeDoc would call ClearPageInfo AFTER
// FPageInfoList has been destroyed.)
ClearPageInfo;
FPageInfoList.Free;
FPageInfoList := nil;
inherited Destroy;
end;
function TJvTFDaysPrinter.AdjustEndTime(ATime: TTime): TTime;
begin
Result := Frac(Frac(ATime) - Frac(EncodeTime(0, 0, 1, 0)));
end;
procedure TJvTFDaysPrinter.CalcPageColInfo(ShowRowHdrs: Boolean;
out CalcColsPerPage, CalcColWidth: Integer);
var
DataWidth, TargetColsPerPage: Integer;
begin
// Calculate the cols per page
if DaysPageLayout.ColsPerPage = 0 then
TargetColsPerPage := Cols.Count
else
TargetColsPerPage := DaysPageLayout.ColsPerPage;
DataWidth := GetDataWidth(ShowRowHdrs);
if TargetColsPerPage > 0 then
begin
CalcColWidth := DataWidth div TargetColsPerPage;
CalcColWidth := Greater(CalcColWidth, MinColWidth);
CalcColsPerPage := DataWidth div CalcColWidth;
end
else
begin
CalcColsPerPage := 1;
CalcColWidth := DataWidth;
end;
end;
procedure TJvTFDaysPrinter.CalcPageInfo;
var
Segments: TStringList;
lPageInfo, SegmentInfo: TJvTFDaysPageInfo;
WorkRowHeight, WorkRowsPerPage, WorkColWidth, WorkColsPerPage: Integer;
CurrRow, CurrCol, I, WorkEndCol: Integer;
WorkShowRowHdr: Boolean;
begin
// ALL MEASUREMENTS ARE ASSUMED TO BE IN PIXELS !!
ClearPageInfo;
// Calculate the segments
// A segment is concerned with rows only (if all rows fit on one page then
// there is one segment. if the rows fit on two pages then there are two
// segments...)
Segments := TStringList.Create;
try
// create the segments
CurrRow := 0;
while CurrRow < RowCount do
begin
lPageInfo := TJvTFDaysPageInfo.Create;
Segments.AddObject('', lPageInfo);
with lPageInfo do
begin
PageNum := Segments.Count;
StartRow := CurrRow;
ShowColHdr := (CurrRow = 0) or DaysPageLayout.AlwaysShowColHdr;
CalcPageRowInfo(ShowColHdr, WorkRowsPerPage, WorkRowHeight);
EndRow := Lesser(CurrRow + WorkRowsPerPage - 1, RowCount - 1);
RowHeight := WorkRowHeight;
end;
CurrRow := lPageInfo.EndRow + 1;
end;
// create the pages
CurrCol := 0;
while CurrCol < Cols.Count do
begin
WorkShowRowHdr := (CurrCol = 0) or DaysPageLayout.AlwaysShowRowHdr;
CalcPageColInfo(WorkShowRowHdr, WorkColsPerPage, WorkColWidth);
WorkEndCol := CurrCol + WorkColsPerPage - 1;
WorkEndCol := Lesser(WorkEndCol, Cols.Count - 1);
for I := 0 to Segments.Count - 1 do
begin
SegmentInfo := TJvTFDaysPageInfo(Segments.Objects[I]);
lPageInfo := TJvTFDaysPageInfo.Create;
FPageInfoList.AddObject('', lPageInfo);
with lPageInfo do
begin
PageNum := FPageInfoList.Count;
StartRow := SegmentInfo.StartRow;
EndRow := SegmentInfo.EndRow;
RowHeight := SegmentInfo.RowHeight;
ShowColHdr := SegmentInfo.ShowColHdr;
StartCol := CurrCol;
EndCol := WorkEndCol;
ColWidth := WorkColWidth;
ShowRowHdr := WorkShowRowHdr;
end;
end;
CurrCol := WorkEndCol + 1;
end;
finally
// clean up the segments
while Segments.Count > 0 do
begin
Segments.Objects[0].Free;
Segments.Delete(0);
end;
Segments.Free;
FValidPageInfo := True;
end;
end;
procedure TJvTFDaysPrinter.CalcPageRowInfo(ShowColHdrs: Boolean;
out CalcRowsPerPage, CalcRowHeight: Integer);
var
DataHeight, TargetRowsPerPage: Integer;
begin
// Calculate the rows per page
if DaysPageLayout.RowsPerPage = 0 then
TargetRowsPerPage := RowCount
else
TargetRowsPerPage := DaysPageLayout.RowsPerPage;
DataHeight := GetDataHeight(ShowColHdrs);
CalcRowHeight := DataHeight div TargetRowsPerPage;
CalcRowHeight := Greater(CalcRowHeight, MinRowHeight);
CalcRowsPerPage := DataHeight div CalcRowHeight;
end;
procedure TJvTFDaysPrinter.CalcStartEndRows(AAppt: TJvTFAppt;
SchedDate: TDate; out StartRow, EndRow: Integer);
begin
if Trunc(AAppt.StartDate) = Trunc(SchedDate) then
StartRow := TimeToRow(AAppt.StartTime)
else
StartRow := 0;
if Trunc(AAppt.EndDate) = Trunc(SchedDate) then
EndRow := TimeToRow(AdjustEndTime(AAppt.EndTime))
else
EndRow := RowCount - 1;
end;
procedure TJvTFDaysPrinter.CanDrawWhat(ACanvas: TCanvas; ApptRect: TRect;
PicsHeight, PicsWidth: Integer; out CanDrawText, CanDrawPics: Boolean);
var
TextHeightThreshold, TextWidthThreshold: Integer;
begin
TextHeightThreshold := ACanvas.TextHeight('Wq') * Thresholds.TextHeight;
TextWidthThreshold := ACanvas.TextWidth('Bi') div 2 * Thresholds.TextWidth;
if TextHeightThreshold < RectHeight(ApptRect) then
begin
CanDrawText := RectWidth(ApptRect) >= TextWidthThreshold;
CanDrawPics := True;
end
else
if Thresholds.DropTextFirst then
begin
CanDrawText := False;
CanDrawPics := True;
if Thresholds.WholePicsOnly then
if PicsHeight > RectHeight(ApptRect) then
CanDrawPics := False;
end
else
begin
CanDrawText := (RectHeight(ApptRect) >= TextHeightThreshold) and
(RectWidth(ApptRect) >= TextWidthThreshold);
CanDrawPics := False;
end;
if not ShowPics then
CanDrawPics := False;
if not ShowText then
CanDrawText := False;
end;
function TJvTFDaysPrinter.CellRect(Col, Row: Integer;
PageInfo: TJvTFDaysPageInfo): TRect;
var
VisGrpHdrRect: TRect;
begin
Result := EmptyRect;
if (Row = gcGroupHdr) and (Col > gcHdr) then
begin
VisGrpHdrRect := Classes.Rect(RowHdrWidth, 0,
RowHdrWidth + GetDataWidth(PageInfo.ShowRowHdr),
CalcGroupHdrHeight);
IntersectRect(Result, VisGrpHdrRect,
VirtualGroupHdrRect(Col, PageInfo));
end
else
if Col < 0 then // Row hdr
if Row < 0 then
// origin cell
if PageInfo.ShowColHdr and PageInfo.ShowRowHdr then
//group Result := Classes.Rect(0, 0, RowHdrWidth, ColHdrHeight)
Result := Classes.Rect(0, 0, RowHdrWidth, CalcGroupColHdrsHeight)
else
Result := EmptyRect
else
if (Row >= PageInfo.StartRow) and (Row <= PageInfo.EndRow) then
// Row Hdr for visible data row
if PageInfo.ShowRowHdr then
begin
Result.Left := 0;
if PageInfo.ShowColHdr then
//group Result.Top := ColHdrHeight
Result.Top := CalcGroupColHdrsHeight
else
Result.Top := 0;
Result.Top := Result.Top + (Row - PageInfo.StartRow) * PageInfo.RowHeight;
Result.Right := RowHdrWidth;
Result.Bottom := Result.Top + PageInfo.RowHeight;
end
else
Result := EmptyRect
else
// Row Hdr for non-visible data row
Result := EmptyRect
else
if (Col >= PageInfo.StartCol) and (Col <= PageInfo.EndCol) then
// visible data col
if Row < 0 then
// Col hdr for visible data col
if PageInfo.ShowColHdr then
begin
if PageInfo.ShowRowHdr then
Result.Left := RowHdrWidth
else
Result.Left := 0;
Inc(Result.Left, PageInfo.ColWidth * (Col - PageInfo.StartCol));
Result.Right := Result.Left + PageInfo.ColWidth;
{ variable width columns, leave for future reference
For I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
}
//group Result.Top := 0;
Result.Top := CalcGroupHdrHeight;
//group Result.Bottom := ColHdrHeight;
Result.Bottom := Result.Top + ColHdrHeight;
end
else
Result := EmptyRect
else
if (Row >= PageInfo.StartRow) and (Row <= PageInfo.EndRow) then
// visible data cell
begin
if PageInfo.ShowRowHdr then
Result.Left := RowHdrWidth
else
Result.Left := 0;
Inc(Result.Left, PageInfo.ColWidth * (Col - PageInfo.StartCol));
Result.Right := Result.Left + PageInfo.ColWidth;
{ variable width cols, leave for future reference
For I := LeftCol to Col - 1 do
Inc(Result.Left, Cols[I].Width);
Result.Right := Result.Left + Cols[Col].Width;
}
if PageInfo.ShowColHdr then
//group Result.Top := ColHdrHeight
Result.Top := CalcGroupColHdrsHeight
else
Result.Top := 0;
Inc(Result.Top, (Row - PageInfo.StartRow) * PageInfo.RowHeight);
Result.Bottom := Result.Top + PageInfo.RowHeight;
end
else
// non-visible data cell (visible col, but non-visible row)
Result := EmptyRect
else // non-visible data col
Result := EmptyRect;
end;
procedure TJvTFDaysPrinter.ClearPageInfo;
begin
if not Assigned(FPageInfoList) then
Exit;
while FPageInfoList.Count > 0 do
begin
FPageInfoList.Objects[0].Free;
FPageInfoList.Delete(0);
end;
FValidPageInfo := False;
end;
procedure TJvTFDaysPrinter.ClearPicDrawList(DrawList: TList);
begin
while DrawList.Count > 0 do
begin
TJvTFDrawPicInfo(DrawList[0]).Free;
DrawList.Delete(0);
end;
end;
procedure TJvTFDaysPrinter.CreateLayout;
begin
FPageLayout := TJvTFDaysPrinterPageLayout.Create(Self);
end;
procedure TJvTFDaysPrinter.CreatePicDrawList(ARect: TRect; Appt: TJvTFAppt;
DrawList: TList);
var
I, NextPicLeft, ImageIndex, PicWidth: Integer;
ImageList: TCustomImageList;
ImageMap: TJvTFStateImageMap;
CustomImageMap: TJvTFCustomImageMap;
procedure AddToList(AImageList: TCustomImageList; AImageIndex: Integer;
APicLeft, APicTop: Integer);
var
DrawInfo: TJvTFDrawPicInfo;
begin
DrawInfo := TJvTFDrawPicInfo.Create;
DrawInfo.ImageList := AImageList;
DrawInfo.ImageIndex := AImageIndex;
DrawInfo.PicLeft := APicLeft;
DrawInfo.PicTop := APicTop;
DrawList.Add(DrawInfo);
end;
begin
NextPicLeft := ARect.Left;
if ShowPics and Assigned(ScheduleManager.CustomImages) then
begin
ImageList := ScheduleManager.CustomImages;
CustomImageMap := Appt.ImageMap;
PicWidth := ScreenToPrinter(ImageList.Width + 2, True);
for I := 0 to CustomImageMap.Count - 1 do
begin
ImageIndex := CustomImageMap[I];
AddToList(ImageList, ImageIndex, NextPicLeft, ARect.Top);
Inc(NextPicLeft, PicWidth);
end;
end;
if ShowPics and Assigned(ScheduleManager.StateImages) then
begin
ImageList := ScheduleManager.StateImages;
PicWidth := ScreenToPrinter(ImageList.Width + 2, True);
ImageMap := ScheduleManager.StateImageMap;
if Appt.AlarmEnabled then
begin
ImageIndex := ImageMap.AlarmEnabled;
if ImageIndex > -1 then
begin
AddToList(ImageList, ImageIndex, NextPicLeft, ARect.Top);
Inc(NextPicLeft, PicWidth);
end
end
else
begin
ImageIndex := ImageMap.AlarmDisabled;
if ImageIndex > -1 then
begin
AddToList(ImageList, ImageIndex, NextPicLeft, ARect.Top);
Inc(NextPicLeft, PicWidth);
end;
end;
ImageIndex := ImageMap.Shared;
if Appt.Shared and (ImageIndex > -1) then
begin
AddToList(ImageList, ImageIndex, NextPicLeft, ARect.Top);
// The following line generates a compiler hint so comment out,
// but leave here as reminder in case method is expanded.
//Inc(NextPicLeft, ImageList.Width + 2);
end;
{ don't show modified pic in printed page
if Appt.Modified and (ImageMap.Modified > -1) then
begin
AddToList(ImageList, ImageMap.Modified, NextPicLeft, ARect.Top);
// The following line generates a compiler hint so comment out,
// but leave here as reminder in case method is expanded.
//Inc(NextPicLeft, ImageList.Width + 2);
end;
}
end;
end;
function TJvTFDaysPrinter.DaysPageLayout: TJvTFDaysPrinterPageLayout;
begin
Result := TJvTFDaysPrinterPageLayout(PageLayout);
end;
{***************************************************************************
* The following routine was based off of a routine originally found in the
* PrinterDemo #1 project of Earl F. Glynn's Computer Lab and is used with
* permission.
* http://www.efg2.com/Lab/OtherProjects/PrinterDemo1.htm
*
* This routine solves a color "washing" problem encountered on some printers.
* It demonstrates the proper use of StretchDIBits. Many thanks to Earl
* for providing the Computer Lab. This solution saved me several hours
* of research and trial and error.
****************************************************************************}
procedure TJvTFDaysPrinter.PrintBitmap(ACanvas: TCanvas; SourceRect,
DestRect: TRect; aBitmap: TBitmap);
{
var
BitmapHeader: pBitmapInfo;
BitmapImage: POINTER;
HeaderSize: LongWord;
ImageSize: LongWord;
}
begin
{ wp --- to do (GetDIBSizes not in LCL)
GetDIBSizes(aBitmap.Handle, HeaderSize, ImageSize);
GetMem(BitmapHeader, HeaderSize);
GetMem(BitmapImage, ImageSize);
try
GetDIB(aBitmap.Handle, aBitmap.Palette, BitmapHeader^, BitmapImage^);
StretchDIBits(ACanvas.Handle,
DestRect.Left, DestRect.Top,
DestRect.Right - DestRect.Left,
DestRect.Bottom - DestRect.Top,
SourceRect.Left, SourceRect.Top,
RectWidth(SourceRect),
RectHeight(SourceRect),
BitmapImage,
TBitmapInfo(BitmapHeader^),
DIB_RGB_COLORS,
SRCCOPY);
finally
FreeMem(BitmapHeader);
FreeMem(BitmapImage)
end;
}
end;
procedure TJvTFDaysPrinter.DrawAppt(ACanvas: TCanvas; Col: Integer;
Appt: TJvTFAppt; StartRow, EndRow: Integer; PageInfo: TJvTFDaysPageInfo);
var
ApptRect, DataRect: TRect;
ClipRgn: HRgn;
begin
ApptRect := GetApptRect(Col, Appt, PageInfo);
if IsRectEmpty(ApptRect) then
Exit;
// Printer bug start, fixed
// Calc the data area rect on the given canvas
if PageInfo.ShowRowHdr then
DataRect.Left := RowHdrWidth
else
DataRect.Left := 0;
if PageInfo.ShowColHdr then
DataRect.Top := CalcGroupColHdrsHeight
else
DataRect.Top := 0;
DataRect.Right := DataRect.Left + BodyWidth;
DataRect.Bottom := DataRect.Top + BodyHeight;
// Need to add BodyLeft and BodyTop to account for ViewPortOrg adjustment
ClipRgn := CreateRectRgn(DataRect.Left + BodyLeft,
DataRect.Top + BodyTop, DataRect.Right + BodyLeft, DataRect.Bottom + BodyTop);
SelectClipRgn(ACanvas.Handle, ClipRgn);
DrawApptDetail(ACanvas, ApptRect, Appt, Col, StartRow, EndRow);
SelectClipRgn(ACanvas.Handle, 0);
DeleteObject(ClipRgn);
// Printer bug end, fixed
end;
function TJvTFDaysPrinter.CalcTimeStampRect(Appt: TJvTFAppt; BarRect: TRect;
Col, StartRow, EndRow: Integer): TRect;
var
Offset, ApptLength: TTime;
ColDate: TDate;
StartPercent, EndPercent: Double;
begin
Result := BarRect;
if StartRow < 0 then
StartRow := 0;
if EndRow > RowCount - 1 then
EndRow := RowCount - 1;
Offset := RowToTime(StartRow);
ApptLength := RowEndTime(EndRow) - Offset;
ColDate := Cols[Col].SchedDate;
if Trunc(ColDate) <> Trunc(Appt.StartDate) then
StartPercent := 0
else
StartPercent := (Appt.StartTime - Offset) / ApptLength;
if Trunc(ColDate) <> Trunc(Appt.EndDate) then
EndPercent := 1.0
else
EndPercent := (Appt.EndTime - Offset) / ApptLength;
Result.Top := Round((BarRect.Bottom - BarRect.Top) * StartPercent) +
BarRect.Top;
Result.Bottom := Round((BarRect.Bottom - BarRect.Top) * EndPercent) +
BarRect.Top;
end;
procedure TJvTFDaysPrinter.DrawTimeStamp(ACanvas: TCanvas; TimeStampRect: TRect);
var
OldColor: TColor;
StampLeft: Integer;
begin
with ACanvas do
case ApptBar.TimeStampStyle of
tssFullI:
begin
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
Pen.Width := ScreenToPrinter(2, False);
MoveTo(TimeStampRect.Left + 1, TimeStampRect.Top);
LineTo(TimeStampRect.Right - 1, TimeStampRect.Top);
MoveTo(TimeStampRect.Left + 1, TimeStampRect.Bottom - 1);
LineTo(TimeStampRect.Right - 1, TimeStampRect.Bottom - 1);
if ApptBar.Width > 5 then
Pen.Width := ScreenToPrinter(2, True)
else
Pen.Width := ScreenToPrinter(1, True);
// Printer bug, fixed
StampLeft := TimeStampRect.Left + RectWidth(TimeStampRect) div 2;
MoveTo(StampLeft, TimeStampRect.Top + 1);
LineTo(StampLeft, TimeStampRect.Bottom - 1);
Pen.Width := 1;
Pen.Color := OldColor;
end;
tssHalfI:
begin
// we only want the left half of the time stamp rect
TimeStampRect.Right := (TimeStampRect.Left + TimeStampRect.Right) div 2;
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
Pen.Width := ScreenToPrinter(2, False);
MoveTo(TimeStampRect.Left, TimeStampRect.Top);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Top);
MoveTo(TimeStampRect.Left, TimeStampRect.Bottom - 0);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Bottom - 0);
if ApptBar.Width > 5 then
Pen.Width := ScreenToPrinter(2, True)
else
Pen.Width := ScreenToPrinter(1, True);
MoveTo(TimeStampRect.Right - 0, TimeStampRect.Top + 1);
LineTo(TimeStampRect.Right - 0, TimeStampRect.Bottom);
Pen.Color := OldColor;
Pen.Width := 1;
end;
tssBlock:
begin
// we only want the left half of the time stamp rect
TimeStampRect.Right := (TimeStampRect.Left + TimeStampRect.Right) div 2;
OldColor := Brush.Color;
Brush.Color := ApptBar.TimeStampColor;
FillRect(TimeStampRect);
Brush.Color := OldColor;
end;
end;
end;
procedure TJvTFDaysPrinter.DrawApptBar(ACanvas: TCanvas; Appt: TJvTFAppt;
BarRect: TRect; Col, StartRow, EndRow: Integer);
var
OldColor: TColor;
TimeStampRect: TRect;
begin
with ACanvas do
begin
// Fill Bar Color
OldColor := Brush.Color;
if Appt.BarColor = clDefault then
Brush.Color := ApptBar.Color
else
Brush.Color := Appt.BarColor;
FillRect(BarRect);
Brush.Color := OldColor;
// Draw Bar Border
Pen.Width := 1;
Pen.Color := ApptAttr.FrameColor;
MoveTo(BarRect.Right - 1, BarRect.Top);
LineTo(BarRect.Right - 1, BarRect.Bottom);
// Draw Time Stamp
TimeStampRect := CalcTimeStampRect(Appt, BarRect, Col, StartRow, EndRow);
if ApptBar.TimeStampStyle <> tssNone then
DrawTimeStamp(ACanvas, TimeStampRect);
if Assigned(FOnDrawApptBar) then
FOnDrawApptBar(Self, ACanvas, Appt, Col, BarRect, TimeStampRect);
end;
end;
{
procedure TJvTFDaysPrinter.DrawApptBar(ACanvas: TCanvas; Appt: TJvTFAppt;
BarRect: TRect; Col, StartRow, EndRow: Integer);
var
OldColor: TColor;
MarkerRect: TRect;
Offset,
ApptLength: TTime;
ColDate: TDate;
StartPercent,
EndPercent: Double;
begin
With ACanvas do
begin
// Fill Bar Color
OldColor := Brush.Color;
if Appt.BarColor = clDefault then
Brush.Color := ApptBar.Color
else
Brush.Color := Appt.BarColor;
FillRect(BarRect);
Brush.Color := OldColor;
// Draw Bar Border
Pen.Width := 1;
Pen.Color := ApptAttr.FrameColor;
MoveTo(BarRect.Right - 1, BarRect.Top);
LineTo(BarRect.Right - 1, BarRect.Bottom);
// Draw Time Stamp
Case ApptBar.TimeStampStyle of
tssFullI :
begin
MarkerRect := BarRect;
Offset := RowToTime(StartRow);
ApptLength := RowEndTime(EndRow) - Offset;
ColDate := Cols[Col].SchedDate;
if Trunc(ColDate) <> Trunc(Appt.StartDate) then
StartPercent := 0
else
StartPercent := (Appt.StartTime - Offset) / ApptLength;
if Trunc(ColDate) <> Trunc(Appt.EndDate) then
EndPercent := 1.0
else
EndPercent := (Appt.EndTime - Offset) / ApptLength;
MarkerRect.Top := Round((BarRect.Bottom - BarRect.Top) *
StartPercent) + BarRect.Top;
MarkerRect.Bottom := Round((BarRect.Bottom - BarRect.Top) *
EndPercent) + BarRect.Top;
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
Pen.Width := ScreenToPrinter(2, False);
MoveTo(MarkerRect.Left + 1, MarkerRect.Top);
LineTo(MarkerRect.Right - 1, MarkerRect.Top);
MoveTo(MarkerRect.Left + 1, MarkerRect.Bottom - 1);
LineTo(MarkerRect.Right - 1, MarkerRect.Bottom - 1);
if ApptBar.Width > 5 then
Pen.Width := ScreenToPrinter(2, True)
else
Pen.Width := ScreenToPrinter(1, True);
MoveTo((MarkerRect.Right) div 2, MarkerRect.Top + 1);
LineTo((MarkerRect.Right) div 2, MarkerRect.Bottom - 1);
Pen.Width := 1;
Pen.Color := OldColor;
end;
tssHalfI :
begin
MarkerRect := BarRect;
MarkerRect.Right := MarkerRect.Right div 2;
Offset := RowToTime(StartRow);
ApptLength := RowEndTime(EndRow) - Offset;
ColDate := Cols[Col].SchedDate;
if Trunc(ColDate) <> Trunc(Appt.StartDate) then
StartPercent := 0
else
StartPercent := (Appt.StartTime - Offset) / ApptLength;
if Trunc(ColDate) <> Trunc(Appt.EndDate) then
EndPercent := 1.0
else
EndPercent := (Appt.EndTime - Offset) / ApptLength;
MarkerRect.Top := Round((BarRect.Bottom - BarRect.Top) *
StartPercent) + BarRect.Top;
MarkerRect.Bottom := Round((BarRect.Bottom - BarRect.Top) *
EndPercent) + BarRect.Top;
OldColor := Pen.Color;
Pen.Color := ApptBar.TimeStampColor;
Pen.Width := ScreenToPrinter(2, False);
MoveTo(MarkerRect.Left, MarkerRect.Top);
LineTo(MarkerRect.Right - 0, MarkerRect.Top);
MoveTo(MarkerRect.Left, MarkerRect.Bottom - 0);
LineTo(MarkerRect.Right - 0, MarkerRect.Bottom - 0);
if ApptBar.Width > 5 then
Pen.Width := ScreenToPrinter(2, True)
else
Pen.Width := ScreenToPrinter(1, True);
MoveTo(MarkerRect.Right - 0, MarkerRect.Top + 1);
LineTo(MarkerRect.Right - 0, MarkerRect.Bottom);
Pen.Color := OldColor;
Pen.Width := 1;
end;
tssBlock :
begin
MarkerRect := BarRect;
MarkerRect.Right := MarkerRect.Right div 2;
Offset := RowToTime(StartRow);
ApptLength := RowEndTime(EndRow) - Offset;
ColDate := Cols[Col].SchedDate;
if Trunc(ColDate) <> Trunc(Appt.StartDate) then
StartPercent := 0
else
StartPercent := (Appt.StartTime - Offset) / ApptLength;
if Trunc(ColDate) <> Trunc(Appt.EndDate) then
EndPercent := 1.0
else
EndPercent := (Appt.EndTime - Offset) / ApptLength;
MarkerRect.Top := Round((BarRect.Bottom - BarRect.Top) *
StartPercent) + BarRect.Top;
MarkerRect.Bottom := Round((BarRect.Bottom - BarRect.Top) *
EndPercent) + BarRect.Top;
OldColor := Brush.Color;
Brush.Color := ApptBar.TimeStampColor;
FillRect(MarkerRect);
Brush.Color := OldColor;
end;
end;
end;
end;
}
procedure TJvTFDaysPrinter.DrawApptDetail(ACanvas: TCanvas; ARect: TRect;
Appt: TJvTFAppt; Col, StartRow, EndRow: Integer);
var
TheFrameRect, TxtRect, DetailRect, BarRect: TRect;
Txt: string;
Flags: UINT;
CanDrawText, CanDrawPics, CanDrawAppt: Boolean;
PicsHeight, PicsWidth: Integer;
DrawList: TList;
DrawInfo: TJvTFDaysApptDrawInfo;
begin
with ACanvas do
begin
DrawInfo := TJvTFDaysApptDrawInfo.Create;
try
GetApptDrawInfo(DrawInfo, Appt);
Font.Assign(DrawInfo.Font);
Brush.Color := DrawInfo.Color;
Pen.Color := DrawInfo.FrameColor;
Pen.Width := DrawInfo.FrameWidth;
CanDrawAppt := DrawInfo.Visible;
finally
DrawInfo.Free;
end;
// !!!!!!!!!!!!!!!!!!!!!!!!!!
// EXIT IF NOTHING TO DRAW !!
// !!!!!!!!!!!!!!!!!!!!!!!!!!
if not CanDrawAppt then
Exit;
//Brush.Color := GetApptDispColor(Appt);
FillRect(ARect);
//Pen.Color := ApptAttr.FrameColor;
//Pen.Width := ApptAttr.FrameWidth;
TheFrameRect := ARect;
InflateRect(TheFrameRect, -(ApptAttr.FrameWidth div 2), -(ApptAttr.FrameWidth div 2));
// Need to fine tune the frame rect
if ApptAttr.FrameWidth mod 2 = 0 then
begin
Inc(TheFrameRect.Right);
Inc(TheFrameRect.Bottom);
end;
MoveTo(TheFrameRect.Left, TheFrameRect.Top);
LineTo(TheFrameRect.Right - 1, TheFrameRect.Top);
LineTo(TheFrameRect.Right - 1, TheFrameRect.Bottom - 1);
LineTo(TheFrameRect.Left, TheFrameRect.Bottom - 1);
LineTo(TheFrameRect.Left, TheFrameRect.Top);
// Only go through the following work if all details must be drawn
if (RectHeight(ARect) > Thresholds.DetailHeight) and
(RectWidth(ARect) > Thresholds.DetailWidth) then
begin
InflateRect(TheFrameRect, -(ApptAttr.FrameWidth div 2), -(ApptAttr.FrameWidth div 2));
DetailRect := TheFrameRect;
if ApptBar.Visible then
begin
Inc(DetailRect.Left, ApptBar.Width);
SubtractRect(BarRect, TheFrameRect, DetailRect);
Dec(BarRect.Bottom);
DrawApptBar(ACanvas, Appt, BarRect, Col, StartRow, EndRow);
end;
TxtRect := DetailRect;
InflateRect(TxtRect, -2, -2);
DrawList := TList.Create;
try
// Set the canvas' font now so text height and width calc's will
// be correct.
//Font := ApptAttr.Font;
CreatePicDrawList(TxtRect, Appt, DrawList);
FilterPicDrawList(TxtRect, DrawList, PicsHeight, PicsWidth);
// Calc'ing text height and width in CanDrawWhat
CanDrawWhat(ACanvas, TxtRect, PicsHeight, PicsWidth, CanDrawText, CanDrawPics);
if CanDrawPics then
begin
DrawListPics(ACanvas, TxtRect, DrawList);
Inc(TxtRect.Left, PicsWidth); // Mantis 2340: Be coherent with JvTFDays
end;
finally
ClearPicDrawList(DrawList);
DrawList.Free;
end;
if CanDrawText then
begin
Flags := DT_WORDBREAK or DT_NOPREFIX or DT_EDITCONTROL;
Txt := ScheduleManager.GetApptDisplayText(Self, Appt);
if not FormattedDesc then
begin
Txt := StripCRLF(Txt);
Flags := Flags or DT_END_ELLIPSIS;
end;
DrawText(ACanvas.Handle, PChar(Txt), -1, TxtRect, Flags);
end;
end;
if Assigned(FOnDrawAppt) then
FOnDrawAppt(Self, ACanvas, ARect, Appt, False);
end;
end;
procedure TJvTFDaysPrinter.DrawAppts(ACanvas: TCanvas; DrawAll: Boolean;
PageInfo: TJvTFDaysPageInfo);
var
FromCol, ToCol, FromRow, ToRow, Col, I: Integer;
ApptStartRow, ApptEndRow, SchedDate: Integer;
Appt: TJvTFAppt;
begin
if Aborted then
Exit;
if DrawAll then
begin
FromCol := 0;
ToCol := Cols.Count - 1;
FromRow := 0;
ToRow := RowCount - 1;
end
else
begin
FromCol := PageInfo.StartCol;
ToCol := PageInfo.EndCol;
FromRow := PageInfo.StartRow;
ToRow := PageInfo.EndRow;
end;
if Assigned(FOnApptProgress) and (FApptsDrawn = 0) then
FOnApptProgress(Self, 0, ApptCount);
Application.ProcessMessages;
Col := FromCol;
while (Col <= ToCol) and not Aborted do
//For Col := FromCol to ToCol do
begin
if Cols[Col].Connected and not Aborted then
begin
SchedDate := Trunc(Cols[Col].SchedDate);
I := 0;
while (I < Cols[Col].Schedule.ApptCount) and not Aborted do
//For I := 0 to Cols[Col].Schedule.ApptCount - 1 do
begin
Appt := Cols[Col].Schedule.Appts[I];
CalcStartEndRows(Appt, SchedDate, ApptStartRow, ApptEndRow);
if (ApptStartRow <= ToRow) and (ApptEndRow >= FromRow) then
begin
DrawAppt(ACanvas, Col, Appt, ApptStartRow, ApptEndRow, PageInfo);
Inc(FApptsDrawn);
if Assigned(FOnApptProgress) then
FOnApptProgress(Self, FApptsDrawn, ApptCount);
Application.ProcessMessages;
end;
Inc(I);
end;
end;
Inc(Col);
end;
end;
procedure TJvTFDaysPrinter.DrawBody(ACanvas: TCanvas; ARect: TRect;
PageNum: Integer);
var
SaveMeasure: TJvTFPrinterMeasure;
lPageInfo: TJvTFDaysPageInfo;
I, J: Integer;
begin
if Aborted then
Exit;
SaveMeasure := Measure;
Measure := pmPixels;
lPageInfo := TJvTFDaysPageInfo(FPageInfoList.Objects[PageNum - 1]);
with ACanvas do
begin
Brush.Color := Self.Color;
FillRect(ARect);
DrawCorner(ACanvas);
if lPageInfo.ShowColHdr then
begin
if Cols.Count = 0 then
DrawEmptyColHdr(ACanvas, lPageInfo)
else
begin
DrawGroupHdrs(ACanvas, lPageInfo);
for I := lPageInfo.StartCol to lPageInfo.EndCol do
begin
if Aborted then
Break;
//DrawColHdr(ACanvas, I, lPageInfo);
DrawColGroupHdr(ACanvas, I, lPageInfo, False);
end;
end;
end;
if lPageInfo.ShowRowHdr then
if RowHdrType = rhFancy then
DrawFancyRowHdrs(ACanvas, lPageInfo)
else
for I := lPageInfo.StartRow to lPageInfo.EndRow do
begin
if Aborted then
Break;
DrawRowHdr(ACanvas, I, lPageInfo);
end;
for I := lPageInfo.StartRow to lPageInfo.EndRow do
for J := lPageInfo.StartCol to lPageInfo.EndCol do
begin
if Aborted then
Break;
DrawDataCell(ACanvas, J, I, lPageInfo);
end;
if not (csDesigning in ComponentState) and not Aborted then
DrawAppts(ACanvas, False, lPageInfo);
end;
Measure := SaveMeasure;
inherited DrawBody(ACanvas, ARect, PageNum);
end;
{
procedure TJvTFDaysPrinter.DrawColHdr(ACanvas: TCanvas; Index: Integer;
PageInfo: TJvTFDaysPageInfo);
var
ARect,
TxtRect,
CalcRect: TRect;
Txt: string;
PTxt: PChar;
Flags: UINT;
TxtHt,
TxtRectHt: Integer;
begin
ARect := CellRect(Index, -1, PageInfo);
//Txt := Copy(Cols[Index].Title, 1, Length(Cols[Index].Title));
Txt := Cols[Index].Title;
ACanvas.Brush.Color := HdrAttr.Color;
ACanvas.Font.Assign(HdrAttr.Font);
Flags := DT_NOPREFIX or DT_CENTER;
Case ColTitleStyle of
ctsSingleClip : Flags := Flags or DT_SINGLELINE or DT_VCENTER;
ctsSingleEllipsis: Flags := Flags or DT_END_ELLIPSIS or DT_SINGLELINE or
DT_VCENTER;
ctsMultiClip : Flags := Flags or DT_WORDBREAK;
ctsMultiEllipsis : Flags := Flags or DT_END_ELLIPSIS or DT_WORDBREAK or
DT_EDITCONTROL;
ctsHide : Flags := Flags or DT_SINGLELINE or DT_VCENTER;
end;
ACanvas.FillRect(ARect);
TxtRect := ARect;
Windows.InflateRect(TxtRect, -2, -2);
CalcRect := TxtRect;
//PTxt := StrNew(PChar(Txt));
PTxt := StrAlloc((Length(Txt) + 4) * SizeOf(Char));
StrPCopy(PTxt, Txt);
if (ColTitleStyle = ctsMultiClip) or
(ColTitleStyle = ctsMultiEllipsis) then
begin
TxtHt := Windows.DrawText(ACanvas.Handle, PTxt, -1, CalcRect,
Flags or DT_CALCRECT);
if TxtHt < RectHeight(TxtRect) then
begin
// we need to vertically center the text
TxtRectHt := RectHeight(TxtRect);
TxtRect.Top := TxtRect.Top + RectHeight(TxtRect) div 2 - TxtHt div 2;
TxtRect.Bottom := Lesser(TxtRect.Top + TxtRectHt, TxtRect.Bottom);
end;
end
else
if ColTitleStyle = ctsHide then
begin
Windows.DrawText(ACanvas.Handle, PTxt, -1, CalcRect, Flags or DT_CALCRECT);
if RectWidth(CalcRect) > RectWidth(TxtRect) then
StrPCopy(PTxt, '');
end;
Windows.DrawText(ACanvas.Handle, PTxt, -1, TxtRect, Flags);
StrDispose(PTxt);
DrawFrame(ACanvas, ARect, HdrAttr.Frame3D);
if Assigned(FOnDrawColHdr) then
FOnDrawColHdr(Self, ACanvas, ARect, Index, False);
end;
}
procedure TJvTFDaysPrinter.DrawCorner(ACanvas: TCanvas);
var
ARect: TRect;
begin
//group ARect := Classes.Rect(0, 0, RowHdrWidth, ColHdrHeight);
ARect := Classes.Rect(0, 0, RowHdrWidth, CalcGroupColHdrsHeight);
with ACanvas do
begin
Brush.Color := HdrAttr.Color;
FillRect(ARect);
if HdrAttr.Frame3D then
DrawFrame(ACanvas, ARect, HdrAttr.Frame3D)
else
begin
if RowHdrType = rhFancy then
begin
Pen.Color := FancyRowHdrAttr.TickColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom - 1);
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
end
else
DrawFrame(ACanvas, ARect, False);
end;
if Assigned(FOnDrawCorner) then
FOnDrawCorner(Self, ACanvas, ARect, agcTopLeft);
end;
end;
procedure TJvTFDaysPrinter.DrawDataCell(ACanvas: TCanvas; ColIndex,
RowIndex: Integer; PageInfo: TJvTFDaysPageInfo);
var
ARect: TRect;
PrimeStartRow, PrimeEndRow: Integer;
CellColor: TColor;
begin
// Calc the cell rect
if PageInfo.ShowRowHdr then
ARect.Left := RowHdrWidth
else
ARect.Left := 0;
ARect.Left := ARect.Left + (ColIndex - PageInfo.StartCol) * PageInfo.ColWidth;
ARect.Right := ARect.Left + PageInfo.ColWidth;
{ variable col widths, leave for future reference
For I := LeftCol to ColIndex - 1 do
Inc(ARect.Left, Cols[I].Width);
ARect.Right := ARect.Left + Cols[ColIndex].Width;
}
if PageInfo.ShowColHdr then
//group ARect.Top := ColHdrHeight
ARect.Top := CalcGroupColHdrsHeight
else
ARect.Top := 0;
ARect.Top := ARect.Top + (RowIndex - PageInfo.StartRow) * PageInfo.RowHeight;
ARect.Bottom := ARect.Top + PageInfo.RowHeight;
PrimeStartRow := TimeToRow(PrimeTime.StartTime);
PrimeEndRow := TimeToRow(AdjustEndTime(PrimeTime.EndTime));
if (RowIndex >= PrimeStartRow) and (RowIndex <= PrimeEndRow) then
CellColor := PrimeTime.Color
else
CellColor := Color;
if Assigned(FOnShadeCell) then
FOnShadeCell(Self, ColIndex, RowIndex, CellColor);
if CellColor <> Color then
begin
ACanvas.Brush.Color := CellColor;
ACanvas.FillRect(ARect);
end;
// Draw a line across the ARect.Bottom and down the ARect.Right side
with ACanvas do
begin
Pen.Color := GridLineColor;
Pen.Width := 1;
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom - 1);
end;
if Assigned(FOnDrawDataCell) then
FOnDrawDataCell(Self, ACanvas, ARect, ColIndex, RowIndex);
end;
procedure TJvTFDaysPrinter.DrawEmptyColHdr(ACanvas: TCanvas;
PageInfo: TJvTFDaysPageInfo);
var
ARect: TRect;
begin
ARect.Left := RowHdrWidth;
ARect.Top := 0;
ARect.Right := ARect.Left + GetDataWidth(PageInfo.ShowRowHdr);
//group ARect.Bottom := ColHdrHeight;
ARect.Bottom := CalcGroupColHdrsHeight;
with ACanvas do
begin
Brush.Color := HdrAttr.Color;
FillRect(ARect);
Pen.Color := clGray;
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
end;
end;
procedure TJvTFDaysPrinter.DrawFancyRowHdrs(ACanvas: TCanvas;
PageInfo: TJvTFDaysPageInfo);
var
I, MajorTickLength, MinorTickLength, TickLength: Integer;
ARect: TRect;
Lbl: string;
PrevHour, CurrentHour: Word;
FirstMajor, Switch: Boolean;
begin
MajorTickLength := GetMajorTickLength;
MinorTickLength := GetMinorTickLength(ACanvas);
FirstMajor := True;
PrevHour := RowToHour(PageInfo.StartRow);
for I := PageInfo.StartRow to PageInfo.EndRow do
begin
CurrentHour := RowToHour(I);
Switch := (CurrentHour <> PrevHour) or (I = PageInfo.EndRow);
ARect := CellRect(-1, I, PageInfo);
Lbl := GetMinorLabel(I, PageInfo);
if not RowEndsHour(I) then
TickLength := MinorTickLength
else
TickLength := MajorTickLength;
DrawMinor(ACanvas, ARect, I, Lbl, TickLength);
// Draw Major if needed
if Switch and (Granularity <> 60) then
begin
if I <> PageInfo.StartRow + 1 then
begin
ARect.Left := ScreenToPrinter(2, true); // Allow for a small margin on ARect.Left side
ARect.Right := RowHdrWidth - MinorTickLength;
// ARect.Right := RowHdrWidth; // No "cutting" before the end of the cell.
ARect.Top := CellRect(-1, HourStartRow(PrevHour), PageInfo).Top;
//group if ARect.Top < ColHdrHeight then
//group ARect.Top := ColHdrHeight;
if ARect.Top < CalcGroupColHdrsHeight then
ARect.Top := CalcGroupColHdrsHeight;
ARect.Bottom := CellRect(-1, HourEndRow(PrevHour), PageInfo).Bottom - 1;
// No need to check for ARect.Bottom to be outside the page, CellRect
// calculates it so that it does not happen. And using GetDataHeight
// is not a good idea as it removes the column header height, which
// is NOT what we want here as we want the page's integral height.
// If we wer to use it, we would trigger Mantis 2340.
if FancyRowHdrAttr.Hr2400 then
Lbl := IntToStr(PrevHour)
else
begin
if PrevHour = 0 then
Lbl := '12'
else
if PrevHour > 12 then
Lbl := IntToStr(PrevHour - 12)
else
Lbl := IntToStr(PrevHour);
if FirstMajor or (PrevHour = 0) or (PrevHour = 12) then
if PrevHour < 12 then
Lbl := Lbl + 'a'
else
Lbl := Lbl + 'p';
end;
ACanvas.Font.Assign(FancyRowHdrAttr.MajorFont);
ACanvas.Brush.Style := bsClear;
DrawText(ACanvas.Handle, PChar(Lbl), -1, ARect,
DT_NOPREFIX or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
if Assigned(FOnDrawMajorRowHdr) then
FOnDrawMajorRowHdr(Self, ACanvas, ARect, I - 1, False);
FirstMajor := False;
end;
if Switch then
PrevHour := CurrentHour;
end;
end;
end;
procedure TJvTFDaysPrinter.DrawFrame(ACanvas: TCanvas; ARect: TRect;
Draw3D: Boolean);
var
OldPenColor: TColor;
begin
with ACanvas do
begin
OldPenColor := Pen.Color;
if Draw3D then
Pen.Color := clBtnShadow
else
Pen.Color := GridLineColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
MoveTo(ARect.Left, ARect.Bottom - 1);
LineTo(ARect.Right, ARect.Bottom - 1);
if Draw3D then
begin
Pen.Color := clBtnHighlight;
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Right, ARect.Top);
MoveTo(ARect.Left, ARect.Top);
LineTo(ARect.Left, ARect.Bottom);
end;
Pen.Color := OldPenColor;
end;
end;
procedure TJvTFDaysPrinter.DrawListPics(ACanvas: TCanvas;
var ARect: TRect; DrawList: TList);
var
I: Integer;
DrawInfo: TJvTFDrawPicInfo;
Pic: TBitmap;
DestRect: TRect;
begin
Pic := TBitmap.Create;
Pic.Canvas.Brush.Color := ACanvas.Brush.Color;
try
for I := 0 to DrawList.Count - 1 do
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[I]);
Pic.Height := DrawInfo.ImageList.Height;
Pic.Width := DrawInfo.ImageList.Width;
Pic.Canvas.FillRect(Classes.Rect(0, 0, Pic.Width, Pic.Height));
with DrawInfo do
ImageList.Draw(Pic.Canvas, 0, 0, ImageIndex);
DestRect.Left := DrawInfo.PicLeft;
DestRect.Top := DrawInfo.PicTop;
DestRect.Right := DrawInfo.PicLeft +
ScreenToPrinter(DrawInfo.ImageList.Width + 2, True);
DestRect.Bottom := DrawInfo.PicTop +
ScreenToPrinter(DrawInfo.ImageList.Height + 2, False);
PrintBitmap(ACanvas, Classes.Rect(0, 0, Pic.Width, Pic.Height), DestRect, Pic);
end;
finally
Pic.Free;
end;
end;
procedure TJvTFDaysPrinter.DrawMinor(ACanvas: TCanvas; ARect: TRect;
RowNum: Integer; const LabelStr: string; TickLength: Integer);
var
MinorRect, TxtRect: TRect;
begin
// do the background shading
ACanvas.Brush.Color := FancyRowHdrAttr.Color;
ACanvas.FillRect(ARect);
MinorRect := ARect;
MinorRect.Left := MinorRect.Right - GetMinorTickLength(ACanvas);
with ACanvas do
begin
// draw the right border line
Pen.Color := FancyRowHdrAttr.TickColor;
MoveTo(ARect.Right - 1, ARect.Top);
LineTo(ARect.Right - 1, ARect.Bottom);
// now draw the tick
MoveTo(ARect.Right - 1, ARect.Bottom - 1);
LineTo(ARect.Right - 1 - TickLength, ARect.Bottom - 1);
end;
// set up a 2 pel margin on the right and bottom sides
TxtRect := ARect;
TxtRect.Right := TxtRect.Right - ScreenToPrinter(2, true);
TxtRect.Bottom := TxtRect.Bottom - ScreenToPrinter(2, true);
// now draw the LabelStr right aligned
ACanvas.Font.Assign(FancyRowHdrAttr.MinorFont);
ACanvas.Brush.Style := bsClear;
DrawText(ACanvas.Handle, PChar(LabelStr), -1, TxtRect,
DT_SINGLELINE or DT_RIGHT or DT_NOPREFIX or DT_VCENTER);
if Assigned(FOnDrawMinorRowHdr) then
FOnDrawMinorRowHdr(Self, ACanvas, ARect, RowNum, False);
end;
procedure TJvTFDaysPrinter.DrawRowHdr(ACanvas: TCanvas; Index: Integer;
PageInfo: TJvTFDaysPageInfo);
var
ARect: TRect;
Txt: string;
begin
ARect.Left := 0;
if PageInfo.ShowColHdr then
//group Top := ColHdrHeight
ARect.Top := CalcGroupColHdrsHeight
else
ARect.Top := 0;
ARect.Top := ARect.Top + (Index - PageInfo.StartRow) * PageInfo.RowHeight;
ARect.Right := RowHdrWidth;
ARect.Bottom := ARect.Top + PageInfo.RowHeight;
Txt := FormatDateTime(TimeFormat, RowToTime(Index));
ACanvas.Brush.Color := HdrAttr.Color;
ACanvas.Font.Assign(HdrAttr.Font);
DrawTxt(ACanvas, ARect, Txt, taCenter, vaCenter);
DrawFrame(ACanvas, ARect, HdrAttr.Frame3D);
if Assigned(FOnDrawRowHdr) then
FOnDrawRowHdr(Self, ACanvas, ARect, Index, False);
end;
procedure TJvTFDaysPrinter.EnsureRow(RowNum: Integer);
begin
if RowNum >= RowCount then
raise EJvTFPrinterError.CreateResFmt(@RsEInvalidRowd, [RowNum]);
end;
procedure TJvTFDaysPrinter.FilterPicDrawList(ARect: TRect;
DrawList: TList; out PicsHeight, PicsWidth: Integer);
var
I, NextPicLeft, PicRight, PicBottom: Integer;
DrawIt: Boolean;
DrawInfo: TJvTFDrawPicInfo;
begin
PicsHeight := 0;
PicsWidth := 0;
if DrawList.Count = 0 then
Exit;
if Thresholds.PicsAllOrNone then
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[DrawList.Count - 1]);
PicRight := DrawInfo.PicLeft + ScreenToPrinter(DrawInfo.ImageList.Width, True);
if PicRight >= ARect.Right then
begin
while DrawList.Count > 0 do
begin
TJvTFDrawPicInfo(DrawList[0]).Free;
DrawList.Delete(0);
end;
end;
end;
PicsHeight := 0;
NextPicLeft := ARect.Left;
I := 0;
while I < DrawList.Count do
begin
DrawInfo := TJvTFDrawPicInfo(DrawList[I]);
with DrawInfo do
begin
PicRight := PicLeft + ScreenToPrinter(ImageList.Width + 2, True);
PicBottom := PicTop + ScreenToPrinter(ImageList.Height + 2, False);
DrawIt := True;
if Thresholds.WholePicsOnly and
(PicRight >= ARect.Right) or (PicBottom >= ARect.Bottom) then
DrawIt := False;
if DrawIt then
begin
//PicsHeight := Greater(PicsHeight, ImageList.Height + 2);
PicsHeight := Greater(PicsHeight, PicBottom - PicTop + 2);
PicLeft := NextPicLeft;
//Inc(NextPicLeft, ImageList.Width + 2);
Inc(NextPicLeft, PicRight - PicLeft + 2);
// Increment I to move onto next pic in list
Inc(I);
end
else // Remove pic from list
begin
// Remove pic from list
DrawInfo.Free;
DrawList.Delete(I);
// DO NOT increment I - Since pic was removed from list
// I will now point to next pic
end;
end;
end;
PicsWidth := NextPicLeft - ARect.Left;
end;
function TJvTFDaysPrinter.GetApptDispColor(Appt: TJvTFAppt): TColor;
begin
if Appt.Color = clDefault then
Result := ApptAttr.Color
else
Result := Appt.Color;
end;
function TJvTFDaysPrinter.GetApptRect(Col: Integer; Appt: TJvTFAppt;
PageInfo: TJvTFDaysPageInfo): TRect;
var
MapCol, MapColCount, Base, MakeUp, BaseWidth, MakeUpWidth: Integer;
BaseCount, GridColWidth, ApptWidth, StartRow, EndRow: Integer;
WorkLeft, WorkTop: Integer;
begin
if not Assigned(Appt) then
begin
Result := EmptyRect;
Exit;
end;
CalcStartEndRows(Appt, Cols[Col].SchedDate, StartRow, EndRow);
if (StartRow < 0) and (EndRow >= 0) then
StartRow := 0;
// if the above condition fails and the StartRow is STILL invalid then
// let the 'Map col not found' catch the error.
// Printer bug, fixed
EndRow := Lesser(EndRow, PageInfo.EndRow);
MapCol := Cols[Col].LocateMapCol(Appt, StartRow);
if MapCol < 1 then
begin
raise EJvTFDaysError.CreateRes(@RsEMapColNotFoundForAppointment);
end;
MapColCount := Cols[Col].MapColCount(StartRow);
if MapColCount < 1 then
begin
//Cols[Col].FMap.Dump('corrupt dump.txt'); !!! FOR DEBUGGING ONLY !!!!
raise EJvTFPrinterError.CreateRes(@RsECorruptAppointmentMap);
end;
// Col guaranteed to be partially visible
// Printer bug start, fixed
WorkLeft := CellRect(Col, Greater(StartRow, PageInfo.StartRow), PageInfo).Left;
if StartRow < PageInfo.StartRow then
WorkTop := CellRect(Col, PageInfo.StartRow, PageInfo).Top -
PageInfo.RowHeight * (PageInfo.StartRow - StartRow)
else
WorkTop := CellRect(Col, StartRow, PageInfo).Top;
// Printer bug end, fixed
GridColWidth := PageInfo.ColWidth;
// The Base* and MakeUp* code that follows calc's the appt width and left
// and takes into account a total width that isn't evenly divisible by
// the map col count. if there is a discrepency then that discrepency
// is divvied up amoung the cols working Result.Left to Result.Right.
//
// Example: Total width = 113, col count = 5
// col 1 = 23
// col 2 = 23
// col 3 = 23
// col 4 = 22
// col 5 = 22
// Total = 113
//
// As opposed to:
// width of all cols = Total div colcount = 22
// ==> Total = 22 * 5 = 110 [110 <> 113]
Base := GridColWidth div MapColCount;
MakeUp := GridColWidth mod MapColCount;
MakeUpWidth := Lesser(MapCol - 1, MakeUp) * (Base + 1);
BaseCount := MapCol - 1 - MakeUp;
if BaseCount > 0 then
BaseWidth := BaseCount * Base
else
BaseWidth := 0;
ApptWidth := Base;
if MapCol <= MakeUp then
Inc(ApptWidth);
// Printer bug, fixed
Result.Left := WorkLeft + MakeUpWidth + BaseWidth;
Result.Right := Result.Left + ApptWidth - ApptBuffer;
// Printer bug, fixed
Result.Top := WorkTop - 1;
Result.Bottom := CellRect(Col, EndRow, PageInfo).Bottom;
end;
function TJvTFDaysPrinter.GetDataHeight(ShowColHdr: Boolean): Integer;
begin
Result := BodyHeight;
if ShowColHdr then
//group Dec(Result, ConvertMeasure(ColHdrHeight, Measure, pmPixels, False));
Dec(Result, ConvertMeasure(CalcGroupColHdrsHeight, Measure, pmPixels, False));
end;
function TJvTFDaysPrinter.GetDataWidth(ShowRowHdr: Boolean): Integer;
begin
Result := BodyWidth;
if ShowRowHdr then
Dec(Result, ConvertMeasure(RowHdrWidth, Measure, pmPixels, True));
end;
function TJvTFDaysPrinter.GetMajorTickLength: Integer;
begin
Result := RowHdrWidth;
end;
function TJvTFDaysPrinter.GetMinorLabel(RowNum: Integer;
PageInfo: TJvTFDaysPageInfo): string;
const
Full24 = 'h:nn';
FullAP = 'h:nna/p';
MinOnly = 'nn';
var
TimeFmt: string;
LastFullRow, LastHourStart: Integer;
LastHour: Word;
begin
if Granularity = 60 then
TimeFmt := Full24
else
if (RowNum = PageInfo.StartRow) and not RowStartsHour(RowNum) then
TimeFmt := Full24
else
begin
LastFullRow := PageInfo.EndRow;
LastHour := RowToHour(LastFullRow);
LastHourStart := HourStartRow(LastHour);
if ((RowNum = LastHourStart) and not RowStartsHour(RowNum)) or
((LastHourStart = PageInfo.StartRow) and (RowNum = PageInfo.StartRow)) then
TimeFmt := Full24
else
TimeFmt := MinOnly;
end;
if (TimeFmt = Full24) and not FancyRowHdrAttr.Hr2400 then
TimeFmt := FullAP;
Result := FormatDateTime(TimeFmt, RowToTime(RowNum));
end;
function TJvTFDaysPrinter.GetMinorTickLength(ACanvas: TCanvas): Integer;
var
TempFont: TFont;
begin
TempFont := TFont.Create;
try
TempFont.Assign(ACanvas.Font);
ACanvas.Font.Assign(FancyRowHdrAttr.MinorFont);
Result := ACanvas.TextWidth('00') + ScreenToPrinter(6, true);
// Result := ACanvas.TextWidth('22:22a');
ACanvas.Font.Assign(TempFont);
finally
TempFont.Free;
end;
end;
function TJvTFDaysPrinter.HourEndRow(Hour: Word): Integer;
begin
Result := TimeToRow(EncodeTime(Hour, 59, 0, 0));
end;
function TJvTFDaysPrinter.HourStartRow(Hour: Word): Integer;
begin
Result := TimeToRow(EncodeTime(Hour, 0, 0, 0));
end;
procedure TJvTFDaysPrinter.Loaded;
var
I: Integer;
begin
inherited Loaded;
for I := 0 to Cols.Count - 1 do
Cols[I].Connect;
end;
procedure TJvTFDaysPrinter.Prepare;
var
I: Integer;
begin
NewDoc;
try
FApptsDrawn := 0;
CalcPageInfo;
if FPageInfoList.Count = 0 then
raise EJvTFPrinterError.CreateRes(@RsEThereIsNoDataToPrint);
for I := 0 to FPageInfoList.Count - 1 do
NewPage;
//Except on EJvTFPrinterError do
except
begin
FreeDoc;
raise;
end;
end;
FApptsDrawn := 0;
FinishDoc;
end;
function TJvTFDaysPrinter.RowCount: Integer;
var
Adjustment, H, M, S, MS: Word;
WorkTime: TTime;
begin
WorkTime := GridEndTime;
DecodeTime(WorkTime, H, M, S, MS);
Adjustment := 0;
if (H = 0) and (M = 0) then
begin
WorkTime := EncodeTime(23, 59, 59, 999);
Adjustment := 1;
end;
//DecodeTime(GridEndTime - GridStartTime, H, M, S, MS);
DecodeTime(WorkTime - GridStartTime, H, M, S, MS);
Result := (H * 60 + M) div Granularity + Adjustment;
end;
function TJvTFDaysPrinter.RowEndsHour(RowNum: Integer): Boolean;
var
H, M, S, MS: Word;
TempTime: TTime;
begin
EnsureRow(RowNum);
TempTime := RowToTime(RowNum) + EncodeTime(0, Granularity - 1, 0, 0);
DecodeTime(TempTime, H, M, S, MS);
Result := M = 59;
end;
function TJvTFDaysPrinter.RowEndTime(RowNum: Integer): TTime;
begin
Result := RowToTime(RowNum) +
Granularity * EncodeTime(0, 1, 0, 0) - EncodeTime(0, 0, 1, 0);
end;
function TJvTFDaysPrinter.RowStartsHour(RowNum: Integer): Boolean;
var
H, M, S, MS: Word;
begin
EnsureRow(RowNum);
DecodeTime(RowToTime(RowNum), H, M, S, MS);
Result := M = 0;
end;
function TJvTFDaysPrinter.RowToHour(RowNum: Integer): Word;
var
H, M, S, MS: Word;
begin
DecodeTime(RowToTime(RowNum), H, M, S, MS);
Result := H;
end;
function TJvTFDaysPrinter.RowToTime(RowNum: Integer): TTime;
var
TotalMins: Integer;
WorkHours, WorkMins: Word;
H, M, S, MS: Word;
Offset: Integer;
begin
DecodeTime(GridStartTime, H, M, S, MS);
Offset := H * 60 + M;
TotalMins := RowNum * Granularity + Offset;
WorkHours := TotalMins div 60;
WorkMins := TotalMins mod 60;
if WorkHours < 24 then
Result := EncodeTime(WorkHours, WorkMins, 0, 0)
else
Result := EncodeTime(23, 59, 59, 999);
end;
procedure TJvTFDaysPrinter.SetApptAttr(Value: TJvTFDaysApptAttr);
begin
SetPropertyCheck;
FApptAttr.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetApptBar(Value: TJvTFDaysApptBar);
begin
SetPropertyCheck;
FApptBar.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetApptBuffer(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
FApptBuffer := Value;
end;
procedure TJvTFDaysPrinter.SetColHdrHeight(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
FColHdrHeight := Value;
end;
procedure TJvTFDaysPrinter.SetColor(Value: TColor);
begin
SetPropertyCheck;
FColor := Value;
end;
procedure TJvTFDaysPrinter.SetCols(Value: TJvTFDaysCols);
begin
FCols.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetTFColTitleStyle(Value: TJvTFColTitleStyle);
begin
SetPropertyCheck;
FColTitleStyle := Value;
end;
procedure TJvTFDaysPrinter.SetFancyRowHdrAttr(Value: TJvTFDaysFancyRowHdrAttr);
begin
SetPropertyCheck;
FFancyRowHdrAttr.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetGranularity(Value: Integer);
var
MaxRowHeight, I: Integer;
begin
SetPropertyCheck;
// Enforce minimum granularity of 1 min and max of 60 mins
if Value < 1 then
Value := 1
else
if Value > 60 then
Value := 60;
// Ensure that granularity is evenly divisable by an hour
while 60 mod Value <> 0 do
Dec(Value);
// Sum of row heights cannot exceed 32767
MaxRowHeight := 32767 div (60 div Value * 24);
if RowHeight > MaxRowHeight then
RowHeight := MaxRowHeight;
if Value <> FGranularity then
begin
FGranularity := Value;
if not (csLoading in ComponentState) then
begin
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
end;
end;
end;
procedure TJvTFDaysPrinter.SetGridLineColor(Value: TColor);
begin
SetPropertyCheck;
FGridLineColor := Value;
end;
procedure TJvTFDaysPrinter.SetHdrAttr(Value: TJvTFDaysHdrAttr);
begin
SetPropertyCheck;
FHdrAttr.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetMeasure(Value: TJvTFPrinterMeasure);
var
I: Integer;
begin
try
FConvertingProps := True;
if Value <> Measure then
begin
// convert properties
ApptAttr.FrameWidth := ConvertMeasure(ApptAttr.FrameWidth, Measure,
Value, False);
ApptBar.Width := ConvertMeasure(ApptBar.Width, Measure, Value, True);
ApptBuffer := ConvertMeasure(ApptBuffer, Measure, Value, True);
ColHdrHeight := ConvertMeasure(ColHdrHeight, Measure, Value, False);
GroupHdrHeight := ConvertMeasure(GroupHdrHeight, Measure, Value, False);
for I := 0 to Cols.Count - 1 do
Cols[I].Width := ConvertMeasure(Cols[I].Width, Measure, Value, True);
MinColWidth := ConvertMeasure(MinColWidth, Measure, Value, True);
MinRowHeight := ConvertMeasure(MinRowHeight, Measure, Value, False);
RowHdrWidth := ConvertMeasure(RowHdrWidth, Measure, Value, True);
RowHeight := ConvertMeasure(RowHeight, Measure, Value, False);
Thresholds.DetailHeight := ConvertMeasure(Thresholds.DetailHeight,
Measure, Value, False);
Thresholds.DetailWidth := ConvertMeasure(Thresholds.DetailWidth,
Measure, Value, True);
inherited SetMeasure(Value);
end;
finally
FConvertingProps := False;
end;
end;
procedure TJvTFDaysPrinter.SetMinColWidth(Value: Integer);
var
absMinColWidth: Integer;
begin
SetPropertyCheck;
absMinColWidth := DEFAULT_MIN_COL_WIDTH;
if Value < absMinColWidth then
Value := absMinColWidth;
FMinColWidth := Value;
end;
procedure TJvTFDaysPrinter.SetMinRowHeight(Value: Integer);
begin
SetPropertyCheck;
if Value < 1 then
Value := 1;
FMinRowHeight := Value;
end;
procedure TJvTFDaysPrinter.SetPrimeTime(Value: TJvTFDaysPrimeTime);
begin
SetPropertyCheck;
FPrimeTime.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetProperties(aJvTFDays: TJvTFDays);
begin
ApptAttr := aJvTFDays.ApptAttr;
ApptAttr.FrameWidth :=
ConvertMeasure(ScreenToPrinter(ApptAttr.FrameWidth, False), pmPixels,
Measure, False);
ApptBar := aJvTFDays.ApptBar;
ApptBar.Width := ConvertMeasure(ScreenToPrinter(ApptBar.Width, True), pmPixels,
Measure, True);
ApptBuffer := ConvertMeasure(ScreenToPrinter(aJvTFDays.ApptBuffer, True),
pmPixels, Measure, True);
ColHdrHeight := ConvertMeasure(ScreenToPrinter(aJvTFDays.ColHdrHeight, False),
pmPixels, Measure, False);
Color := aJvTFDays.Color;
ColTitleStyle := aJvTFDays.ColTitleStyle;
DateFormat := aJvTFDays.DateFormat;
FancyRowHdrAttr := aJvTFDays.FancyRowHdrAttr;
FormattedDesc := agoFormattedDesc in aJvTFDays.Options;
Granularity := aJvTFDays.Granularity;
GridLineColor := aJvTFDays.GridLineColor;
GroupHdrAttr := aJvTFDays.GroupHdrAttr;
//GroupHdrHeight := aJvTFDays.GroupHdrHeight;
GroupHdrHeight := ConvertMeasure(ScreenToPrinter(aJvTFDays.GroupHdrHeight,
False), pmPixels, Measure, False);
Grouping := aJvTFDays.Grouping;
HdrAttr := aJvTFDays.HdrAttr;
FixFont(FancyRowHdrAttr.MajorFont);
FixFont(FancyRowHdrAttr.Minorfont);
FixFont(GroupHdrAttr.Font);
FixFont(HdrAttr.Font);
MinColWidth := ConvertMeasure(ScreenToPrinter(aJvTFDays.MinColWidth, True),
pmPixels, Measure, True);
PrimeTime := aJvTFDays.PrimeTime;
RowHdrType := aJvTFDays.RowHdrType;
RowHdrWidth := ConvertMeasure(ScreenToPrinter(aJvTFDays.RowHdrWidth, True),
pmPixels, Measure, True);
RowHeight := ConvertMeasure(ScreenToPrinter(aJvTFDays.RowHeight, False),
pmPixels, Measure, False);
ShowPics := agoShowPics in aJvTFDays.Options;
ShowText := agoShowText in aJvTFDays.Options;
Thresholds := aJvTFDays.Thresholds;
Thresholds.DetailHeight :=
ConvertMeasure(ScreenToPrinter(Thresholds.DetailHeight, False), pmPixels,
Measure, False);
Thresholds.DetailWidth :=
ConvertMeasure(ScreenToPrinter(Thresholds.DetailWidth, True), pmPixels,
Measure, True);
TimeFormat := aJvTFDays.TimeFormat;
// Set the property fields directly to avoid validity check. Assume
// settings from aJvTFDays are already validated.
FGridStartTime := aJvTFDays.GridStartTime;
FGridEndTime := aJvTFDays.GridEndTime;
end;
procedure TJvTFDaysPrinter.SetTFRowHdrType(Value: TJvTFRowHdrType);
begin
SetPropertyCheck;
FRowHdrType := Value;
end;
procedure TJvTFDaysPrinter.SetRowHdrWidth(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
FRowHdrWidth := Value;
end;
procedure TJvTFDaysPrinter.SetRowHeight(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
FRowHeight := Value;
end;
procedure TJvTFDaysPrinter.SetShowPics(Value: Boolean);
begin
SetPropertyCheck;
FShowPics := Value;
end;
procedure TJvTFDaysPrinter.SetShowText(Value: Boolean);
begin
SetPropertyCheck;
FShowText := Value;
end;
procedure TJvTFDaysPrinter.SetThresholds(Value: TJvTFDaysThresholds);
begin
SetPropertyCheck;
FThresholds.Assign(Value);
end;
function TJvTFDaysPrinter.TimeToRow(ATime: TTime): Integer;
var
TotalMins: Integer;
WorkHours, WorkMins, WorkSecs, WorkMSecs: Word;
H, M, S, MS: Word;
Offset: Integer;
begin
DecodeTime(ATime, WorkHours, WorkMins, WorkSecs, WorkMSecs);
// Convert the given time to minutes
DecodeTime(GridStartTime, H, M, S, MS);
Offset := H * 60 + M;
TotalMins := WorkHours * 60 + WorkMins - Offset;
// Find the row number by dividing the time in minutes by the granularity
Result := TotalMins div Granularity;
if (TotalMins < 0) and (TotalMins mod Granularity <> 0) then
Dec(Result);
end;
function TJvTFDaysPrinter.GetPageLayout: TJvTFDaysPrinterPageLayout;
begin
Result := TJvTFDaysPrinterPageLayout(inherited PageLayout);
end;
procedure TJvTFDaysPrinter.SetPageLayout(Value: TJvTFDaysPrinterPageLayout);
begin
inherited PageLayout := Value;
end;
procedure TJvTFDaysPrinter.CreateDoc;
var
I: Integer;
begin
inherited CreateDoc;
FApptCount := 0;
for I := 0 to Cols.Count - 1 do
Inc(FApptCount, Cols[I].Schedule.ApptCount);
end;
function TJvTFDaysPrinter.GetApptCount: Integer;
var
I: Integer;
begin
if State = spsNoDoc then
begin
Result := 0;
for I := 0 to Cols.Count - 1 do
Inc(Result, Cols[I].Schedule.ApptCount);
end
else
Result := FApptCount;
end;
function TJvTFDaysPrinter.GetPageInfo(PageNum: Integer): TJvTFDaysPageInfo;
begin
if not FValidPageInfo then
raise EJvTFPrinterError.CreateRes(@RsENoPageInfoExists);
Result := TJvTFDaysPageInfo(FPageInfoList.Objects[PageNum - 1]);
end;
procedure TJvTFDaysPrinter.FreeDoc;
begin
inherited FreeDoc;
// Do not call ClearPageInfo if component is being destroyed. This must be
// done in TJvTFDaysPrinter.Destroy. TJvTFPrinter.Destroy calls FreeDoc
// and since TJvTFDaysPrinter.Destroy frees FPageInfo a NASTY AV happens.
if not (csDestroying in ComponentState) then
ClearPageInfo;
end;
procedure TJvTFDaysPrinter.SetFormattedDesc(Value: Boolean);
begin
SetPropertyCheck;
FFormattedDesc := Value;
end;
procedure TJvTFDaysPrinter.SetGroupHdrAttr(Value: TJvTFDaysHdrAttr);
begin
SetPropertyCheck;
FGroupHdrAttr.Assign(Value);
end;
procedure TJvTFDaysPrinter.SetGroupHdrHeight(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
FGroupHdrHeight := Value;
end;
procedure TJvTFDaysPrinter.SetGrouping(Value: TJvTFDaysGrouping);
begin
SetPropertyCheck;
FGrouping := Value;
Cols.UpdateTitles;
end;
procedure TJvTFDaysPrinter.DrawColGroupHdr(ACanvas: TCanvas;
Index: Integer; PageInfo: TJvTFDaysPageInfo; IsGroupHdr: Boolean);
var
ARect, TxtRect, CalcRect: TRect;
Txt: string;
Flags: UINT;
TxtHt, TxtRectHt: Integer;
UseAttr: TJvTFDaysHdrAttr;
begin
if IsGroupHdr then
begin
ARect := VirtualGroupHdrRect(Index, PageInfo);
Txt := Cols[Index].GroupTitle;
UseAttr := GroupHdrAttr;
end
else
begin
ARect := CellRect(Index, -1, PageInfo);
Txt := Cols[Index].Title;
UseAttr := HdrAttr;
end;
ACanvas.Brush.Color := UseAttr.Color;
ACanvas.Font.Assign(UseAttr.Font);
Flags := DT_NOPREFIX or DT_CENTER;
case ColTitleStyle of
ctsSingleClip:
Flags := Flags or DT_SINGLELINE or DT_VCENTER;
ctsSingleEllipsis:
Flags := Flags or DT_END_ELLIPSIS or DT_SINGLELINE or DT_VCENTER;
ctsMultiClip:
Flags := Flags or DT_WORDBREAK;
ctsMultiEllipsis:
Flags := Flags or DT_END_ELLIPSIS or DT_WORDBREAK or DT_EDITCONTROL;
ctsHide:
Flags := Flags or DT_SINGLELINE or DT_VCENTER;
end;
ACanvas.FillRect(ARect);
TxtRect := ARect;
InflateRect(TxtRect, -2, -2);
CalcRect := TxtRect;
if (ColTitleStyle = ctsMultiClip) or (ColTitleStyle = ctsMultiEllipsis) then
begin
TxtHt := DrawText(ACanvas.Handle, PChar(Txt), -1, CalcRect,
Flags or DT_CALCRECT);
if TxtHt < RectHeight(TxtRect) then
begin
// we need to vertically center the text
TxtRectHt := RectHeight(TxtRect);
TxtRect.Top := TxtRect.Top + RectHeight(TxtRect) div 2 - TxtHt div 2;
TxtRect.Bottom := Lesser(TxtRect.Top + TxtRectHt, TxtRect.Bottom);
end;
end
else
if ColTitleStyle = ctsHide then
begin
DrawText(ACanvas.Handle, PChar(Txt), -1, CalcRect, Flags or DT_CALCRECT);
if RectWidth(CalcRect) > RectWidth(TxtRect) then
Txt := '';
end;
DrawText(ACanvas.Handle, PChar(Txt), -1, TxtRect, Flags);
DrawFrame(ACanvas, ARect, HdrAttr.Frame3D);
if IsGroupHdr then
begin
if Assigned(FOnDrawGroupHdr) then
FOnDrawGroupHdr(Self, ACanvas, ARect, Index, False);
end
else
if Assigned(FOnDrawColHdr) then
FOnDrawColHdr(Self, ACanvas, ARect, Index, False);
end;
procedure TJvTFDaysPrinter.DrawGroupHdrs(ACanvas: TCanvas;
PageInfo: TJvTFDaysPageInfo);
var
CurrGroup: string;
I: Integer;
begin
if CalcGroupHdrHeight > 0 then
begin
CurrGroup := Cols[PageInfo.StartCol].GroupTitle;
DrawColGroupHdr(ACanvas, PageInfo.StartCol, PageInfo, True);
for I := PageInfo.StartCol + 1 to PageInfo.EndCol do
if Cols[I].GroupTitle <> CurrGroup then
begin
CurrGroup := Cols[I].GroupTitle;
DrawColGroupHdr(ACanvas, I, PageInfo, True);
end;
end;
end;
function TJvTFDaysPrinter.CalcGroupColHdrsHeight: Integer;
begin
Result := CalcGroupHdrHeight + ColHdrHeight;
end;
function TJvTFDaysPrinter.CalcGroupHdrHeight: Integer;
begin
if Grouping = grNone then
Result := 0
else
Result := GroupHdrHeight;
end;
function TJvTFDaysPrinter.VirtualGroupHdrRect(Col: Integer;
APageInfo: TJvTFDaysPageInfo): TRect;
var
I, GroupWidth: Integer;
GroupStartCol: Integer = 0; // to silence the compiler
GroupEndCol: Integer = 0; // dto.
begin
Result.Top := 0;
Result.Bottom := CalcGroupHdrHeight;
GetGroupStartEndCols(Col, GroupStartCol, GroupEndCol);
GroupWidth := 0;
for I := GroupStartCol to GroupEndCol do
Inc(GroupWidth, APageInfo.ColWidth);
Result.Left := RowHdrWidth;
// At most, only one of the following For loops will execute
// depending on whether Col is to the left or to the right of LeftCol
//For I := LeftCol - 1 downto GroupStartCol do
for I := APageInfo.StartCol - 1 downto GroupStartCol do
Dec(Result.Left, APageInfo.ColWidth);
//For I := LeftCol to GroupStartCol - 1 do
for I := APageInfo.StartCol to GroupStartCol - 1 do
Inc(Result.Left, APageInfo.ColWidth);
Result.Right := Result.Left + GroupWidth;
end;
procedure TJvTFDaysPrinter.GetGroupStartEndCols(Col: Integer;
var StartCol, EndCol: Integer);
var
I: Integer;
begin
// find group start col
I := Col;
while (I >= 0) and (Cols[I].GroupTitle = Cols[Col].GroupTitle) do
begin
StartCol := I;
Dec(I);
end;
// find group end col
I := Col;
while (I < Cols.Count) and (Cols[I].GroupTitle = Cols[Col].GroupTitle) do
begin
EndCol := I;
Inc(I);
end;
end;
procedure TJvTFDaysPrinter.PrintDirect;
begin
DirectPrint := True;
try
try
Prepare;
finally
FreeDoc;
end;
finally
DirectPrint := False;
end;
end;
procedure TJvTFDaysPrinter.GetApptDrawInfo(DrawInfo: TJvTFDaysApptDrawInfo;
Appt: TJvTFAppt);
begin
DrawInfo.Color := GetApptDispColor(Appt);
DrawInfo.FrameColor := ApptAttr.FrameColor;
DrawInfo.FrameWidth := ApptAttr.FrameWidth;
DrawInfo.Font := ApptAttr.Font;
FixFont(DrawInfo.Font);
DrawInfo.Visible := True;
if Assigned(FOnGetApptDrawInfo) then
FOnGetApptDrawInfo(Self, Appt, DrawInfo);
end;
procedure TJvTFDaysPrinter.SetGridEndTime(Value: TTime);
var
I: Integer;
WorkEnd: TTime;
H, M, S, MS: Word;
begin
WorkEnd := Value;
DecodeTime(WorkEnd, H, M, S, MS);
if (H = 0) and (M = 0) then
WorkEnd := EncodeTime(23, 59, 59, 999);
if not (csLoading in ComponentState) and (WorkEnd <= GridStartTime) then
raise EJvTFDaysError.CreateRes(@RsEGridEndTimeCannotBePriorToGridStart);
FGridEndTime := Value;
if not (csLoading in ComponentState) then
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
end;
procedure TJvTFDaysPrinter.SetGridStartTime(Value: TTime);
var
I: Integer;
WorkEnd: TTime;
H, M, S, MS: Word;
begin
WorkEnd := GridEndTime;
DecodeTime(WorkEnd, H, M, S, MS);
if (H = 0) and (M = 0) then
WorkEnd := EncodeTime(23, 59, 59, 999);
if not (csLoading in ComponentState) and (Value >= WorkEnd) then
raise EJvTFDaysError.CreateRes(@RsEGridStartTimeCannotBeAfterGridEndTi);
FGridStartTime := Value;
if not (csLoading in ComponentState) then
for I := 0 to Cols.Count - 1 do
Cols[I].RefreshMap;
end;
//=== { TJvTFDaysPrinterPageLayout } =========================================
procedure TJvTFDaysPrinterPageLayout.Assign(Source: TPersistent);
begin
inherited Assign(Source);
if Source is TJvTFDaysPrinterPageLayout then
begin
FColsPerPage := TJvTFDaysPrinterPageLayout(Source).ColsPerPage;
FRowsPerPage := TJvTFDaysPrinterPageLayout(Source).RowsPerPage;
FAlwaysShowColHdr := TJvTFDaysPrinterPageLayout(Source).AlwaysShowColHdr;
FAlwaysShowRowHdr := TJvTFDaysPrinterPageLayout(Source).AlwaysShowRowHdr;
// Don't call Change. Ancestor will call it.
end;
end;
procedure TJvTFDaysPrinterPageLayout.SetAlwaysShowColHdr(Value: Boolean);
begin
SetPropertyCheck;
if Value <> FAlwaysShowColHdr then
begin
FAlwaysShowColHdr := Value;
Change;
end;
end;
procedure TJvTFDaysPrinterPageLayout.SetAlwaysShowRowHdr(Value: Boolean);
begin
SetPropertyCheck;
if Value <> FAlwaysShowRowHdr then
begin
FAlwaysShowRowHdr := Value;
Change;
end;
end;
procedure TJvTFDaysPrinterPageLayout.SetColsPerPage(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
if Value <> FColsPerPage then
begin
FColsPerPage := Value;
Change;
end;
end;
procedure TJvTFDaysPrinterPageLayout.SetRowsPerPage(Value: Integer);
begin
SetPropertyCheck;
if Value < 0 then
Value := 0;
if Value <> FRowsPerPage then
begin
FRowsPerPage := Value;
Change;
end;
end;
//=== { TJvTFCompNamesList } =================================================
procedure TJvTFCompNamesList.Move(CurIndex, NewIndex: Integer);
begin
inherited Move(CurIndex, NewIndex);
if Assigned(FOnMove) then
FOnMove(Self, CurIndex, NewIndex);
end;
{$IFDEF Jv_TIMEBLOCKS}
// ok
//=== { TJvTFDaysTimeBlock } =================================================
constructor TJvTFDaysTimeBlock.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FLength := 1;
FName := 'Block' + IntToStr(Index);
FTitle := Name;
FAllowAppts := True;
end;
procedure TJvTFDaysTimeBlock.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysTimeBlock then
begin
FLength := TJvTFDaysTimeBlock(Source).Length;
FTitle := TJvTFDaysTimeBlock(Source).Title;
FAllowAppts := TJvTFDaysTimeBlock(Source).AllowAppts;
Change;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysTimeBlock.Change;
begin
if Assigned(BlockCollection) and Assigned(BlockCollection.DaysControl) then
BlockCollection.DaysControl.Invalidate;
end;
function TJvTFDaysTimeBlock.GetBlockCollection: TJvTFDaysTimeBlocks;
begin
Result := TJvTFDaysTimeBlocks(Collection);
end;
function TJvTFDaysTimeBlock.GetDisplayName: string;
begin
Result := Name;
if Result = '' then
Result := inherited GetDisplayName;
end;
function TJvTFDaysTimeBlock.GetGridLength: Integer;
var
Days: TJvTFDays;
begin
Days := BlockCollection.DaysControl;
Result := Length * (Days.TimeBlockProps.BlockGran div Days.Granularity);
end;
procedure TJvTFDaysTimeBlock.SetAllowAppts(Value: Boolean);
begin
FAllowAppts := Value;
end;
procedure TJvTFDaysTimeBlock.SetLength(Value: Integer);
begin
if Value < 1 then
Value := 1;
if Value <> FLength then
begin
FLength := Value;
Change;
end;
end;
procedure TJvTFDaysTimeBlock.SetName(const Value: string);
begin
if Value = '' then
raise EJvTFDaysError.CreateRes(@RsEATimeBlockNameCannotBeNull);
if Value <> FName then
if not Assigned(BlockCollection.FindBlock(Value)) then
begin
if Title = Name then
Title := Value;
FName := Value;
Change;
end
else
raise EJvTFDaysError.CreateResFmt(@RsEAnotherTimeBlockWithTheName, [Value]);
end;
procedure TJvTFDaysTimeBlock.SetTitle(const Value: string);
begin
if Value <> FTitle then
begin
FTitle := Value;
Change;
end;
end;
//=== { TJvTFDaysTimeBlocks } ================================================
constructor TJvTFDaysTimeBlocks.Create(ADaysControl: TJvTFDays);
begin
inherited Create(TJvTFDaysTimeBlock);
FDaysControl := ADaysControl;
end;
function TJvTFDaysTimeBlocks.Add: TJvTFDaysTimeBlock;
begin
Result := TJvTFDaysTimeBlock(inherited Add);
end;
procedure TJvTFDaysTimeBlocks.Assign(Source: TPersistent);
var
I: Integer;
begin
if Source is TJvTFDaysTimeBlocks then
begin
BeginUpdate;
try
Clear;
for I := 0 to TJvTFDaysTimeBlocks(Source).Count - 1 do
Add.Assign(TJvTFDaysTimeBlocks(Source).Items[I]);
finally
EndUpdate;
end;
end
else
inherited Assign(Source);
end;
function TJvTFDaysTimeBlocks.BlockByName(const BlockName: string): TJvTFDaysTimeBlock;
begin
Result := FindBlock(BlockName);
if not Assigned(Result) then
raise EJvTFDaysError.CreateResFmt(@RsEATimeBlockWithTheNamesDoesNotExist,
[BlockName]);
end;
function TJvTFDaysTimeBlocks.FindBlock(const BlockName: string): TJvTFDaysTimeBlock;
var
I: Integer;
begin
Result := nil;
I := 0;
while (I < Count) and not Assigned(Result) do
begin
if Items[I].Name = BlockName then
Result := Items[I];
Inc(I);
end;
end;
function TJvTFDaysTimeBlocks.GetItem(Index: Integer): TJvTFDaysTimeBlock;
begin
Result := TJvTFDaysTimeBlock(inherited GetItem(Index));
end;
function TJvTFDaysTimeBlocks.GetOwner: TPersistent;
begin
Result := DaysControl;
end;
procedure TJvTFDaysTimeBlocks.SetItem(Index: Integer;
Value: TJvTFDaysTimeBlock);
begin
inherited SetItem(Index, Value);
end;
//=== { TJvTFDaysBlockProps } ================================================
constructor TJvTFDaysBlockProps.Create(ADaysControl: TJvTFDays);
begin
inherited Create;
FBlockGran := 60;
FDaysControl := ADaysControl;
FBlockHdrWidth := DEFAULT_BLOCK_HDR_WIDTH; // will be scaled by FDaysControl
FBlockHdrAttr := TJvTFDaysHdrAttr.Create(DaysControl);
FSelBlockHdrAttr := TJvTFDaysHdrAttr.Create(DaysControl);
FOffTimeColor := clGray;
FDataDivColor := clBlack;
FSnapMove := True;
FDrawOffTime := True;
with FSelBlockHdrAttr do
begin
Color := clBtnFace;
Font.Color := clBlack;
FrameColor := clBlack;
end;
end;
destructor TJvTFDaysBlockProps.Destroy;
begin
FBlockHdrAttr.Free;
FSelBlockHdrAttr.Free;
inherited Destroy;
end;
procedure TJvTFDaysBlockProps.Assign(Source: TPersistent);
begin
if Source is TJvTFDaysBlockProps then
begin
FBlockGran := TJvTFDaysBlockProps(Source).BlockGran;
FDayStart := TJvTFDaysBlockProps(Source).DayStart;
FBlockHdrWidth := TJvTFDaysBlockProps(Source).BlockHdrWidth;
FBlockHdrAttr.Assign(TJvTFDaysBlockProps(Source).BlockHdrAttr);
FSelBlockHdrAttr.Assign(TJvTFDaysBlockProps(Source).SelBlockHdrAttr);
FOffTimeColor := TJvTFDaysBlockProps(Source).OffTimeColor;
FDataDivColor := TJvTFDaysBlockProps(Source).DataDivColor;
FSnapMove := TJvTFDaysBlockProps(Source).SnapMove;
FDrawOffTime := TJvTFDaysBlockProps(Source).DrawOffTime;
Change;
end
else
inherited Assign(Source);
end;
procedure TJvTFDaysBlockProps.AutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
if IsStoredBlockHdrWidth then
FBlockHdrWidth := round(FBlockHdrWidth * AXProportion);
end;
end;
procedure TJvTFDaysBlockProps.Change;
begin
if Assigned(DaysControl) then
DaysControl.Invalidate;
end;
function TJvTFDaysBlockProps.IsStoredBlockHdrWidth: Boolean;
begin
if Assigned(FDaysControl) then
Result := FBlockHdrWidth <> FDaysControl.Scale96ToFont(DEFAULT_BLOCK_HDR_WIDTH)
else
Result := true;
end;
procedure TJvTFDaysBlockProps.SetBlockGran(Value: Integer);
begin
if csLoading in DaysControl.ComponentState then
begin
FBlockGran := Value;
Exit;
end;
// Enforce minimum granularity of 1 min and max of 60 mins
if Value < 1 then
Value := 1
else
if Value > 60 then
Value := 60;
// Ensure that granularity is evenly divisible by an hour
//while 60 mod Value <> 0 do
//Dec(Value);
Value := Value - 60 mod Value;
if Value <> FBlockGran then
begin
DaysControl.EnsureBlockRules(DaysControl.Granularity, Value, DayStart);
FBlockGran := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetBlockHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FBlockHdrAttr.Assign(Value);
DaysControl.Invalidate;
end;
procedure TJvTFDaysBlockProps.SetBlockHdrWidth(Value: Integer);
begin
if Value <> FBlockHdrWidth then
begin
FBlockHdrWidth := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetDataDivColor(Value: TColor);
begin
if Value <> FDataDivColor then
begin
FDataDivColor := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetDayStart(Value: TTime);
begin
if Value <> FDayStart then
begin
DaysControl.EnsureBlockRules(DaysControl.Granularity, BlockGran, Value);
FDayStart := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetDrawOffTime(Value: Boolean);
begin
if Value <> FDrawOffTime then
begin
FDrawOffTime := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetOffTimeColor(Value: TColor);
begin
if Value <> FOffTimeColor then
begin
FOffTimeColor := Value;
Change;
end;
end;
procedure TJvTFDaysBlockProps.SetSelBlockHdrAttr(Value: TJvTFDaysHdrAttr);
begin
FSelBlockHdrAttr.Assign(Value);
DaysControl.Invalidate;
end;
{$ENDIF Jv_TIMEBLOCKS}
//=== { TJvTFDaysApptDrawInfo } ==============================================
constructor TJvTFDaysApptDrawInfo.Create;
begin
inherited Create;
FFont := TFont.Create;
end;
destructor TJvTFDaysApptDrawInfo.Destroy;
begin
FFont.Free;
inherited Destroy;
end;
procedure TJvTFDaysApptDrawInfo.SetColor(Value: TColor);
begin
FColor := Value;
end;
procedure TJvTFDaysApptDrawInfo.SetFont(Value: TFont);
begin
FFont.Assign(Value);
end;
procedure TJvTFDaysApptDrawInfo.SetFrameColor(Value: TColor);
begin
FFrameColor := Value;
end;
procedure TJvTFDaysApptDrawInfo.SetFrameWidth(const Value: Integer);
begin
FFrameWidth := Value;
end;
procedure TJvTFDaysApptDrawInfo.SetVisible(Value: Boolean);
begin
FVisible := Value;
end;
end.