Files
lazarus-ccr/components/tvplanit/source/vpdayview.pas

2847 lines
79 KiB
ObjectPascal
Raw Normal View History

{*********************************************************}
{* VPDAYVIEW.PAS 1.03 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* 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/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Visual PlanIt *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C) 2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{
This unit contains everything needed for the TVpDayView component (including
the inline editor).
The rendering of Visual PlanIt components is a bit involved. The component's
Paint method calls RenderToCanvas. The RenderToCanvas method of each of
the visual VisualPlanIt controls is repsonsible both for drawing to the
screen (both design and run time) as well as printing. In the case of
printing, the component needs to render itself to an arbitrary rectangle
and possibly rotated (for the screen the rectangle is the ClientRect
and the rotation angle is always zero). To achieve that goal, the
functions in VpCanvasUtils are used to go between the rendering of the
control and the TCanvas that it needs to render to.
The rendering of the DayView is complex. Look at the other components
(MonthView and TaskList are probably the best places to start) before making
changes to the DayView rendering.
The in place editor is currently based off the TCustomEdit class. This can
probably be changed to use a TCustomMemo as its base class. This will
provide multi-line editing capabilities.
}
{$I vp.inc}
{.$DEFINE DEBUGDV} { Causes the DayView to operate in debug mode }
unit VpDayView;
interface
uses
{$IFDEF LCL}
LMessages, LCLProc, LCLType, LCLIntf,
{$ELSE}
Windows, Messages,
{$ENDIF}
Classes, Graphics, Controls, ExtCtrls, StdCtrls, Buttons, Forms, Menus, ImgList,
VpConst, VpBase, VpBaseDS, VpMisc, VpData, VpSR, VpCanvasUtils;
type
TVpLineRec = packed record
Hour: TVpHours;
Minute: Integer;
Time: TDateTime;
Rec: TRect;
end;
TVpColRec = packed record
Rec: TRect;
Date: TDateTime;
end;
type
TVpLineArray = array of TVpLineRec;
type
TVpLineMatrix = array of TVpLineArray;
TVpColRectArray = array of TVpColRec;
TVpDVIconData = record
Show: Boolean;
Bitmap: TBitmap;
end;
TVpDVIconTypes = (itAlarm, itRecurring, itCategory, itCustom);
TVpDVIcons = array [itAlarm..itCustom] of TVpDVIconData;
TVpOnDVBeforeDrawEvent = procedure (Sender: TObject; Event: TVpEvent;
AActive: Boolean; ACanvas: TCanvas; AGutterRect, AEventRect, AIconRect: TRect) of object;
TVpOnDVAfterDrawEvent = procedure (Sender: TObject; Event: TVpEvent;
AActive: Boolean; ACanvas: TCanvas; AGutterRect, AEventRect, AIconRect: TRect) of object;
TVpOnDVDrawIcons = procedure (Sender: TObject; Event: TVpEvent;
var Icons: TVpDVIcons) of object;
TVpDVWrapStyle = (wsNone, wsIconFlow, wsNoFlow);
{ Forward Declarations }
TVpDayView = class;
TVpDvInplaceEdit = class(TCustomEdit)
protected{private}
procedure CreateParams(var Params: TCreateParams); override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
{$IFNDEF LCL}
procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS;
{$ELSE}
procedure WMKillFocus(var Msg: TLMKillFocus); message LM_KILLFOCUS;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
end;
TVpRHAttributes = class(TPersistent)
protected{ private }
FOwner: TVpDayView;
FColor: TColor;
FHourFont: TVpFont;
FMinuteFont: TVpFont;
procedure SetColor(const Value: TColor);
procedure SetHourFont(Value: TVpFont);
procedure SetMinuteFont(Value: TVpFont);
public
constructor Create(AOwner: TVpDayView);
destructor Destroy; override;
property Owner: TVpDayView read FOwner;
published
property HourFont: TVpFont read FHourFont write SetHourFont;
property MinuteFont: TVpFont read FMinuteFont write SetMinuteFont;
property Color: TColor read FColor write SetColor;
end;
TVpAllDayEventAttributes = class(TPersistent)
protected {Private}
FOwner: TWinControl;
FBackgroundColor: TColor;
FEventBackgroundColor: TColor;
FEventBorderColor: TColor;
FFont: TVpFont;
public
constructor Create(AOwner: TWinControl);
destructor Destroy; override;
procedure SetBackGroundColor(Value: TColor);
procedure SetEventBackgroundColor(Value: TColor);
procedure SetFont(Value: TVpFont);
procedure SetEventBorderColor(Value: TColor);
published
property BackgroundColor: TColor
read FBackgroundColor write SetBackGroundColor;
property EventBorderColor: TColor
read FEventBorderColor write SetEventBorderColor;
property EventBackgroundColor: TColor
read FEventBackgroundColor write SetEventBackgroundColor;
property Font: TVpFont
read FFont write SetFont;
end;
TVpCHAttributes = class(TPersistent)
protected{ private }
FOwner: TVpDayView;
FColor: TColor;
FFont: TVpFont;
procedure SetColor(const Value: TColor);
procedure SetFont(Value: TVpFont);
public
constructor Create(AOwner: TVpDayView);
destructor Destroy; override;
property Owner: TVpDayView read FOwner;
published
property Font: TVpFont read FFont write SetFont;
property Color: TColor read FColor write SetColor;
end;
TVpDayViewIconAttributes = class(TPersistent)
private
FShowAlarmBitmap: Boolean;
FShowCategoryBitmap: Boolean;
FShowRecurringBitmap: Boolean;
FAlarmBitmap: TBitmap;
FRecurringBitmap: TBitmap;
FAlarmImageIndex: TImageIndex;
FRecurringImageIndex: TImageIndex;
FShowInPrint: Boolean;
FOwner: TVpLinkableControl;
protected
procedure SetAlarmBitmap(v: TBitmap);
procedure SetAlarmImageIndex(v: TImageIndex);
procedure SetRecurringBitmap(v: TBitmap);
procedure SetRecurringImageIndex(v: TImageIndex);
procedure SetShowAlarmBitmap(const v: Boolean);
procedure SetShowCategoryBitmap(const v: Boolean);
procedure SetShowRecurringBitmap(const v: Boolean);
public
constructor Create(AOwner: TVpLinkableControl);
destructor Destroy; override;
published
property AlarmBitmap: TBitmap
read FAlarmBitmap write SetAlarmBitmap;
property AlarmImageIndex: TImageIndex
read FAlarmImageIndex write SetAlarmImageIndex default -1;
property RecurringBitmap: TBitmap
read FRecurringBitmap write SetRecurringBitmap;
property RecurringImageIndex: TImageIndex
read FRecurringImageIndex write SetRecurringImageIndex default -1;
property ShowAlarmBitmap: Boolean
read FShowAlarmBitmap write SetShowAlarmBitmap default True;
property ShowCategoryBitmap : Boolean
read FShowCategoryBitmap write SetShowCategoryBitmap default True;
property ShowRecurringBitmap : Boolean
read FShowRecurringBitmap write SetShowRecurringBitmap default True;
property ShowInPrint: Boolean
read FShowInPrint write FShowInPrint default True;
end;
{ TVpDayView }
TVpDayView = class(TVpLinkableControl)
private
FComponentHint: TTranslateString;
FHintMode: TVpHintMode;
FMouseEvent: TVpEvent;
FOnHoliday: TVpHolidayEvent;
protected{ private }
FGranularity: TVpGranularity;
FColumnWidth: Integer;
FColor: TColor;
FLineColor: TColor;
FDefTopHour: TVpHours;
FTopHour: TVpHours;
FDateLabelFormat: string;
FShowResourceName: Boolean;
FTopLine: Integer;
FActiveRow: Integer;
FActiveCol: Integer;
FActiveEvent: TVpEvent;
FGutterWidth: Integer;
FDefaultPopup: TPopupMenu;
FLineCount: Integer;
FVisibleLines: Integer;
FTimeFormat: TVpTimeFormat;
FDrawingStyle: TVpDrawingStyle;
FTimeSlotColors: TVpTimeSlotColor;
FRowHeadAttr: TVpRHAttributes;
FHeadAttr: TVpCHAttributes;
FAllDayEventAttr: TVpAllDayEventAttributes;
FDisplayDate: TDateTime;
FScrollBars: TScrollStyle;
FIconAttributes: TVpDayViewIconAttributes;
FWrapStyle: TVpDVWrapStyle;
FDotDotDotColor: TColor;
FShowEventTimes: Boolean;
FAllowInplaceEdit: Boolean;
FDragDropTransparent: Boolean;
FAllowDragAndDrop: Boolean;
FNumDays: Integer;
FIncludeWeekends: Boolean;
FRowLinesStep: Integer;
FShowNavButtons: Boolean;
FFixedDate: Boolean;
FCustomRowHeight: Integer;
FSimpleRowTime: Boolean;
{ event variables }
FOwnerDrawRowHead: TVpOwnerDrawRowEvent;
FOwnerDrawCells: TVpOwnerDrawRowEvent;
FOwnerDrawColHead: TVpOwnerDrawEvent;
FBeforeEdit: TVpBeforeEditEvent;
FAfterEdit: TVpAfterEditEvent;
FOwnerEditEvent: TVpEditEvent;
FOnDrawIcons: TVpOnDVDrawIcons;
FOnBeforeDrawEvent: TVpOnDVBeforeDrawEvent;
FOnAfterDrawEvent: TVpOnDVAfterDrawEvent;
FOnAddEvent: TVpOnAddNewEvent;
{ internal variables }
dvClickTimer: TTimer;
dvLoaded: Boolean;
dvInLinkHandler: Boolean;
dvRowHeight: Integer;
dvColHeadHeight: Integer;
dvRowHeadWidth: Integer;
dvClientVArea: Integer;
dvMouseDownPoint: TPoint;
dvMouseDown: Boolean;
dvEndingEditing: Boolean;
dvDragging: Boolean;
dvDragStartTime: TDateTime;
{ Nav Buttons }
dvDayUpBtn: TSpeedButton;
dvDayDownBtn: TSpeedButton;
dvTodayBtn: TSpeedButton;
dvWeekUpBtn: TSpeedButton;
dvWeekDownBtn: TSpeedButton;
dvLineMatrix: TVpLineMatrix;
dvColRectArray: TVpColRectArray;
dvEventArray: TVpEventArray;
dvActiveEventRec: TRect;
dvActiveIconRec: TRect;
dvInPlaceEditor: TVpDvInPlaceEdit;
dvCreatingEditor: Boolean;
{ the granularity based time increment for each row }
dvTimeIncSize: double;
dvPainting: Boolean;
dvVScrollDelta: Integer;
dvHotPoint: TPoint;
{ property methods }
function GetLastVisibleDate: TDateTime;
function GetRealNumDays(WorkDate: TDateTime) : Integer;
procedure SetDrawingStyle(Value: TVpDrawingStyle);
procedure SetColor(Value: TColor);
procedure SetLineColor(Value: TColor);
procedure SetTopHour(Value: TVpHours);
procedure SetTopLine(Value: Integer);
procedure SetDateLabelFormat(Value: string);
procedure SetGutterWidth(Value: Integer);
procedure SetDefTopHour(Value: TVpHours);
procedure SetGranularity(Value: TVpGranularity);
procedure SetTimeFormat(Value: TVpTimeFormat);
procedure SetNumDays(Value: Integer);
procedure SetIncludeWeekends(Value: Boolean);
procedure SetDisplayDate(Value: TDateTime);
procedure SetVScrollPos;
procedure SetCustomRowHeight(Value: Integer);
procedure SetRowLinesStep(Value: Integer);
procedure SetShowNavButtons(Value: Boolean);
procedure SetShowResourceName(Value: Boolean);
procedure SetSimpleRowTime(Value: Boolean);
procedure SetActiveRow(Value: Integer);
procedure SetActiveCol(Value: Integer);
procedure SetWrapStyle(const v: TVpDVWrapStyle);
procedure SetDotDotDotColor(const v: TColor);
procedure SetShowEventTimes(Value: Boolean);
{ drag-drop methods }
procedure DoStartDrag(var DragObject: TDragObject); override;
procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
{ Hints }
procedure ShowHintWindow(APoint: TPoint; AEvent: TVpEvent);
procedure HideHintWindow;
procedure SetHint(const AValue: TTranslateString); override;
procedure SetHintMode(const AValue: TVpHintMode);
{ Popup }
procedure PopupAddEvent(Sender: TObject);
procedure PopupAddFromICalFile(Sender: TObject);
procedure PopupDeleteEvent(Sender: TObject);
procedure PopupEditEvent(Sender: TObject);
procedure PopupToday(Sender: TObject);
procedure PopupTomorrow(Sender: TObject);
procedure PopupYesterday(Sender: TObject);
procedure PopupNextDay(Sender: TObject);
procedure PopupPrevDay(Sender: TObject);
procedure PopupNextWeek(Sender: TObject);
procedure PopupPrevWeek(Sender: TObject);
procedure PopupNextMonth(Sender: TObject);
procedure PopupPrevMonth(Sender: TObject);
procedure PopupNextYear(Sender: TObject);
procedure PopupPrevYear(Sender: TObject);
procedure PopupPickResourceGroupEvent(Sender: TObject);
procedure PopupDropdownEvent(Sender: TObject);
procedure InitializeDefaultPopup;
{ internal methods }
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
function dvCalcRowHeight(Scale: Extended; UseGran: TVpGranularity): Integer;
function dvCalcVisibleLines(RenderHeight, ColHeadHeight, ARowHeight: Integer;
Scale: Extended; StartLine, StopLine: Integer): Integer;
function dvCalcColHeadHeight(Scale: Extended): Integer;
procedure dvEditInPlace(Sender: TObject);
procedure dvHookUp;
procedure dvNavButtonsClick(Sender: TObject);
procedure dvPopulate;
procedure dvScrollVertical(Lines: Integer);
procedure dvSpawnEventEditDialog(IsNewEvent: Boolean);
procedure dvSetActiveRowByCoord(Pnt: TPoint; Sloppy: Boolean);
procedure dvSetActiveColByCoord(Pnt: TPoint);
procedure EditEvent;
function EditEventAtCoord(APoint: TPoint): Boolean;
procedure EndEdit(Sender: TObject);
function GetEventAtCoord(APoint: TPoint): TVpEvent;
function GetEventRect(AEvent: TVpEvent): TRect;
procedure SetActiveEventByCoord(APoint: TPoint);
procedure SetTimeIntervals(UseGran: TVpGranularity);
{ inherited methods }
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure Loaded; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); override;
procedure MouseEnter; override;
procedure MouseLeave; override;
procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,Y: Integer); override;
procedure Paint; override;
{ message handlers }
procedure VpDayViewInit(var Msg: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF}); message Vp_DayViewInit;
{$IFNDEF LCL}
procedure WMLButtonDblClk(var Msg : TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
procedure WMSize(var Msg: TWMSize); message WM_SIZE;
procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
procedure WMSetFocus(var Msg : TWMSetFocus); message WM_SETFOCUS;
procedure WMEraseBackground (var Msg : TWMERASEBKGND); // ??? wp: missing "message WM_ERASEBKGND"?
procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
{$ELSE}
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
procedure WMSize(var Msg: TLMSize); message LM_SIZE;
procedure WMVScroll(var Msg: TLMVScroll); message LM_VSCROLL;
procedure WMSetFocus(var Msg: TLMSetFocus); message LM_SETFOCUS;
procedure WMEraseBackground(var Msg: TLMERASEBKGND); message LM_ERASEBKGND;
procedure WMLButtonDblClk(var Msg: TLMLButtonDblClk); message LM_LBUTTONDBLCLK;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function BuildEventString(AEvent: TVpEvent; UseAsHint: Boolean): String;
procedure DeleteActiveEvent(Verify: Boolean);
procedure DragDrop(Source: TObject; X, Y: Integer); override;
procedure Invalidate; override;
function IsHoliday(ADate: TDate; out AHolidayName: String): Boolean;
procedure LoadLanguage;
procedure LinkHandler(Sender: TComponent; NotificationType: TVpNotificationType;
const Value: Variant); override;
procedure EditSelectedEvent(IsNewEvent: Boolean = false);
function GetControlType: TVpItemType; override;
procedure AutoScaledPaintToCanvas(PaintCanvas: TCanvas; PaintTo: TRect;
Angle: TVpRotationAngle; RenderDate: TDateTime; StartLine, StopLine: Integer;
UseGran: TVpGranularity);
procedure PaintToCanvas (ACanvas: TCanvas; ARect: TRect; Angle: TVpRotationAngle;
ADate: TDateTime; StartHour, EndHour: TVpHours; UseGran: TVpGranularity);
procedure RenderToCanvas(RenderCanvas: TCanvas; RenderIn: TRect;
Angle: TVpRotationAngle; Scale: Extended; RenderDate: TDateTime;
StartLine, StopLine: Integer; UseGran: TVpGranularity; DisplayOnly: Boolean); override;
{$IF VP_LCL_SCALING = 2}
procedure ScaleFontsPPI(const AToPPI: Integer; const AProportion: Double); override;
{$ELSE}
{$IF VP_LCL_SCALING = 1}
procedure ScaleFontsPPI(const AProportion: Double); override;
{$ENDIF}
{$ENDIF}
property ActiveEvent: TVpEvent read FActiveEvent write FActiveEvent;
property TopHour: TVpHours read FTopHour write SetTopHour;
property TopLine: Integer read FTopLine write SetTopLine;
property LineCount: Integer read FLineCount;
property ActiveRow: Integer read FActiveRow write SetActiveRow;
property ActiveCol: Integer read FActiveCol write SetActiveCol;
property Date: TDateTime read FDisplayDate write SetDisplayDate;
property LastVisibleDate: TDateTime read GetLastVisibleDate;
property VisibleLines: Integer read FVisibleLines;
published
property Align;
property Anchors;
{$IFDEF LCL}
property BorderSpacing;
{$ENDIF}
property Constraints;
property ReadOnly;
property TabStop;
property TabOrder;
property Font;
property AllDayEventAttributes: TVpAllDayEventAttributes read FAllDayEventAttr write FAllDayEventAttr;
property AllowDragAndDrop: Boolean read FAllowDragAndDrop write FAllowDragAndDrop default false;
property AllowInplaceEditing: Boolean read FAllowInplaceEdit write FAllowInplaceEdit default true;
property DotDotDotColor: TColor read FDotDotDotColor write SetDotDotDotColor default clBlack;
property ShowEventTimes: Boolean read FShowEventTimes write SetShowEventTimes default true;
property DragDropTransparent: Boolean read FDragDropTransparent write FDragDropTransparent default false;
property DrawingStyle: TVpDrawingStyle read FDrawingStyle write SetDrawingStyle stored True;
property TimeSlotColors: TVpTimeSlotColor read FTimeSlotColors write FTimeSlotColors;
property HeadAttributes: TVpCHAttributes read FHeadAttr write FHeadAttr;
property RowHeadAttributes: TVpRHAttributes read FRowHeadAttr write FRowHeadAttr;
property IconAttributes: TVpDayViewIconAttributes read FIconAttributes write FIconAttributes;
property Color: TColor read FColor write SetColor;
property OwnerDrawRowHeader: TVpOwnerDrawRowEvent read FOwnerDrawRowHead write FOwnerDrawRowHead;
property OwnerDrawColHeader: TVpOwnerDrawEvent read FOwnerDrawColHead write FOwnerDrawColHead;
property OwnerDrawCells: TVpOwnerDrawRowEvent read FOwnerDrawCells write FOwnerDrawCells;
property ShowResourceName: Boolean read FShowResourceName write SetShowResourceName;
property LineColor: TColor read FLineColor write SetLineColor;
property GutterWidth: Integer read FGutterWidth write SetGutterWidth;
property DateLabelFormat: string read FDateLabelFormat write SetDateLabelFormat;
Property Granularity: TVpGranularity read FGranularity write SetGranularity;
property DefaultTopHour: TVpHours read FDefTopHour write SetDefTopHour;
property TimeFormat: TVpTimeFormat read FTimeFormat write SetTimeFormat;
property IncludeWeekends: Boolean read FIncludeWeekends write SetIncludeWeekends default True;
property NumDays: Integer read FNumDays write SetNumDays default 1;
property WrapStyle: TVpDVWrapStyle read FWrapStyle Write SetWrapStyle default wsIconFlow;
property HintMode: TVpHintMode read FHintMode write SetHintMode default hmPlannerHint;
property ShowNavButtons: Boolean read FShowNavButtons write SetShowNavButtons default true;
property FixedDate: Boolean read FFixedDate write FFixedDate default false;
property RowHeight: Integer read FCustomRowHeight write SetCustomRowHeight default 0;
property RowLinesStep: Integer read FRowLinesStep write SetRowLinesStep default 1;
property SimpleRowTime: Boolean read FSimpleRowTime write SetSimpleRowTime default false;
{events}
property AfterEdit: TVpAfterEditEvent read FAfterEdit write FAfterEdit;
property BeforeEdit: TVpBeforeEditEvent read FBeforeEdit write FBeforeEdit;
property OnAddEvent: TVpOnAddNewEvent read FOnAddEvent write FOnAddEvent;
property OnAfterDrawEvent: TVpOnDVAfterDrawEvent read FOnAfterDrawEvent write FOnAfterDrawEvent;
property OnBeforeDrawEvent: TVpOnDVBeforeDrawEvent read FOnBeforeDrawEvent write FOnBeforeDrawEvent;
property OnDrawIcons: TVpOnDVDrawIcons read FOnDrawIcons Write FOnDrawIcons;
property OnHoliday: TVpHolidayEvent read FOnHoliday write FOnHoliday;
property OnOwnerEditEvent: TVpEditEvent read FOwnerEditEvent write FOwnerEditEvent;
property OnClick;
end;
implementation
uses
{$IFDEF LCL}
DateUtils,
{$ENDIF}
SysUtils, StrUtils, Math, Dialogs,
VpEvntEditDlg, VpDayViewPainter, VpICal;
(*****************************************************************************)
{ TVpTGInPlaceEdit }
constructor TVpDvInPlaceEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
TabStop := False;
BorderStyle := bsNone;
// DoubleBuffered := False;
end;
{=====}
procedure TVpDvInPlaceEdit.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style{$IFNDEF LCL} or ES_MULTILINE{$ENDIF};
end;
{=====}
procedure TVpDvInPlaceEdit.KeyDown(var Key: Word; Shift: TShiftState);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!! WARNING
// !!!!
// !!!! Experimental change below. Verify this change before releasing
// !!!! VP 1.03
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
begin
case Key of
VK_RETURN:
begin
Key := 0;
TVpDayView(Owner).EndEdit(Self);
end;
VK_UP:
begin
Key := 0;
TVpDayView(Owner).ActiveRow := TVpDayView(Owner).ActiveRow - 1;
// !!!! TVpDayView(Owner).EndEdit(Self); !!!! !!!!!!!!!!!!!!!!!!!!!!!!!
end;
VK_DOWN:
begin
Key := 0;
TVpDayView(Owner).ActiveRow := TVpDayView(Owner).ActiveRow + 1;
// !!!! TVpDayView(Owner).EndEdit(Self); !!!! !!!!!!!!!!!!!!!!!!!!!!!!!
end;
VK_ESCAPE:
begin
Key := 0;
Hide;
TVpDayView(Owner).SetFocus;
end;
else
inherited;
end;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDvInPlaceEdit.WMKillFocus(var Msg: TWMKillFocus);
{$ELSE}
procedure TVpDvInPlaceEdit.WMKillFocus(var Msg: TLMKillFocus);
{$ENDIF}
begin
Unused(Msg);
TVpDayView(Owner).EndEdit(self);
end;
{=====}
{ TVpAllDayEventAttributes }
constructor TVpAllDayEventAttributes.Create(AOwner: TWinControl);
begin
FOwner:= AOwner;
FFont := TVpFont.Create(AOwner);
FBackgroundColor := clBtnShadow;
FEventBackgroundColor := clBtnFace;
FEventBorderColor := cl3dDkShadow;
end;
{=====}
destructor TVpAllDayEventAttributes.Destroy;
begin
inherited;
FFont.Free;
end;
{=====}
procedure TVpAllDayEventAttributes.SetBackGroundColor(Value: TColor);
begin
FBackgroundColor := Value;
FOwner.Invalidate;
end;
{=====}
procedure TVpAllDayEventAttributes.SetEventBackgroundColor(Value: TColor);
begin
FEventBackgroundColor := Value;
FOwner.Invalidate;
end;
{=====}
procedure TVpAllDayEventAttributes.SetEventBorderColor(Value: TColor);
begin
FEventBorderColor := Value;
FOwner.Invalidate;
end;
procedure TVpAllDayEventAttributes.SetFont(Value: TVpFont);
begin
FFont.Assign(Value);
FFont.Owner := FOwner;
end;
{=====}
(*****************************************************************************)
{ TVpDayViewIconAttributes }
constructor TVpDayViewIconAttributes.Create(AOwner: TVpLinkableControl);
begin
inherited Create;
FOwner := AOwner;
FAlarmBitmap := TBitmap.Create;
FRecurringBitmap := TBitmap.Create;
FAlarmImageIndex := -1;
FRecurringImageIndex := -1;
FShowAlarmBitmap := True;
FShowCategoryBitmap := True;
FShowRecurringBitmap := True;
FShowInPrint := True;
end;
destructor TVpDayViewIconAttributes.Destroy;
begin
FAlarmBitmap.Free;
FRecurringBitmap.Free;
inherited Destroy;
end;
procedure TVpDayViewIconAttributes.SetAlarmBitmap(v: TBitmap);
begin
FAlarmBitmap.Assign(v);
if Assigned(FOwner) then
FOwner.Invalidate;
end;
procedure TVpDayViewIconAttributes.SetAlarmImageIndex(v: TImageIndex);
begin
if FAlarmImageIndex <> v then
begin
FAlarmImageIndex := v;
if Assigned(FOwner) then
FOwner.Invalidate;
end;
end;
procedure TVpDayViewIconAttributes.SetRecurringBitmap(v: TBitmap);
begin
FRecurringBitmap.Assign(v);
if Assigned(FOwner) then
FOwner.Invalidate;
end;
procedure TVpDayViewIconAttributes.SetRecurringImageIndex(v: TImageIndex);
begin
if FRecurringImageIndex <> v then
begin
FRecurringImageIndex := v;
if Assigned(FOwner) then
FOwner.Invalidate;
end;
end;
procedure TVpDayViewIconAttributes.SetShowAlarmBitmap(const v: Boolean);
begin
if FShowAlarmBitmap <> v then begin
FShowAlarmBitmap := v;
if Assigned(FOwner) then
FOwner.Invalidate
end;
end;
procedure TVpDayViewIconAttributes.SetShowCategoryBitmap(const v: Boolean);
begin
if FShowCategoryBitmap <> v then begin
FShowCategoryBitmap := v;
if Assigned(FOwner) then
FOwner.Invalidate;
end;
end;
procedure TVpDayViewIconAttributes.SetShowRecurringBitmap(const v: Boolean);
begin
if FShowRecurringBitmap <> v then begin
FShowRecurringBitmap := v;
if Assigned(FOwner) then
FOwner.Invalidate
end;
end;
(*****************************************************************************)
{ TVpDayView }
constructor TVpDayView.Create(AOwner: TComponent);
begin
inherited;
ControlStyle := [csCaptureMouse, csOpaque, csDoubleClicks];
HintWindowClass := TVpHintWindow;
{ Create internal classes and stuff }
FTimeSlotColors := TVpTimeSlotColor.Create(self);
FHeadAttr := TVpCHAttributes.Create(self);
FRowHeadAttr := TVpRHAttributes.Create(self);
FAllDayEventAttr := TVpAllDayEventAttributes.Create(self);
dvClickTimer := TTimer.Create(self);
FIconAttributes := TVpDayViewIconAttributes.Create(Self);
{ create Nav buttons }
dvDayUpBtn := TSpeedButton.Create(self);
dvDayUpBtn.Parent := self;
dvDayDownBtn := TSpeedButton.Create(self);
dvDayDownBtn.Parent := self;
dvTodayBtn := TSpeedButton.Create(self);
dvTodayBtn.Parent := self;
dvWeekDownBtn := TSpeedButton.Create(self);
dvWeekDownBtn.Parent := self;
dvWeekUpBtn := TSpeedButton.Create(self);
dvWeekUpBtn.Parent := self;
{ flat }
dvTodayBtn.Flat := true;
dvWeekDownBtn.Flat := true;
dvDayDownBtn.Flat := true;
dvDayUpBtn.Flat := true;
dvWeekUpBtn.Flat := true;
{ transparent }
dvTodayBtn.Transparent := true;
dvWeekDownBtn.Transparent := true;
dvDayDownBtn.Transparent := true;
dvDayUpBtn.Transparent := true;
dvWeekUpBtn.Transparent := true;
{ load their images }
{$IFDEF NEW_ICONS}
LoadGlyphFromRCDATA(dvDayUpBtn.Glyph, 'VpRArrow', 16, 24, 32);
LoadGlyphFromRCDATA(dvDayDownBtn.Glyph, 'VpLArrow', 16, 24, 32);
LoadGlyphFromRCDATA(dvTodayBtn.Glyph, 'VpToday', 16, 24, 32);
LoadGlyphFromRCDATA(dvWeekUpBtn.Glyph, 'VpRArrows', 16, 24, 32);
LoadGlyphFromRCDATA(dvWeekDownBtn.Glyph, 'VpLArrows', 16, 24, 32);
{$ELSE}
dvDayUpBtn.Glyph.LoadFromResourceName(HINSTANCE, 'VPRIGHTARROW');
dvDayDownBtn.Glyph.LoadFromResourceName(HINSTANCE, 'VPLEFTARROW');
dvTodayBtn.Glyph.LoadFromResourceName(HINSTANCE, 'VPTODAY');
dvWeekUpBtn.Glyph.LoadFromResourceName(HINSTANCE, 'VPRIGHTARROWS');
dvWeekDownBtn.Glyph.LoadFromResourceName(HINSTANCE, 'VPLEFTARROWS');
{$ENDIF}
{ set their OnClick handler }
dvDayUpBtn.OnClick := dvNavButtonsClick;
dvDayDownBtn.OnClick := dvNavButtonsClick;
dvTodayBtn.OnClick := dvNavButtonsClick;
dvWeekUpBtn.OnClick := dvNavButtonsClick;
dvWeekDownBtn.OnClick := dvNavButtonsClick;
{ Set up the hints }
dvDayUpBtn.ShowHint := True;
dvDayDownBtn.ShowHint := True;
dvTodayBtn.ShowHint := True;
dvWeekUpBtn.ShowHint := True;
dvWeekDownBtn.ShowHint := True;
{ Set styles and initialize internal variables }
{$IFDEF VERSION4}
// DoubleBuffered := true;
{$ENDIF}
NumDays := 1;
dvInLinkHandler := false;
dvClickTimer.Enabled := false;
dvClickTimer.Interval := ClickDelay;
dvClickTimer.OnTimer := dvEditInPlace;
dvCreatingEditor := false;
FDrawingStyle := ds3d;
dvPainting := false;
FShowNavButtons := true;
FShowResourceName := true;
FColor := clWindow;
FLineColor := clGray;
Granularity := gr30min;
FDefTopHour := h_07;
FDisplayDate := Now;
FFixedDate := false;
FCustomRowHeight := 0;
FRowLinesStep := 1;
FSimpleRowTime := false;
TopHour := FDefTopHour;
FTimeFormat := tf12Hour;
FDateLabelFormat := 'dddddd'; //'dddd, mmmm dd, yyyy';
FColumnWidth := 200;
FScrollBars := ssVertical;
FActiveRow := -1;
FGutterWidth := 7;
dvEndingEditing := False;
FWrapStyle := wsIconFlow;
FDotDotDotColor := clBlack;
FIncludeWeekends := True;
FAllowInplaceEdit := true;
FShowEventTimes := true;
{ set up fonts and colors }
FHeadAttr.Font.Size := 10;
FHeadAttr.Font.Style := [];
FHeadAttr.Color := clBtnFace;
FRowHeadAttr.FHourFont.Size := 18;
FRowHeadAttr.FHourFont.Style := [];
FRowHeadAttr.FMinuteFont.Size := 9;
FRowHeadAttr.FMinuteFont.Style := [];
FRowHeadAttr.Color := clBtnFace;
{$IFNDEF LCL}
FHeadAttr.Font.Name := 'Tahoma';
FRowHeadAttr.FHourFont.Name := 'Tahoma';
FRowHeadAttr.FMinuteFont.Name := 'Tahoma';
{$ENDIF}
SetLength(dvEventArray, MaxVisibleEvents);
DragMode := dmManual;
dvDragging := false;
dvMouseDownPoint := Point(0, 0);
dvMouseDown := false;
// Size
Height := 225;
Width := 265;
// popup menu
FDefaultPopup := TPopupMenu.Create(Self);
Self.PopupMenu := FDefaultPopup;
FDefaultPopup.OnPopup := PopupDropDownEvent;
LoadLanguage;
dvHookUp;
end;
{=====}
destructor TVpDayView.Destroy;
begin
FreeAndNil(dvInplaceEditor);
FTimeSlotColors.Free;
FHeadAttr.Free;
FRowHeadAttr.Free;
FAllDayEventAttr.Free;
dvClickTimer.Free;
FDefaultPopup.Free;
FIconAttributes.Free;
dvDayUpBtn.Free;
dvDayDownBtn.Free;
dvTodayBtn.Free;
dvWeekUpBtn.Free;
dvWeekDownBtn.Free;
inherited;
end;
function TVpDayView.BuildEventString(AEvent: TVpEvent;
UseAsHint: Boolean): String;
var
timeFmt: String;
timeStr: String;
s: String;
res: TVpResource;
grp: TVpResourceGroup;
isOverlayed: Boolean;
showDetails: Boolean;
begin
Result := '';
if (AEvent = nil) or (Datastore = nil) or (Datastore.Resource = nil) then
exit;
grp := Datastore.Resource.Group;
showDetails := (grp <> nil) and (odEventDescription in grp.ShowDetails);
isOverlayed := AEvent.IsOverlayed;
timefmt := GetTimeFormatStr(TimeFormat);
if UseAsHint then begin
{ Usage as hint }
if isOverlayed then begin
grp := Datastore.Resource.Group;
if (odResource in grp.ShowDetails) then begin
res := Datastore.Resources.GetResource(AEvent.ResourceID);
Result := RSOverlayed + ': ' + res.Description;
end else
Result := RSOverlayed;
end else
showDetails := true;
timeStr := IfThen(AEvent.AllDayEvent,
RSAllDay,
FormatDateTime(timeFmt, AEvent.StartTime) + ' - ' + FormatDateTime(timeFmt, AEvent.EndTime)
);
Result := IfThen(Result = '',
timeStr,
Result + LineEnding + timeStr
);
if showDetails then begin
// Event description
Result := Result + LineEnding + LineEnding +
RSEvent + ':' + LineEnding + AEvent.Description;
// Event notes
if (AEvent.Notes <> '') then begin
s := WrapText(AEvent.Notes, MAX_HINT_WIDTH);
s := StripLastLineEnding(s);
Result := Result + LineEnding + LineEnding +
RSNotes + ':' + LineEnding + s;
end;
// Event location
if (AEvent.Location <> '') then
Result := Result + LineEnding + LineEnding +
RSLocation + ':' + LineEnding + AEvent.Location;
end;
end
else
begin
{ Usage as cell text }
if isOverlayed then begin
Result := '[' + RSOverlayedEvent + '] ';
if showDetails then begin
res := Datastore.Resources.GetResource(AEvent.ResourceID);
if res <> nil then
Result := '[' + res.Description + '] '
end;
end else
showDetails := true;
timeStr := IfThen(ShowEventTimes, Format('%s - %s: ', [
FormatDateTime(timeFmt, AEvent.StartTime),
FormatDateTime(timeFmt, AEvent.EndTime)
]));
if showDetails then
Result := IfThen(Result = '',
timeStr + AEvent.Description,
Result + timeStr + AEvent.Description)
else
Result := IfThen(Result = '',
timeStr,
Result + timeStr);
end;
end;
procedure TVpDayView.LoadLanguage;
begin
dvDayUpBtn.Hint := RSNextDay;
dvDayDownBtn.Hint := RSPrevDay;
dvTodayBtn.Hint := RSToday;
dvWeekUpBtn.Hint := RSNextWeek;
dvWeekDownBtn.Hint := RSPrevWeek;
FDefaultPopup.Items.Clear;
InitializeDefaultPopup;
end;
{=====}
procedure TVpDayView.DeleteActiveEvent(Verify: Boolean);
var
DoIt: Boolean;
begin
if ReadOnly then
Exit;
if (FActiveEvent <> nil) and (not FActiveEvent.CanEdit) then
exit;
dvClickTimer.Enabled := false;
EndEdit(self);
DoIt := not Verify;
if FActiveEvent <> nil then begin
if Verify then
DoIt := (MessageDlg(RSConfirmDeleteEvent + #13#10#10 + RSPermanent,
mtConfirmation, [mbYes, mbNo], 0) = mrYes);
if DoIt then begin
FActiveEvent.Deleted := true;
DataStore.PostEvents;
Invalidate;
end;
end;
end;
{=====}
procedure TVpDayView.Invalidate;
begin
inherited;
end;
function TVpDayView.IsHoliday(ADate: TDate; out AHolidayName: String): Boolean;
begin
AHolidayName := '';
if Assigned(FOnHoliday) then
FOnHoliday(Self, ADate, AHolidayName);
Result := AHolidayName <> '';
end;
procedure TVpDayView.LinkHandler(Sender: TComponent;
NotificationType: TVpNotificationType; const Value: Variant);
begin
dvInLinkHandler := true;
try
case NotificationType of
neDateChange : Date := Value;
neDataStoreChange : Invalidate;
neInvalidate : Invalidate;
end;
finally
dvInLinkHandler := false;
end;
end;
{=====}
procedure TVpDayView.dvHookUp;
var
I: Integer;
begin
{ If the component is being dropped on a form at designtime, then }
{ automatically hook up to the first datastore component found }
if csDesigning in ComponentState then
for I := 0 to pred(Owner.ComponentCount) do begin
if (Owner.Components[I] is TVpCustomDataStore) then begin
DataStore := TVpCustomDataStore(Owner.Components[I]);
Exit;
end;
end;
end;
{ Hint support }
procedure TVpDayView.ShowHintWindow(APoint: TPoint; AEvent: TVpEvent);
var
txt: String;
begin
HideHintWindow;
case FHintMode of
hmPlannerHint:
begin
if (AEvent = nil) or (Datastore = nil) or (Datastore.Resource = nil) then
exit;
txt := BuildEventString(AEvent, true);
end;
hmComponentHint:
txt := FComponentHint;
end;
if (txt <> '') and not (csDesigning in ComponentState) and
not ((dvInplaceEditor <> nil) and dvInplaceEditor.Visible) then
begin
Hint := txt;
Application.Hint := Hint;
Application.ActivateHint(ClientToScreen(APoint), true);
end;
end;
procedure TVpDayView.HideHintWindow;
begin
Application.CancelHint;
end;
{ Popup menu }
procedure TVpDayView.InitializeDefaultPopup;
var
NewItem: TMenuItem;
NewSubItem: TMenuItem;
canEdit: Boolean;
begin
canEdit := (FActiveEvent <> nil) and FActiveEvent.CanEdit;
FDefaultPopup.Items.Clear;
if RSPopupAddEvent <> '' then begin // Add
NewItem := TMenuItem.Create(Self);
NewItem.Caption := RSPopupAddEvent;
NewItem.OnClick := PopupAddEvent;
NewItem.Tag := 0;
FDefaultPopup.Items.Add(NewItem);
end;
if RSPopupAddEventFromICal <> '' then begin
NewItem := TMenuItem.Create(Self);
NewItem.Caption := RSPopupAddEventFromICal; // Import from iCal
NewItem.OnClick := PopupAddFromICalFile;
NewItem.Tag := 0;
FDefaultPopup.Items.Add(NewItem);
end;
if RSPopupEditEvent <> '' then begin // Edit
NewItem := TMenuItem.Create(Self);
NewItem.Caption := RSPopupEditEvent;
NewItem.Enabled := canEdit;
NewItem.OnClick := PopupEditEvent;
NewItem.Tag := 1;
FDefaultPopup.Items.Add(NewItem);
end;
if RSPopupDeleteEvent <> '' then begin // Delete
NewItem := TMenuItem.Create(Self);
NewItem.Caption := RSPopupDeleteEvent;
NewItem.Enabled := canEdit;
NewItem.OnClick := PopupDeleteEvent;
NewItem.Tag := 1;
FDefaultPopup.Items.Add(NewItem);
end;
NewItem := TMenuItem.Create(Self); // ----
NewItem.Caption := '-';
FDefaultPopup.Items.Add(NewItem);
if RSPopupChangeDate <> '' then begin // Change date >
NewItem := TMenuItem.Create(Self);
NewItem.Caption := RSPopupChangeDate;
NewItem.Tag := 0;
FDefaultPopup.Items.Add(NewItem);
if RSToday <> '' then begin // Today
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSToday;
NewSubItem.OnClick := PopupToday;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
NewSubItem := TMenuItem.Create(Self); // ---
NewSubItem.Caption := '-';
NewItem.Add(NewSubItem);
if RSYesterday <> '' then begin // Yesterday
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSYesterday;
NewSubItem.OnClick := PopupYesterday;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
if RSTomorrow <> '' then begin // Tomorrow
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSTomorrow;
NewSubItem.OnClick := PopupTomorrow;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
NewSubItem := TMenuItem.Create(Self); // --
NewSubItem.Caption := '-';
NewItem.Add(NewSubItem);
if RSNextDay <> '' then begin // Next day
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSNextDay;
NewSubItem.OnClick := PopupNextDay;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
if RSPrevDay <> '' then begin // Prev day
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSPrevDay;
NewSubItem.OnClick := PopupPrevDay;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
NewSubItem := TMenuItem.Create(Self); // ---
NewSubItem.Caption := '-';
NewItem.Add(NewSubItem);
if RSNextWeek <> '' then begin // Next week
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSNextWeek;
NewSubItem.OnClick := PopupNextWeek;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
if RSPrevWeek <> '' then begin // Prev week
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSPrevWeek;
NewSubItem.OnClick := PopupPrevWeek;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
NewSubItem := TMenuItem.Create(Self); // ---
NewSubItem.Caption := '-';
NewItem.Add(NewSubItem);
if RSNextMonth <> '' then begin // Next month
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSNextMonth;
NewSubItem.OnClick := PopupNextMonth;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
if RSPrevMonth <> '' then begin // Prev Month
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSPrevMonth;
NewSubItem.OnClick := PopupPrevMonth;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
NewSubItem := TMenuItem.Create(Self); // ---
NewSubItem.Caption := '-';
NewItem.Add(NewSubItem);
if RSNextYear <> '' then begin // Next year
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSNextYear;
NewSubItem.OnClick := PopupNextYear;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
if RSPrevYear <> '' then begin // Prev year
NewSubItem := TMenuItem.Create(Self);
NewSubItem.Caption := RSPrevYear;
NewSubItem.OnClick := PopupPrevYear;
NewSubItem.Tag := 0;
NewItem.Add(NewSubItem);
end;
end;
if (Datastore <> nil) and (Datastore.Resource <> nil) then
AddResourceGroupMenu(FDefaultPopup.Items, Datastore.Resource, PopupPickResourceGroupEvent);
end;
{=====}
procedure TVpDayView.PopupAddEvent(Sender: TObject);
var
StartTime: TDateTime;
EndTime: TDateTime;
begin
if ReadOnly or (not CheckCreateResource) or
(not Assigned(DataStore)) or (not Assigned(DataStore.Resource))
then
Exit;
StartTime := trunc(FDisplayDate + ActiveCol) + dvLineMatrix[ActiveCol, ActiveRow].Time;
EndTime := StartTime + dvTimeIncSize * FRowLinesStep;
FActiveEvent := DataStore.Resource.Schedule.AddEvent(
DataStore.GetNextID(EventsTableName),
StartTime,
EndTime
);
Repaint;
{ edit this new event }
dvSpawnEventEditDialog(True);
end;
procedure TVpDayView.PopupAddFromICalFile(Sender: TObject);
var
dlg: TOpenDialog;
ical: TVpICalendar;
fn: String;
i: Integer;
id: Integer;
startTime, endTime: TDateTime;
begin
if ReadOnly or (not CheckCreateResource) or
(not Assigned(DataStore)) or (not Assigned(DataStore.Resource))
then
Exit;
dlg := TOpenDialog.Create(nil);
try
dlg.Title := RSLoadICalTitle;
dlg.Filter := RSICalFilter;
dlg.FileName := '';
dlg.Options := dlg.Options + [ofAllowMultiSelect, ofFileMustExist];
if dlg.Execute then begin
Screen.Cursor := crHourGlass;
Application.ProcessMessages;
ical := TVpICalendar.Create;
try
for fn in dlg.Files do begin
ical.LoadFromFile(fn);
for i := 0 to ical.Count-1 do begin
if not (ical[i] is TVpICalEvent) then
Continue;
startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times
endTime := TVpICalEvent(ical[i]).EndTime[false];
if (startTime = 0) and (endTime = 0) then
continue;
id := DataStore.GetNextID(EventsTableName);
FActiveEvent := Datastore.Resource.Schedule.AddEvent(id, starttime, endtime);
FActiveEvent.Changed := true;
FActiveEvent.LoadFromICalendar(TVpICalEvent(ical[i]));
Datastore.PostEvents;
Datastore.NotifyDependents;
end;
end;
Invalidate;
finally
ical.Free;
Screen.Cursor := crDefault;
end;
end;
finally
dlg.Free;
end;
end;
procedure TVpDayView.PopupDeleteEvent(Sender: TObject);
begin
if ReadOnly then
Exit;
Repaint;
if FActiveEvent <> nil then
DeleteActiveEvent (True);
end;
{=====}
procedure TVpDayView.PopupEditEvent(Sender: TObject);
begin
if ReadOnly then
Exit;
Repaint;
if FActiveEvent <> nil then
{ edit this Event }
dvSpawnEventEditDialog(False);
end;
{=====}
procedure TVpDayView.PopupToday(Sender: TObject);
begin
Date := Now;
end;
{=====}
procedure TVpDayView.PopupTomorrow(Sender: TObject);
begin
Date := Now + 1;
end;
{=====}
procedure TVpDayView.PopupYesterday(Sender: TObject);
begin
Date := Now - 1;
end;
{=====}
procedure TVpDayView.PopupNextDay(Sender: TObject);
begin
Date := Date + 1;
end;
{=====}
procedure TVpDayView.PopupPrevDay(Sender: TObject);
begin
Date := Date - 1;
end;
{=====}
procedure TVpDayView.PopupNextWeek(Sender: TObject);
begin
Date := Date + 7;
end;
{=====}
procedure TVpDayView.PopupPrevWeek(Sender: TObject);
begin
Date := Date - 7;
end;
{=====}
procedure TVpDayView.PopupNextMonth(Sender: TObject);
var
M, D, Y: Word;
begin
DecodeDate(Date, Y, M, D);
if M = 12 then begin
M := 1;
Y := Y + 1;
end else
M := M + 1;
if (D > DaysInAMonth(Y, M)) then
D := DaysInAMonth(Y, M);
Date := EncodeDate(Y, M, D);
end;
{=====}
procedure TVpDayView.PopupPrevMonth(Sender: TObject);
var
M, D, Y: Word;
begin
DecodeDate(Date, Y, M, D);
if M = 1 then begin
M := 12;
Y := Y - 1;
end else
M := M - 1;
if (D > DaysInAMonth(Y, M)) then
D := DaysInAMonth(Y, M);
Date := EncodeDate(Y, M, D);
end;
{=====}
procedure TVpDayView.PopupNextYear(Sender: TObject);
var
M, D, Y : Word;
begin
DecodeDate(Date, Y, M, D);
Date := EncodeDate(Y + 1, M, 1);
end;
{=====}
procedure TVpDayView.PopupPrevYear(Sender: TObject);
var
M, D, Y: Word;
begin
DecodeDate(Date, Y, M, D);
Date := EncodeDate(Y - 1, M, 1);
end;
{=====}
procedure TVpDayView.PopupPickResourceGroupEvent(Sender: TObject);
begin
Datastore.Resource.Group := TVpResourceGroup(TMenuItem(Sender).Tag);
Datastore.UpdateGroupEvents;
end;
procedure TVpDayView.PopupDropDownEvent(Sender: TObject);
begin
InitializeDefaultPopup;
end;
procedure TVpDayView.Loaded;
begin
inherited;
TopHour := DefaultTopHour;
dvLoaded := true;
dvPopulate;
end;
{=====}
procedure TVpDayView.Paint;
begin
RenderToCanvas(Canvas, Rect(0, 0, Width, Height), ra0, 1, FDisplayDate,
TopLine, -1, FGranularity, False);
SetVScrollPos;
end;
{=====}
procedure TVpDayView.dvPopulate;
begin
if DataStore <> nil then
DataStore.Date := FDisplayDate;
end;
{=====}
procedure TVpDayView.dvNavButtonsClick(Sender: TObject);
begin
{ set the value of Date based on which button was pressed. }
if Sender = dvDayUpBtn then
Date := Date + 1
else if Sender = dvDayDownBtn then
Date := Date - 1
else if Sender = dvTodayBtn then
Date := trunc(Now)
else if Sender = dvWeekUpBtn then
Date := Date + 7
else if Sender = dvWeekDownBtn then
Date := Date - 7;
end;
{=====}
function TVpDayView.dvCalcVisibleLines(RenderHeight, ColHeadHeight, ARowHeight: Integer;
Scale: Extended; StartLine, StopLine: Integer): Integer;
var
vertical: integer;
d: Integer = 0; // d = result of "div"
m: Integer = 0; // m = result of "mod"
begin
if StartLine < 0 then
StartLine := TopLine;
{ take into account the number lines that are allowed! }
// vertical := Round(RenderHeight - ColHeadHeight * Scale - 2);
vertical := Round(RenderHeight - ColHeadHeight * Scale);
DivMod(Vertical, ARowHeight, d, m);
Result := d + ord(m <> 0);
{
if Vertical mod ARowHeight = 0 then
Result :=
Result := Vertical div ARowHeight + 1; // - 4; //+2;
}
if Result > FLineCount then
Result := FLineCount;
if (StopLine > 0) and (StopLine > StartLine) and (Result > Stopline-StartLine) then
Result := StopLine - StartLine + 1;
{
if (StopLine > 0) and (StopLine > StartLine) then
if Result > StopLine - StartLine then
Result := StopLine - StartLine + 2;
}
FVisibleLines := Result;
end;
{=====}
procedure TVpDayView.SetColor(Value: TColor);
begin
if FColor <> Value then begin
FColor := Value;
Invalidate;
end;
end;
{=====}
function TVpDayView.dvCalcColHeadHeight(Scale: Extended): Integer;
var
TextHeight: Integer;
glyphHeights: Integer;
begin
Canvas.Font.Assign(FHeadAttr.Font);
Canvas.Font.Size := ScaleY(Canvas.Font.Size, DesignTimeDPI);
if FShowResourceName and (DataStore <> nil) and (DataStore.Resource <> nil) then
TextHeight := Canvas.TextHeight(TallShortChars) * 2 + TextMargin * 3
else
TextHeight := Canvas.TextHeight(TallShortChars) + TextMargin * 2;
Result := Round(TextHeight * Scale);
if Assigned(dvTodayBtn.Glyph) then begin
glyphHeights := dvDayUpBtn.Glyph.Height + dvTodayBtn.Glyph.Height + 6;
if Result < glyphHeights then Result := glyphHeights;
end;
dvColHeadHeight := Result;
end;
{=====}
procedure TVpDayView.DoStartDrag(var DragObject: TDragObject);
{$IFDEF LCL}
var
P, HotSpot: TPoint;
EventName: string;
{$ENDIF}
begin
DvDragStartTime := 0.0;
if ReadOnly or not FAllowDragAndDrop then
Exit;
if FActiveEvent <> nil then begin
// Set the time from which this event was dragged
DvDragStartTime := trunc(Date + ActiveCol) + dvLineMatrix[ActiveCol, ActiveRow].Time;
{$IFDEF LCL}
EventName := FActiveEvent.Description;
GetCursorPos(P{%H-});
P := TVpDayView(Self).ScreenToClient(P);
HotSpot := Point(P.X - Self.dvActiveEventRec.Left, P.Y - Self.dvActiveEventRec.Top);
DragObject := TVpEventDragObject.CreateWithDragImages(Self as TControl,
HotSpot, Self.dvActiveEventRec, EventName, FDragDropTransparent);
{$ELSE}
DragObject := DragObject := TVpEventDragObject.Create(Self);
{$ENDIF}
TVpEventDragObject(DragObject).Event := FActiveEvent;
end
else
{$IFDEF LCL}
CancelDrag;
{$ELSE}
DragObject.Free;//EndDrag(false);
{$ENDIF}
end;
{=====}
procedure TVpDayView.DoEndDrag(Target: TObject; X, Y: Integer);
begin
Unused(Target, X, Y);
if ReadOnly or (not FAllowDragAndDrop) then
Exit;
{$IFNDEF LCL}
TVpEventDragObject(Target).Free;
{$ENDIF}
// not needed for LCL: we use DragObjectEx !!
end;
{=====}
procedure TVpDayView.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
begin
Unused(Source, State);
if ReadOnly or (not FAllowDragAndDrop) then begin
Accept := False;
Exit;
end;
if (X > dvRowHeadWidth + GutterWidth) and (Y > dvColHeadHeight) then begin
{ The mouse is dragging over the client area }
dvSetActiveColByCoord(Point(X, Y));
dvSetActiveRowByCoord(Point(X, Y), False);
Accept := true;
end else
Accept := false;
end;
{=====}
procedure TVpDayView.DragDrop(Source: TObject; X, Y: Integer);
var
Event: TVpEvent;
Duration: TDateTime;
DragToTime: TDateTime;
i: Integer;
begin
Unused(X, Y);
if ReadOnly or (not FAllowDragAndDrop) then
Exit;
Event := TVpEventDragObject(Source).Event;
if Event <> nil then begin
Duration := Event.EndTime - Event.StartTime;
DragToTime := trunc(Date + ActiveCol) + dvLineMatrix[ActiveCol, ActiveRow].Time;
if Ord(Event.RepeatCode) = 0 then
{ if this is not a recurring event then just drop it here }
Event.StartTime := DragToTime
else
{ if this is a recurring event, then modify the event's start time
according to how far the event was dragged }
Event.StartTime := Event.StartTime + (DragToTime - DvDragStartTime);
Event.EndTime := Event.StartTime + Duration;
DataStore.PostEvents;
{ Force a repaint. This will update the rectangles for the event }
Repaint;
{ Reset the active event rectangle }
for I := 0 to pred(Length(dvEventArray)) do begin
if dvEventArray[I].Event = nil then
Break;
if dvEventArray[i].Event = Event then begin
dvActiveEventRec := dvEventArray[I].Rec;
dvActiveIconRec := dvEventArray[I].IconRect;
Break;
end;
end;
{ Invalidate; }
end;
// TVpEventDragObject(Source).EndDrag(False);
end;
{=====}
function TVpDayView.dvCalcRowHeight(Scale: Extended;
UseGran: TVpGranularity): Integer;
var
SaveFont: TFont;
Temp: Integer;
begin
{ Calculates row height based on the largest of the RowHead's Minute }
{ font, the standard client font, and a sample character string. }
SaveFont := Canvas.Font;
Canvas.Font.Assign(FRowHeadAttr.FMinuteFont);
Canvas.Font.Size := ScaleY(Canvas.Font.Size, DesignTimeDPI);
Canvas.Font.Height := GetRealFontHeight(Canvas.Font);
Result := Canvas.TextHeight(TallShortChars);
Canvas.Font.Assign(SaveFont);
Temp := Canvas.TextHeight(TallShortChars);
if Temp > Result then
Result := Temp;
if FCustomRowHeight = 0 then
Result := Result + TextMargin * 2
else
Result := FCustomRowHeight;
Result := Round(Result * Scale);
dvClientVArea := Result * MinutesInDay div GranularityMinutes[UseGran];
dvRowHeight := Result;
end;
{=====}
function TVpDayView.GetLastVisibleDate: TDateTime;
begin
Result := Date + GetRealNumDays(Date);
end;
{=====}
function TVpDayView.GetRealNumDays(WorkDate: TDateTime) : Integer;
var
i: Integer;
begin
if not FIncludeWeekends then begin
Result := 0;
i := 0;
while i < FNumDays do begin
if (DayOfWeek(WorkDate) <> 1) and (DayOfWeek(WorkDate) <> 7) then
Inc(i);
WorkDate := WorkDate + 1;
Inc(Result);
end;
end else
Result := FNumDays;
end;
{=====}
procedure TVpDayView.SetDrawingStyle(Value: TVpDrawingStyle);
begin
if FDrawingStyle <> Value then begin
FDrawingStyle := Value;
Repaint;
end;
end;
{=====}
procedure TVpDayView.SetLineColor(Value: TColor);
begin
if FLineColor <> Value then begin
FLineColor := Value;
Repaint;
end;
end;
{=====}
procedure TVpDayView.SetTopHour(Value: TVpHours);
begin
if FTopHour <> Value then begin
FTopHour := Value;
TopLine := HourToLine(FTopHour, FGranularity);
end;
end;
{=====}
procedure TVpDayView.SetTopLine(Value: Integer);
begin
if Value <> FTopLine then begin
if Value + VisibleLines >= pred(LineCount) then begin
// FTopLine := pred(LineCount) - VisibleLines + 2; // why +2?
FTopLine := pred(LineCount) - VisibleLines;
if FTopLine < 0 then FTopLine := 0;
{ prevent the control from hanging at the bottom }
if (Value < FTopLine) and (Value > 0) then
FTopLine := Value;
end
else if Value < 0 then
FTopLine := 0
else
FTopLine := Value;
Invalidate;
SetVScrollPos;
end;
end;
{=====}
procedure TVpDayView.SetDateLabelFormat(Value: string);
begin
if Value <> FDateLabelFormat then begin
FDateLabelFormat := Value;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetGutterWidth(Value: Integer);
begin
if (Value <> FGutterWidth) and (Value > -1) and (Value < Width div 10) then
begin
FGutterWidth := Value;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetDefTopHour(Value: TVpHours);
begin
if Value <> FDefTopHour then begin
FDefTopHour := Value;
if csDesigning in ComponentState then
TopHour := Value;
end;
end;
{=====}
procedure TVpDayView.SetTimeIntervals(UseGran: TVpGranularity);
var
I, J: Integer;
grPerHour: Integer;
begin
FLineCount := MinutesInDay div GranularityMinutes[UseGran];
dvTimeIncSize := GranularityMinutes[UseGran] / MinutesInDay;
grPerHour := 60 div GranularityMinutes[UseGran];
SetLength(dvLineMatrix, NumDays);
for I := 0 to pred(NumDays) do begin
SetLength(dvLineMatrix[I], LineCount + 1); // was +1. Why? Without it, the IDE crashes! - there is an upper loop index of LineCount in DrawCells. After correcting that, the crash is gone.
// wp: the additional line is needed to fully display the last line of the day.
for J := 0 to pred(LineCount) do begin
dvLineMatrix[I,J].Hour := TVpHours(J div grPerHour);
dvLineMatrix[I,J].Minute := (J mod grPerHour) * GranularityMinutes[UseGran];
dvLineMatrix[I,J].Time := ord(dvLineMatrix[I,J].Hour) / 24 + dvTimeIncSize * (J mod grPerHour);
end;
end;
if FLineCount <= FVisibleLines then
FTopLine := HourToLine(h_00, FGranularity);
SetVScrollPos;
end;
procedure TVpDayView.SetGranularity(Value: TVpGranularity);
begin
FGranularity := Value;
SetTimeIntervals(FGranularity);
FTopLine := HourToLine(FTopHour, FGranularity);
if dvRowHeight <> 0 then
dvCalcVisibleLines(Height, dvColHeadHeight, dvRowHeight, 1, FTopLine, -1);
if (FGranularity = gr60Min) and (FVisibleLines = LineCount) then
FTopLine := 0;
Invalidate;
end;
{=====}
procedure TVpDayView.SetTimeFormat(Value: TVpTimeFormat);
begin
if Value <> FTimeFormat then begin
FTimeFormat := Value;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetDisplayDate(Value: TDateTime);
begin
if (not FFixedDate) and (FDisplayDate <> Value) then begin
EndEdit(self);
FDisplayDate := Value;
if dvLoaded then
dvPopulate;
Invalidate;
if (not dvInLinkHandler) and (ControlLink <> nil) then
ControlLink.Notify(self, neDateChange, Date);
end;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.WMSize(var Msg: TWMSize);
{$ELSE}
procedure TVpDayView.WMSize(var Msg: TLMSize);
{$ENDIF}
var
MaxLinesToDraw: Integer;
EmptyLines: Integer;
begin
inherited;
{ How many lines are there between TopLine and the last line of the day. }
MaxLinesToDraw := Length(dvLineMatrix[0]) - TopLine;
EmptyLines := FVisibleLines - MaxLinesToDraw;
if EmptyLines > 0 then
TopLine := TopLine - EmptyLines
else
Invalidate;
end;
{=====}
procedure TVpDayView.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
Style := Style or WS_TABSTOP;
if FScrollBars in [ssVertical, ssBoth] then Style := Style or WS_VSCROLL;
if FScrollBars in [ssHorizontal, ssBoth] then Style := Style or WS_HSCROLL;
{$IFNDEF LCL}
WindowClass.style := CS_DBLCLKS;
{$ENDIF}
end;
end;
{=====}
procedure TVpDayView.CreateWnd;
begin
inherited;
PostMessage (Handle, Vp_DayViewInit, 0, 0);
end;
procedure TVpDayView.MouseEnter;
begin
FMouseEvent := nil;
end;
procedure TVpDayView.MouseLeave;
begin
HideHintWindow;
end;
procedure TVpDayView.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if Button = mbLeft then
begin
dvMouseDownPoint := Point(0, 0);
dvMouseDown := false;
dvDragging := false;
end
else
begin
end;
end;
procedure TVpDayView.MouseMove(Shift: TShiftState; X, Y: Integer);
var
event: TVpEvent;
begin
inherited MouseMove(Shift, X, Y);
if (FActiveEvent <> nil) and (not ReadOnly) then begin
if (not dvDragging) and dvMouseDown and
((dvMouseDownPoint.x <> x) or (dvMouseDownPoint.y <> y)) and
FActiveEvent.CanEdit
then begin
dvDragging := true;
dvClickTimer.Enabled := false;
BeginDrag(true);
end;
end;
if ShowHint then
begin
event := GetEventAtCoord(Point(X, Y));
if event = nil then
HideHintWindow
else
if FMouseEvent <> event then begin
// HideHintWindow;
ShowHintWindow(Point(X, Y), event);
FMouseEvent := event;
end;
end;
end;
procedure TVpDayView.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
i: Integer;
begin
inherited MouseDown(Button, Shift, X, Y);
if Button = mbLeft then
begin
dvMouseDownPoint := Point(x, y);
dvMouseDown := true;
{ if the mouse was pressed down in the client area, then select the cell. }
if not focused then SetFocus;
if (x > dvRowHeadWidth - 9) and (y > dvColHeadHeight) then
begin
{ The mouse click landed inside the client area }
dvSetActiveColByCoord(Point(x, y));
dvSetActiveRowByCoord(Point(x, y), True);
if not ReadOnly then
EditEventAtCoord(Point(x, y));
end else
if y > dvColHeadHeight then
dvSetActiveRowByCoord(Point (x, y), True);
if Assigned(OnClick) then
OnClick(self);
end
else begin
if not Focused then
SetFocus;
if (x > dvRowHeadWidth - 9) and (y > dvColHeadHeight) then
begin
{ The mouse click landed inside the client area }
dvSetActiveColByCoord(Point(x, y));
dvSetActiveRowByCoord(Point(x, y), True);
end;
EditEventAtCoord(Point (x, y));
dvClickTimer.Enabled := false;
if not Assigned(FActiveEvent) then
for i := 0 to FDefaultPopup.Items.Count - 1 do begin
if (FDefaultPopup.Items[i].Tag = 1) or (ReadOnly) then
FDefaultPopup.Items[i].Enabled := False;
end
else
for i := 0 to FDefaultPopup.Items.Count - 1 do
FDefaultPopup.Items[i].Enabled := True;
end;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.WMLButtonDblClk(var Msg: TWMLButtonDblClk);
{$ELSE}
procedure TVpDayView.WMLButtonDblClk(var Msg: TLMLButtonDblClk);
{$ENDIF}
var
StartTime, EndTime: TDateTime;
begin
inherited;
dvClickTimer.Enabled := false;
dvMouseDownPoint := Point(0, 0);
dvMouseDown := false;
dvDragging := false;
{ if the mouse was pressed down in the client area, then select the cell. }
if not focused then SetFocus;
if (Msg.XPos > dvRowHeadWidth - 9) and (Msg.YPos > dvColHeadHeight) then
begin
{ The mouse click landed inside the client area }
dvSetActiveRowByCoord(Point(Msg.XPos, Msg.YPos), True);
{ See if we hit an active event }
if (FActiveEvent <> nil) and (not ReadOnly) then begin
{ edit this event }
dvSpawnEventEditDialog(False);
end else if not ReadOnly then begin
if not CheckCreateResource then
Exit;
if (DataStore = nil) or (DataStore.Resource = nil) then
Exit;
{ otherwise, we must want to create a new event }
StartTime := trunc(FDisplayDate + ActiveCol)
+ dvLineMatrix[ActiveCol, ActiveRow].Time;
EndTime := StartTime + dvTimeIncSize * FRowLinesStep;
FActiveEvent := DataStore.Resource.Schedule.AddEvent(
DataStore.GetNextID(EventsTableName), StartTime, EndTime);
{ edit this new event }
dvSpawnEventEditDialog(True);
end;
end;
end;
{=====}
{$IFDEF LCL}
function TVpDayView.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
end;
function TVpDayView.DoMouseWheelDown(Shift: TShiftState;
MousePos: TPoint): Boolean;
var
delta: Integer;
begin
Result := inherited DoMouseWheelDown(Shift, MousePos);
if not Result then begin
if [ssCtrl, ssShift] * Shift <> [] then begin
delta := HourToLine(h_01, FGranularity);
if delta = 1 then delta := 3;
end else
delta := 1;
dvScrollVertical(delta);
Result := True;
end;
end;
function TVpDayView.DoMouseWheelUp(Shift: TShiftState;
MousePos: TPoint): Boolean;
var
delta: Integer;
begin
Result := inherited DoMouseWheelUp(Shift, MousePos);
if not Result then begin
if [ssCtrl, ssShift] * Shift <> [] then begin
delta := HourToLine(h_01, FGranularity);
if delta = 1 then delta := 3;
end else
delta := 1;
dvScrollVertical(-delta);
Result := True;
end;
end;
{$ENDIF}
procedure TVpDayView.EditSelectedEvent(IsNewEvent: Boolean = false);
begin
if ReadOnly then
Exit;
if FActiveEvent <> nil then
dvSpawnEventEditDialog(IsNewEvent);
end;
{=====}
procedure TVpDayView.dvSpawnEventEditDialog(IsNewEvent: Boolean);
var
AllowIt: Boolean;
EventDlg : TVpEventEditDialog;
begin
if (DataStore = nil) or (DataStore.Resource = nil) or ReadOnly then
Exit;
if (not IsNewEvent) and (not FActiveEvent.CanEdit) then begin
MessageDlg(RSCannotEditOverlayedEvent, mtInformation, [mbOK], 0);
exit;
end;
AllowIt := false;
if Assigned(FOwnerEditEvent) then
FOwnerEditEvent(self, FActiveEvent, IsNewEvent, DataStore.Resource, AllowIt)
else begin
EventDlg := TVpEventEditDialog.Create(nil);
try
EventDlg.DataStore := DataStore;
AllowIt := EventDlg.Execute(FActiveEvent);
finally
EventDlg.Free;
end;
end;
if AllowIt then begin
FActiveEvent.Changed := true;
DataStore.PostEvents;
if IsNewEvent and Assigned(FOnAddEvent) then
FOnAddEvent(self, FActiveEvent);
end else begin
if IsNewEvent then begin
FActiveEvent.Deleted := true;
DataStore.PostEvents;
FActiveEvent := nil;
dvActiveEventRec := Rect(0, 0, 0, 0);
dvActiveIconRec := Rect(0, 0, 0, 0);
end;
end;
Invalidate;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.WMSetFocus(var Msg: TWMSetFocus);
{$ELSE}
procedure TVpDayView.WMSetFocus(var Msg: TLMSetFocus);
{$ENDIF}
begin
Unused(Msg);
if ActiveRow = -1 then ActiveRow := TopLine;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.WMEraseBackground(var Msg: TWMERASEBKGND);
{$ELSE}
procedure TVpDayView.WMEraseBackground(var Msg: TLMERASEBKGND);
{$ENDIF}
begin
Msg.Result := 1;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
begin
inherited;
Msg.Result := 1;
end;
{$ENDIF}
{=====}
procedure TVpDayView.SetActiveEventByCoord(APoint: TPoint);
var
I : Integer;
begin
for I := 0 to pred(Length(dvEventArray)) do begin
if dvEventArray[I].Event = nil then
Exit;
if PointInRect(APoint, dvEventArray[I].Rec) then
begin
FActiveEvent := TVpEvent(dvEventArray[I].Event);
dvActiveEventRec := dvEventArray[I].Rec;
dvActiveIconRec := dvEventArray[I].IconRect;
Exit;
end;
end;
end;
function TVpDayView.EditEventAtCoord(APoint: TPoint): Boolean;
var
I: Integer;
begin
result := false;
if ReadOnly then
Exit;
for I := 0 to pred(Length(dvEventArray)) do begin
FActiveEvent := nil; // wp: shouldn't these be set also if ReadOnly is true?
dvActiveEventRec := Rect(0, 0, 0, 0);
dvActiveIconRec := Rect(0, 0, 0, 0);
if dvEventArray[I].Event = nil then
{ we've hit the end of visible events without finding a match }
Exit;
if PointInRect(APoint, dvEventArray[I].Rec) then
begin
FActiveEvent := TVpEvent(dvEventArray[I].Event);
dvActiveEventRec := dvEventArray[I].Rec;
dvActiveIconRec := dvEventArray[I].IconRect;
dvClickTimer.Enabled := true;
result := true;
Break;
end;
end;
end;
{=====}
function TVpDayView.GetEventAtCoord(APoint: TPoint): TVpEvent;
var
I: Integer;
begin
result := nil;
for I := 0 to pred(Length(dvEventArray)) do begin
if dvEventArray[I].Event = nil then
Exit;
if PointInRect(APoint, dvEventArray[I].Rec) then
begin
result := TVpEvent(dvEventArray[I].Event);
Exit;
end;
end;
end;
function TVpDayView.GetEventRect(AEvent: TVpEvent): TRect;
var
i: Integer;
begin
for i:=0 to High(dvEventArray) do
if dvEventArray[i].Event = AEvent then begin
Result := dvEventArray[i].Rec;
exit;
end;
end;
procedure TVpDayView.dvEditInPlace(Sender: TObject);
begin
{ this is the timer event which spawns an in-place editor }
{ if the event is doublecliked before this timer fires, then the }
{ event is edited in a dialog based editor. }
dvClickTimer.Enabled := false;
EditEvent;
end;
{=====}
procedure TVpDayView.EditEvent;
var
AllowIt: Boolean;
begin
if ReadOnly then
Exit;
if not FAllowInplaceEdit then
Exit;
if (FActiveEvent <> nil) and (not FActiveEvent.CanEdit) then
Exit;
{ call the user defined BeforeEdit event }
AllowIt := true;
if Assigned(FBeforeEdit) then
FBeforeEdit(Self, FActiveEvent, AllowIt);
if not AllowIt then
exit;
{ create and spawn the in-place editor }
if dvInPlaceEditor = nil then begin
dvInPlaceEditor := TVpDvInPlaceEdit.Create(Self);
dvInPlaceEditor.Parent := self;
dvInPlaceEditor.OnExit := EndEdit;
end;
if FActiveEvent.AllDayEvent then
dvInplaceEditor.SetBounds(
dvActiveEventRec.Left + 2 * (TextMargin div 2), // this way it is calculated in DrawAllDayEvents
dvActiveEventRec.Top + 2 * (TextMargin div 2),
WidthOf(dvActiveEventRec) - TextMargin div 2,
HeightOf(dvActiveEventRec)
)
else
dvInPlaceEditor.SetBounds(
dvActiveIconRec.Right + TextMargin,
dvActiveEventRec.Top + TextMargin,
dvActiveEventRec.Right - dvActiveIconRec.Right - TextMargin,
dvActiveEventRec.Bottom - dvActiveEventRec.Top - TextMargin
);
dvInPlaceEditor.Show;
dvInPlaceEditor.Text := FActiveEvent.Description;
Invalidate;
dvInPlaceEditor.SetFocus;
end;
{=====}
procedure TVpDayView.EndEdit(Sender: TObject);
begin
if dvEndingEditing then
Exit;
dvEndingEditing := True;
try
if (dvInPlaceEditor <> nil) and dvInplaceEditor.Visible then begin
if dvInPlaceEditor.Text <> FActiveEvent.Description then begin
FActiveEvent.Description := dvInPlaceEditor.Text;
FActiveEvent.Changed := true;
DataStore.PostEvents;
if Assigned(FAfterEdit) then
FAfterEdit(self, FActiveEvent);
end;
dvInplaceEditor.Hide;
Invalidate;
end;
finally
dvEndingEditing := False;
end;
end;
{=====}
procedure TVpDayView.KeyDown(var Key: Word; Shift: TShiftState);
var
PopupPoint : TPoint;
begin
case Key of
VK_UP:
ActiveRow := ActiveRow - 1;
VK_DOWN:
ActiveRow := ActiveRow + 1;
VK_NEXT:
ActiveRow := ActiveRow + FVisibleLines;
VK_PRIOR:
ActiveRow := ActiveRow - FVisibleLines;
VK_LEFT:
Date := Date - 1;
VK_RIGHT:
Date := Date + 1;
VK_HOME:
ActiveRow := 0;
VK_END:
ActiveRow := LineCount;
VK_DELETE:
if not ReadOnly then
DeleteActiveEvent(true);
{$IFNDEF LCL}
VK_TAB:
if ssShift in Shift then
Windows.SetFocus (GetNextDlgTabItem(GetParent(Handle), Handle, False))
else
Windows.SetFocus (GetNextDlgTabItem(GetParent(Handle), Handle, True));
{$ENDIF}
VK_F10:
if (ssShift in Shift) and not (Assigned (PopupMenu)) then begin
PopupPoint := GetClientOrigin;
FDefaultPopup.Popup(PopupPoint.x + 10, PopupPoint.y + 10);
end;
VK_APPS :
if not Assigned(PopupMenu) then begin
PopupPoint := GetClientOrigin;
FDefaultPopup.Popup(PopupPoint.x + 10, PopupPoint.y + 10);
end;
VK_RETURN:
PopupEditEvent(Self);
VK_INSERT:
PopupAddEvent(Self);
VK_F2:
if Assigned(FActiveEvent) then
dvEditInPlace(Self)
else
begin
PopupPoint := dvLineMatrix[ActiveCol, ActiveRow].Rec.TopLeft;
PopupPoint.x := PopupPoint.x + 1;
PopupPoint.y := PopupPoint.y + 1;
SetActiveEventByCoord (PopupPoint);
if Assigned(FActiveEvent) then
dvEditInPlace(Self);
end;
end;
end;
{=====}
{$IFNDEF LCL}
procedure TVpDayView.WMVScroll(var Msg: TWMVScroll);
{$ELSE}
procedure TVpDayView.WMVScroll(var Msg: TLMVScroll);
{$ENDIF}
begin
{ for simplicity, bail out of editing while scrolling. }
EndEdit(Self);
// wp: Next line should never happen after EndEdit...
if (dvInPlaceEditor <> nil) and dvInplaceEditor.Visible then Exit;
case Msg.ScrollCode of
SB_LINEUP : dvScrollVertical(-1);
SB_LINEDOWN : dvScrollVertical(1);
SB_PAGEUP : dvScrollVertical(-FVisibleLines);
SB_PAGEDOWN : dvScrollVertical(FVisibleLines);
SB_THUMBPOSITION, SB_THUMBTRACK : TopLine := Msg.Pos;
end;
end;
{=====}
procedure TVpDayView.dvScrollVertical(Lines: Integer);
begin
TopLine := TopLine + Lines;
end;
{=====}
procedure TVpDayView.SetVScrollPos;
var
SI : TScrollInfo;
begin
if not HandleAllocated then
Exit;
with SI do begin
cbSize := SizeOf(SI);
fMask := SIF_RANGE or SIF_PAGE or SIF_POS;
nMin := 0;
nMax := FLineCount;
if FVisibleLines >= FLineCount then
nPage := nMax
else
nPage := FVisibleLines;
if FTopLine = pred(LineCount) - VisibleLines then
nPos := LineCount
else
nPos := FTopLine;
nTrackPos := nPos;
end;
SetScrollInfo(Handle, SB_VERT, SI, True);
end;
{=====}
procedure TVpDayView.SetCustomRowHeight(Value: Integer);
begin
if Value <> FCustomRowHeight then begin
if (Value <> 0) and (Value < 1)
then FCustomRowHeight := 1
else FCustomRowHeight := Value;
Invalidate;
end;
end;
procedure TVpDayView.SetRowLinesStep(Value: Integer);
begin
if Value <> FRowLinesStep then begin
if Value < 1
then FRowLinesStep := 1
else FRowLinesStep := Value;
Invalidate;
end;
end;
procedure TVpDayView.SetShowNavButtons(Value: Boolean);
begin
if Value <> FShowNavButtons then begin
FShowNavButtons := Value;
Invalidate;
end;
end;
procedure TVpDayView.SetShowResourceName(Value: Boolean);
begin
if Value <> FShowResourceName then begin
FShowResourceName := Value;
Invalidate;
end;
end;
procedure TVpDayView.SetSimpleRowTime(Value: Boolean);
begin
if Value <> FSimpleRowTime then begin
FSimpleRowTime := Value;
Invalidate;
end;
end;
procedure TVpDayView.SetNumDays(Value: Integer);
begin
if (Value <> FNumDays) and (Value > 0) and (Value < 31) then begin
FNumDays := Value;
SetLength(dvColRectArray, FNumDays);
SetTimeIntervals(Granularity);
ActiveCol := 0;
Invalidate;
end;
end;
procedure TVpDayView.SetIncludeWeekends(Value : Boolean);
begin
if Value <> FIncludeWeekends then begin
FIncludeWeekends := Value;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetActiveRow(Value: Integer);
var
OldActiveRow: Integer;
begin
if dvClickTimer.Enabled then
dvClickTimer.Enabled := false;
if not Focused then SetFocus;
OldActiveRow := FActiveRow;
{ set active row }
if (Value < 0) then
FActiveRow := 0
else if (Value >= pred(LineCount)) then
FActiveRow := pred(LineCount)
else
FActiveRow := Value;
{ clamp in view }
if (FActiveRow < FTopLine) then
TopLine := FActiveRow
else if (FActiveRow >= FTopLine + FVisibleLines) then
TopLine := FActiveRow - FVisibleLines + 1;
if (OldActiveRow <> FActiveRow) then begin
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetActiveCol(Value: Integer);
begin
if FActiveCol <> Value then begin
if Value < 0 then
FActiveCol := 0
else if Value > pred(NumDays) then
FActiveCol := pred(NumDays)
else
FActiveCol := Value;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetDotDotDotColor(const v: TColor);
begin
if v <> FDotDotDotColor then begin
FDotDotDotColor := v;
Invalidate;
end;
end;
{=====}
procedure TVpDayView.SetShowEventTimes(Value: Boolean);
begin
if Value <> FShowEventTimes then begin
FShowEventTimes := Value;
Invalidate;
end
end;
{=====}
procedure TVpDayView.SetWrapStyle(const v: TVpDVWrapStyle);
begin
if v <> FWrapStyle then begin
FWrapStyle := v;
Invalidate;
end;
end;
procedure TVpDayView.SetHint(const AValue: TTranslateString);
begin
inherited;
if FHintMode = hmComponentHint then
FComponentHint := AValue;
end;
procedure TVpDayView.SetHintMode(const AValue: TVpHintMode);
begin
if AValue = FHintMode then
exit;
FHintMode := AValue;
if FHintMode = hmPlannerHint then
FComponentHint := Hint;
end;
{=====}
procedure TVpDayView.dvSetActiveRowByCoord(Pnt: TPoint; Sloppy: Boolean);
var
I : Integer;
begin
if dvClickTimer.Enabled then
dvClickTimer.Enabled := false;
for I := 0 to pred(LineCount) do begin
if Sloppy and
(Pnt.y <= dvLineMatrix[ActiveCol, I].Rec.Bottom) and
(Pnt.y > dvLineMatrix[ActiveCol, I].Rec.Top)
then begin
ActiveRow := I;
Exit;
end else
if PointInRect(Pnt, dvLineMatrix[ActiveCol, I].Rec) then
begin
ActiveRow := I;
Exit;
end;
end;
end;
{=====}
procedure TVpDayView.dvSetActiveColByCoord(Pnt: TPoint);
var
I : Integer;
begin
for I := 0 to pred(length(dvColRectArray)) do begin
if PointInRect(Pnt, dvColRectArray[I].Rec) then
begin
ActiveCol := I;
Exit;
end;
end;
end;
{=====}
function TVpDayView.GetControlType : TVpItemType;
begin
Result := itDayView;
end;
procedure TVpDayView.AutoScaledPaintToCanvas(PaintCanvas: TCanvas; PaintTo: TRect;
Angle: TVpRotationAngle; RenderDate: TDateTime; StartLine, StopLine: Integer;
UseGran: TVpGranularity);
var
SrcResY: Integer;
DestResY: Integer;
Scale: Extended;
begin
SrcResY := GetDeviceCaps(Canvas.Handle, LOGPIXELSY);
DestResY := GetDeviceCaps(PaintCanvas.Handle, LOGPIXELSY);
Scale := DestResY / SrcResY;
RenderToCanvas(PaintCanvas, PaintTo, Angle, Scale, RenderDate, StartLine, StopLine, UseGran, True);
end;
procedure TVpDayView.PaintToCanvas(ACanvas: TCanvas; ARect: TRect;
Angle: TVpRotationAngle; ADate: TDateTime; StartHour, EndHour: TVpHours;
UseGran: TVpGranularity);
begin
RenderToCanvas(
ACanvas,
ARect,
Angle,
1,
ADate,
HourToLine(StartHour, UseGran),
HourToLine(EndHour, UseGran),
UseGran,
True);
end;
procedure TVpDayView.RenderToCanvas(RenderCanvas: TCanvas; RenderIn: TRect;
Angle: TVpRotationAngle; Scale: Extended; RenderDate: TDateTime;
StartLine, StopLine: Integer; UseGran: TVpGranularity; DisplayOnly: Boolean);
var
painter: TVpDayViewPainter;
begin
dvPainting := true;
painter := TVpDayviewPainter.Create(Self, RenderCanvas);
try
painter.RenderToCanvas(RenderIn, Angle, Scale, RenderDate, StartLine,
StopLine, UseGran, DisplayOnly);
finally
painter.Free;
dvPainting := false;
end;
end;
procedure TVpDayView.VpDayViewInit(var Msg: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF});
begin
Unused(Msg);
if csLoading in ComponentState then begin
PostMessage(Handle, Vp_DayViewInit, 0, 0);
Exit;
end;
dvCalcColHeadHeight(1);
dvCalcRowHeight(1, FGranularity);
dvCalcVisibleLines(Height, dvColHeadHeight, dvRowHeight, 1, TopLine, -1);
SetVScrollPos;
end;
{$IF VP_LCL_SCALING = 2}
procedure TVpDayView.ScaleFontsPPI(const AToPPI: Integer;
const AProportion: Double);
begin
inherited;
DoScaleFontPPI(AllDayEventAttributes.Font, AToPPI, AProportion);
DoScaleFontPPI(HeadAttributes.Font, AToPPI, AProportion);
DoScaleFontPPI(RowHeadAttributes.HourFont, AToPPI, AProportion);
DoScaleFontPPI(RowHeadAttributes.MinuteFont, AToPPI, AProportion);
end;
{$ELSEIF VP_LCL_SCALING = 1}
procedure TVpDayView.ScaleFontsPPI(const AProportion: Double);
begin
inherited;
DoScaleFontPPI(AllDayEventAttributes.Font, AProportion);
DoScaleFontPPI(HeadAttributes.Font, AProportion);
DoScaleFontPPI(RowHeadAttributes.HourFont, AProportion);
DoScaleFontPPI(RowHeadAttributes.MinuteFont, AProportion);
end;
{$ENDIF}
(*****************************************************************************)
{ TVpCHAttributes }
constructor TVpCHAttributes.Create(AOwner: TVpDayView);
begin
inherited Create;
FOwner := AOwner;
FFont := TVpFont.Create(AOwner);
end;
{=====}
destructor TVpCHAttributes.Destroy;
begin
FFont.Free;
inherited;
end;
{=====}
procedure TVpCHAttributes.SetColor(const Value: TColor);
begin
if FColor <> Value then begin
FColor := Value;
FOwner.Invalidate;
end;
end;
{=====}
procedure TVpCHAttributes.SetFont(Value: TVpFont);
begin
FFont.Assign(Value);
end;
{=====}
(*****************************************************************************)
{ TVpRHAttributes }
constructor TVpRHAttributes.Create(AOwner: TVpDayView);
begin
inherited Create;
FOwner := AOwner;
FHourFont := TVpFont.Create(AOwner);
FMinuteFont := TVpFont.Create(AOwner);
{$IFNDEF LCL}
FHourFont.Name := 'Tahoma';
FMinuteFont.Name := 'Tahoma';
{$ENDIF}
end;
{=====}
destructor TVpRHAttributes.Destroy;
begin
FHourFont.Free;
FMinuteFont.Free;
inherited;
end;
{=====}
procedure TVpRHAttributes.SetColor(const Value: TColor);
begin
if FColor <> Value then begin
FColor := Value;
FOwner.Invalidate;
end;
end;
{=====}
procedure TVpRHAttributes.SetHourFont(Value: TVpFont);
begin
if Value <> FHourFont then begin
FHourFont.Assign(Value);
FOwner.Invalidate;
end;
end;
{=====}
procedure TVpRHAttributes.SetMinuteFont(Value: TVpFont);
begin
if Value <> FMinuteFont then begin
FMinuteFont.Assign(Value);
FOwner.Invalidate;
end;
end;
end.