{********************************************************************}
{                                                                    }
{       Developer Express Visual Component Library                   }
{                   ExpressScheduler                                 }
{                                                                    }
{       Copyright (c) 2003-2005 Developer Express Inc.               }
{       ALL RIGHTS RESERVED                                          }
{                                                                    }
{   The entire contents of this file is protected by U.S. and        }
{   International Copyright Laws. Unauthorized reproduction,         }
{   reverse-engineering, and distribution of all or any portion of   }
{   the code contained in this file is strictly prohibited and may   }
{   result in severe civil and criminal penalties and will be        }
{   prosecuted to the maximum extent possible under the law.         }
{                                                                    }
{   RESTRICTIONS                                                     }
{                                                                    }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES            }
{   (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE     }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS    }
{   LICENSED TO DISTRIBUTE THE EXPRESSSCHEDULER AND ALL ACCOMPANYING }
{   VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.              }
{                                                                    }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED       }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE         }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE        }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT   }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                       }
{                                                                    }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON        }
{   ADDITIONAL RESTRICTIONS.                                         }
{                                                                    }
{********************************************************************}

unit cxSchedulerWeekView;

{$I cxVer.inc}

interface

uses
  Windows, Forms, Classes, cxClasses, SysUtils, Graphics, cxGraphics,
  cxDateUtils, Controls, cxControls, cxSchedulerCustomControls, Math, StdCtrls,
  cxLookAndFeelPainters, cxGeometry, cxSchedulerStorage, cxSchedulerUtils,
  {$IFDEF DELPHI6} DateUtils, {$ENDIF} cxStyles, cxSchedulerCustomResourceView;

type
  TcxSchedulerCustomWeekView = class;
  TcxSchedulerWeekViewViewInfo = class;
  TcxSchedulerWeeksViewViewInfo = class;
  TcxSchedulerCustomWeekViewNavigation = class;

  { TcxSchedulerCustomWeekViewController }

  TcxSchedulerCustomWeekViewController = class(TcxSchedulerCustomResourceViewController)
  private
    function GetNavigation: TcxSchedulerCustomWeekViewNavigation;
  protected
    function CreateDragEventHelper: TcxDragEventHelper; override;
    function CreateNavigation: TcxSchedulerViewNavigation; override;
    function CreateResizeEventHelper: TcxEventSizingHelper; override;
  public
    property Navigation: TcxSchedulerCustomWeekViewNavigation read GetNavigation;
  end;

  { TcxCustomWeekViewDragEventHelper }

  TcxCustomWeekViewDragEventHelper = class(TcxDragEventHelper)
  protected
    procedure UpdateViewClonesTime; override;
  end;

  { TcxCustomWeekViewEventSizing }

  TcxCustomWeekViewEventSizing = class(TcxEventSizingHelper)
  protected
    procedure UpdateEventBounds; override;
  end;

  TcxSchedulerWeekViewDaysLayout = (wdlTwoColumns, wdlOneColumn);

  { TcxSchedulerCustomWeekView }

  TcxSchedulerCustomWeekView = class(TcxSchedulerCustomResourceView)
  private
    FCompressWeekEnd: Boolean;
    FDaysLayout: TcxSchedulerWeekViewDaysLayout;
    function GetController: TcxSchedulerCustomWeekViewController;
    function GetScrollPos(const ADatePos: TDateTime; ACheckBounds: Boolean = True): Integer;
    procedure SetCompressWeekEnd(const AValue: Boolean);
    procedure SetDaysLayout(Value: TcxSchedulerWeekViewDaysLayout);
  protected
    FWeeks: TcxSchedulerDateList;
    function CheckDate(const ADate: TDateTime): Integer;
    function CreateController: TcxSchedulerSubControlController; override;
    function CreateNavigation: TcxSchedulerViewNavigation; virtual;
    function CreatePainter: TcxSchedulerSubControlPainter; override;
    function GetCompressWeekEnd: Boolean; override;
    function GetDateScrollBarKind: TScrollBarKind;
    function GetFirstVisibleDate: TDateTime; override;
    function GetLastVisibleDate: TDateTime; override;
    function GetMaxScrollPos: Integer; virtual;
    function GetMinScrollPos: Integer; virtual;
    function GetWeekCount: Integer;
    function GetStartOfWeek: TDay; override;
    function GetViewContentRect: TRect; override;
    procedure InitEventBySelectedTime(AEvent: TcxSchedulerEvent;
      AllDay: Boolean; ARecurrence: Boolean; AInplaceEditing: Boolean); override;
    procedure InitScrollBarsParameters; override;
    procedure Scroll(AScrollBarKind: TScrollBarKind;
      AScrollCode: TScrollCode; var AScrollPos: Integer); override;

    property Controller: TcxSchedulerCustomWeekViewController read GetController;
    property CompressWeekEnd: Boolean read FCompressWeekEnd write SetCompressWeekEnd default True;
    property DaysLayout: TcxSchedulerWeekViewDaysLayout read FDaysLayout write SetDaysLayout default wdlTwoColumns;
    property WeekCount: Integer read GetWeekCount;
  public
    constructor Create(AOwner: TcxCustomScheduler); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property FirstVisibleDate;
    property LastVisibleDate;
    property StartOfWeek;
  end;

  { TcxSchedulerCustomWeekViewNavigation }

  TcxSchedulerCustomWeekViewNavigation = class(TcxSchedulerCustomResourceViewNavigation)
  private
    function GetCompress: Boolean;
    function GetFirstVisibleDate: TDateTime;
    function GetLastVisibleDate: TDateTime;
    function GetView: TcxSchedulerCustomWeekView;
    function GetWeeks: TcxSchedulerDateList;
  protected
    FYear: Word;
    FWeekOfYear: Word;
    FWeekIndex: Integer;
    FDayOfWeek: Word;
    IsFirstWeek, IsLastWeek: Boolean;
    function DateScrollBarKind: TScrollBarKind;
    function GetWeekStart(AIndex: Integer): TDateTime;
    procedure GotoCornerCell(AGotoEnd: Boolean); virtual;
    procedure GotoNextCellHorz(AGotoNext: Boolean); virtual;
    procedure GotoNextCellVert(AGotoDown: Boolean); virtual;
    procedure GotoNextPage(AGotoForward: Boolean); virtual;
    function IsResourceNavigation(AGoToDown: Boolean): Boolean;
  public
    procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime;
      var AResource: TcxSchedulerStorageResourceItem); override;
    procedure KeyDown(var AKey: Word; AShift: TShiftState); override;
    property Compress: Boolean read GetCompress;
    property FirstVisibleDate: TDateTime read GetFirstVisibleDate;
    property LastVisibleDate: TDateTime read GetLastVisibleDate;
    property View: TcxSchedulerCustomWeekView read GetView;
    property Weeks: TcxSchedulerDateList read GetWeeks;
  end;

  { TcxSchedulerWeekView }

  TcxSchedulerWeekView = class(TcxSchedulerCustomWeekView)
  private
    function GetViewInfo: TcxSchedulerWeekViewViewInfo;
  protected
    function CreateNavigation: TcxSchedulerViewNavigation; override;
    function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
    function GetCompressWeekEnd: Boolean; override;
    property ViewInfo: TcxSchedulerWeekViewViewInfo read GetViewInfo;
  public
    property SelectedDays;
    property WorkDays;
    property WorkFinish;
    property WorkStart;
  published
    property CanShow;
    property Active;
    property CompressWeekEnd;
    property DaysLayout;
    property GroupingKind;
    property ShowEndTime;
    property ShowTimeAsClock;
  end;

  { TcxSchedulerWeekViewNavigation }

  TcxSchedulerWeekViewNavigation = class(TcxSchedulerCustomWeekViewNavigation)
  private
    function GetViewInfo: TcxSchedulerWeekViewViewInfo;
  protected
    procedure GotoNextCellHorz(AGotoNext: Boolean); override;
    procedure GotoNextCellVert(AGotoDown: Boolean); override;
  public
    property ViewInfo: TcxSchedulerWeekViewViewInfo read GetViewInfo;
  end;

  { TcxSchedulerWeeksView }

  TcxSchedulerWeeksView = class(TcxSchedulerCustomWeekView)
  private
    function GetViewInfo: TcxSchedulerWeeksViewViewInfo;
  protected
    function CreateNavigation: TcxSchedulerViewNavigation; override;
    function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
    function GetMaxScrollPos: Integer; override;
    function GetMinScrollPos: Integer; override;

    property ViewInfo: TcxSchedulerWeeksViewViewInfo read GetViewInfo;
  public
    property SelectedDays;
    property WeekCount;
    property WorkDays;
    property WorkFinish;
    property WorkStart;
  published
    property CanShow;
    property Active;
    property CompressWeekEnd;
    property GroupingKind;
    property ShowEndTime;
    property ShowTimeAsClock;
  end;

  { TcxSchedulerWeeksViewNavigation }

  TcxSchedulerWeeksViewNavigation = class(TcxSchedulerCustomWeekViewNavigation)
  private
    function GetViewInfo: TcxSchedulerWeeksViewViewInfo;
  protected
    procedure GotoNextCellHorz(AGotoNext: Boolean); override;
    procedure GotoNextCellVert(AGotoDown: Boolean); override;
    function IsScrollResource(AGotoNext: Boolean): Boolean;
  public
    property ViewInfo: TcxSchedulerWeeksViewViewInfo read GetViewInfo;
  end;

  { TcxSchedulerWeekViewEventCellViewInfo }

  TcxSchedulerWeekViewEventCellViewInfo = class(TcxSchedulerEventCellViewInfo)
  protected
    procedure CalculateBorders; override;
    procedure CalculateCaptions; override;
    procedure CalculateEventTimeVisibility; override;
    procedure CalculateItemsLayout; override;
    function GetEditingRect: TRect; override;
    procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
  end;

  { TcxSchedulerWeekViewViewInfo }

  TcxSchedulerWeekViewViewInfo = class(TcxSchedulerCustomResourceViewViewInfo)
  private
    function GetDayCell(ADay: Integer): TcxSchedulerContentCellViewInfo;
    function GetDayCellCount: Integer;
    function GetRotateCaptions: Boolean;
    function GetStartDate(AWeek: Integer): TDateTime;
    function GetView: TcxSchedulerWeekView;
    function GetWeeks: TcxSchedulerDateList;
  protected
    Builder: TcxSchedulerEventLayoutBuilder;
    FDayHeaderOffsetTop: Integer;
    FHeaderOffsetLeft: Integer;
    FPrintedMonth: Word;
    FPrintExactlyOneMonth: Boolean;
    FResourceHeaderWidth: Integer;
    FRowCols: Integer;
    FRowColsStart: Integer;
    FWeekEndCells: Integer;
    function AddContentCell(const ARect: TRect; const AStart, AFinish: TDateTime;
      AResourceIndex: Integer): TcxSchedulerContentCellViewInfo; override;
    procedure AddDayCellEvent(APlace: TcxSchedulerEventPlace);
    procedure AddDayCellEventPlace(AEvent: TcxSchedulerControlEvent; var AIndex: Integer);
    function AddWeekDayHeader(AWeekDay: Integer; ALeft, ARight: Integer): TcxSchedulerWeekDayHeaderCellViewInfo;
    procedure CalculateDaysLayout; virtual;
    procedure CalculateDaysLayoutForResource(const ABounds: TRect; AResourceIndex: Integer); virtual;
    procedure CalculateDaysLayoutForDates(const ABounds: TRect; AResourceIndex: Integer); virtual;
    procedure CalculateEventsViewInfo; virtual;
    procedure CalculateGroupByDateForResource(const ABounds: TRect; AResourceIndex: Integer); virtual;
    procedure CalculateHeaderViewInfo; virtual;
    procedure CalculateMetrics; override;
    procedure CalculatePrintRowCols; virtual;
    procedure CalculateResourceHeadersAutoHeight(AWidth: Integer); override;
    procedure CalculateStartFinishCellIndexes; virtual;
    procedure CalculateWeekDates;
    procedure CalculateWeekDisplayRectsHorz(const AStartDate: TDateTime; AResourceID: Integer;
      {const }ABounds: TRect; AIsTopWeek, AIsLastWeek: Boolean); virtual;
    procedure CalculateWeekDisplayRectsVert(const AStartDate: TDateTime; AResourceID: Integer;
      const ABounds: TRect; AddBorders: TcxBorders = []); virtual;
    procedure CalculateWeekDisplayRectsVertEx(const AStartDate: TDateTime; AResourceID: Integer;
      const ABounds: TRect; AddBorders: TcxBorders = []);
    function CanEventVisible(AEvent: TcxSchedulerControlEvent): Boolean;
    function CanVisibleNextLine(ADay: TcxSchedulerContentCellViewInfo; ALine: Integer = -1): Boolean;
    procedure CheckHeaderBorders; virtual;
    function CompressWeekEnd: Boolean; virtual;
    function ContentCellClass: TcxSchedulerContentCellViewInfoClass; override;
    function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; override;
    procedure DoCalculate; override;
    procedure DoMoreEventsButtonClick(Sender: TcxSchedulerMoreEventsButtonViewInfo); override;
    procedure GetEventInfo(AColStart, AColFinish: Integer; var ALeft, ARight: Integer; var AStart, AFinish: TDateTime;
      var AVisibleRect: TRect; var AResource: TcxSchedulerResourceViewInfo);
    function GetResourcesContentWidth: Integer; override;
    function GetResourceImagesSize: TSize; override;
    function GetResourceScrollBarKind: TScrollBarKind; override;
    function GetContentParams(const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
    function GetDayCellContentHeight(ADay: TcxSchedulerContentCellViewInfo): Integer; virtual;
    function GetDayCellHeaderHeight: Integer; virtual;
    function IsCalculateHeaderFirst: Boolean; virtual;
    function IsCellEvent(AEvent: TcxSchedulerControlEvent;
      ACell: TcxSchedulerContentCellViewInfo): Boolean;
    function IsSingleLine(ADay1, ADay2: TcxSchedulerContentCellViewInfo): Boolean;
    function IsTimeSelected(ATime: TDateTime; AResource: TObject): Boolean; override;
    procedure ProcessGroupByDate; virtual;
    procedure ProcessGroupByNone; virtual;
    procedure ProcessGroupByResource; virtual;

    property DayCellCount: Integer read GetDayCellCount;
    property DayCells[ADay: Integer]: TcxSchedulerContentCellViewInfo read GetDayCell;
    property RowCols: Integer read FRowCols;
    property RowColsStart: Integer read FRowColsStart;
    property Weeks: TcxSchedulerDateList read GetWeeks;
    property WeekEndCells: Integer read FWeekEndCells;
  public
    constructor Create(AOwner: TcxSchedulerSubControl); override;
    destructor Destroy; override;
    procedure ScrollVertical(AScrollCode: TScrollCode; var AScrollPos: Integer); override;
    property PrintExactlyOneMonth: Boolean read FPrintExactlyOneMonth;
    property PrintedMonth: Word read FPrintedMonth;
    property StartDates[AWeek: Integer]: TDateTime read GetStartDate;
    property ResourceHeaderWidth: Integer read FResourceHeaderWidth;
    property RotateCaptions: Boolean read GetRotateCaptions;
    property View: TcxSchedulerWeekView read GetView;
  end;

  { TcxSchedulerWeeksViewEventCellViewInfo }

  TcxSchedulerWeeksViewEventCellViewInfo = class(TcxSchedulerWeekViewEventCellViewInfo)
  protected
    function CanAutoHideStandardImages: Boolean; override;
  end;

  { TcxSchedulerWeeksViewViewInfo }

  TcxSchedulerWeeksViewViewInfo = class(TcxSchedulerWeekViewViewInfo)
  protected
    FContentOffset: Integer;
    procedure CalculateDaysLayoutForResource(const ABounds: TRect; AResourceIndex: Integer); override;
    procedure CalculateGroupByDateForResource(const ABounds: TRect; AResourceIndex: Integer); override;
    procedure CalculateHeaderViewInfo; override;
    procedure CheckHeaderBorders; override;
    function CompressWeekEnd: Boolean; override;
    function ContentCellClass: TcxSchedulerContentCellViewInfoClass; override;
    function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; override;
    function GetContentParams(const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
    function GetDayCellHeaderHeight: Integer; override;
    function IsCalculateHeaderFirst: Boolean; override;
    procedure ProcessGroupByNone; override;
    procedure ProcessGroupByResource; override;
  end;

  { TcxSchedulerWeekViewPainter }

  TcxSchedulerWeekViewPainter = class(TcxSchedulerCustomViewPainter)
  private
    function GetViewInfo: TcxSchedulerWeekViewViewInfo;
  public
    procedure Paint; override;

    property ViewInfo: TcxSchedulerWeekViewViewInfo read GetViewInfo;
  end;

implementation

uses
  cxSchedulerDateNavigator;

type
  TcxSchedulerDaysRect = array[0..6] of TRect;
  TcxSchedulerDaysBorders = array[0..6] of TcxBorders;

const
  WeekViewDayBorders: TcxSchedulerDaysBorders =(
    [bTop, bRight], [bTop, bRight], [bTop, bRight],
    [bTop], [bTop], [bTop], [bTop]);
  DayInc: array[Boolean] of Integer = (-1, 1);

{ TcxSchedulerCustomWeekViewController }

function TcxSchedulerCustomWeekViewController.CreateDragEventHelper: TcxDragEventHelper;
begin
  Result := TcxCustomWeekViewDragEventHelper.Create(Scheduler);
end;

function TcxSchedulerCustomWeekViewController.CreateNavigation: TcxSchedulerViewNavigation;
begin
  Result := TcxSchedulerCustomWeekView(View).CreateNavigation;
end;

function TcxSchedulerCustomWeekViewController.CreateResizeEventHelper: TcxEventSizingHelper;
begin
  Result := TcxCustomWeekViewEventSizing.Create(Scheduler);
end;

function TcxSchedulerCustomWeekViewController.GetNavigation: TcxSchedulerCustomWeekViewNavigation;
begin
  Result := TcxSchedulerCustomWeekViewNavigation(inherited Navigation);
end;

{cxCustomWeekViewDragEventHelper }

procedure TcxCustomWeekViewDragEventHelper.UpdateViewClonesTime;
var
  I: Integer;
  ADelta: TDateTime;
begin
  ADelta := Controller.StartDragHitTime - HitTest.Time;
  for I := 0 to Clones.Count - 1 do
    with Clones[I] do
      MoveTo(Source.Start - ADelta);
end;

{ TcxCustomWeekViewEventSizing }

procedure TcxCustomWeekViewEventSizing.UpdateEventBounds;
begin
  if Event.AllDayEvent then
    inherited UpdateEventBounds
  else
  begin
    if Controller.DragKind = edkResizeStart then
    begin
      Event.AllDayEvent := TimeOf(Event.Finish) = 0;
      Event.Start := HitTest.Time;
    end
    else
    begin
      Event.AllDayEvent := TimeOf(Event.Start) = 0;
      if Event.AllDayEvent then
        Event.Finish := HitTest.Time
      else
        Event.Finish := HitTest.Time + 1;
    end;
    CheckEventState(Event);
    RefreshCurrentView;
  end;
end;

{ TcxSchedulerCustomWeekView }

constructor TcxSchedulerCustomWeekView.Create(AOwner: TcxCustomScheduler);
begin
  inherited Create(AOwner);
  FCompressWeekEnd := True;
  EventImagesLayout := eilHorizontal;
  FWeeks := TcxSchedulerDateList.Create;
end;

destructor TcxSchedulerCustomWeekView.Destroy;
begin
  FWeeks.Free;
  inherited Destroy;
end;


procedure TcxSchedulerCustomWeekView.Assign(Source: TPersistent);
begin
  if Source is TcxSchedulerCustomWeekView then
  begin
    CompressWeekEnd := TcxSchedulerCustomWeekView(Source).FCompressWeekEnd;
    FDaysLayout := TcxSchedulerCustomWeekView(Source).DaysLayout;
  end;
  inherited Assign(Source);
end;

function TcxSchedulerCustomWeekView.CheckDate(
  const ADate: TDateTime): Integer;
begin
  //DELPHI8! check Trunc(ADate)
  Result := Trunc(ADate);
  if DayOfWeek(ADate) <> (1 + Byte(CompressWeekEnd)) then
    Result := Result - DayOfWeek(ADate) + 1 + Byte(CompressWeekEnd);
end;

function TcxSchedulerCustomWeekView.CreateController: TcxSchedulerSubControlController;
begin
  Result := TcxSchedulerCustomWeekViewController.Create(Self);
end;

function TcxSchedulerCustomWeekView.CreateNavigation: TcxSchedulerViewNavigation;
begin
  Result := TcxSchedulerCustomWeekViewNavigation.Create(Self);
end;

function TcxSchedulerCustomWeekView.CreatePainter: TcxSchedulerSubControlPainter;
begin
  Result := TcxSchedulerWeekViewPainter.Create(Self);
end;

function TcxSchedulerCustomWeekView.GetCompressWeekEnd: Boolean;
begin
  Result := CompressWeekEnd;
end;

function TcxSchedulerCustomWeekView.GetDateScrollBarKind: TScrollBarKind;
const
  ScrollKind: array[TScrollBarKind] of TScrollBarKind =
    (sbVertical, sbHorizontal);
begin
  Result := ScrollKind[TcxSchedulerWeekViewViewInfo(ViewInfo).GetResourceScrollBarKind];
end;

function TcxSchedulerCustomWeekView.GetFirstVisibleDate: TDateTime;
begin
  Result := inherited GetFirstVisibleDate;
  if GetCompressWeekEnd then
    Result := Result + GetDateOffset;
end;

function TcxSchedulerCustomWeekView.GetLastVisibleDate: TDateTime;
begin
  Result := inherited GetLastVisibleDate;
  if GetCompressWeekEnd then
    Result := Result + GetDateOffset;
end;

function TcxSchedulerCustomWeekView.GetMaxScrollPos: Integer;
begin
  Result := 25;
end;

function TcxSchedulerCustomWeekView.GetMinScrollPos: Integer;
begin
  Result := -25;
end;

function TcxSchedulerCustomWeekView.GetWeekCount: Integer;
begin
  Result := Max(1, SelectedDays.Count div 7);
end;

function TcxSchedulerCustomWeekView.GetStartOfWeek: TDay;
begin
  if GetCompressWeekEnd then
    Result := dMonday
  else
    Result := inherited GetStartOfWeek;
end;

function TcxSchedulerCustomWeekView.GetViewContentRect: TRect;
begin
  Result := inherited GetViewContentRect;
  if ViewInfo.GroupingKind = gkByDate then
  begin
    with TcxSchedulerWeekViewViewInfo(ViewInfo) do
      Result.TopLeft := Point(FResourceHeaderHeight, FDayHeaderHeight);
  end;
end;

procedure TcxSchedulerCustomWeekView.InitEventBySelectedTime(
  AEvent: TcxSchedulerEvent; AllDay: Boolean; ARecurrence: Boolean;
  AInplaceEditing: Boolean);
var
  AStart, AFinish: TDateTime;
begin
  AStart := Scheduler.SelStart;
  AFinish := Scheduler.SelFinish;
  AEvent.AllDayEvent := AllDay or (AFinish - AStart > 1) or (AInplaceEditing and not ARecurrence);
  if not AEvent.AllDayEvent then
  begin
    AStart := AStart + cxTime8AM;
    AFinish := (AFinish - 1) + cxTime8AM + cxHalfHour;
  end;
  AEvent.Start := AStart;
  AEvent.Finish := AFinish;
end;

procedure TcxSchedulerCustomWeekView.InitScrollBarsParameters;
begin
  SetScrollBarInfo(GetDateScrollBarKind,  GetMinScrollPos, GetMaxScrollPos, 1,
    WeekCount, GetScrollPos(FirstVisibleDate), True, True);
  inherited InitScrollBarsParameters;
end;

procedure TcxSchedulerCustomWeekView.Scroll(AScrollBarKind: TScrollBarKind;
  AScrollCode: TScrollCode; var AScrollPos: Integer);
var
  ANewSelDate: TDateTime;
  ADelta: Integer;
begin
  HideHintOnScroll(AScrollCode);
  if (AScrollBarKind <> GetDateScrollBarKind) or (AScrollCode = scEndScroll) then Exit;
  ADelta := GetScrollPos(FirstVisibleDate, False);
  if not (AScrollCode in [scPosition, scTrack]) then
    AScrollPos := ADelta;
  ANewSelDate := Controller.Navigation.SelStart;
  case AScrollCode of
    scLineUp, scLineDown:
    begin
      Inc(AScrollPos, DayInc[AScrollCode <> scLineUp]);
      ANewSelDate := ANewSelDate + DayInc[AScrollCode <> scLineUp] * 7;
    end;
    scPageUp, scPageDown:
    begin
      Inc(AScrollPos, DayInc[AScrollCode <> scPageUp] * WeekCount);
      with Controller.Navigation do
        ANewSelDate := ANewSelDate + DayInc[AScrollCode <> scPageUp] * Weeks.Count * 7;
    end;
    scTop:
      AScrollPos := -GetMinScrollPos;
    scBottom:
      AScrollPos := GetMaxScrollPos;
  end;
  ADelta := ADelta - AScrollPos;
  if ADelta <> 0 then
  begin
    ScrollSelectedDays(ADelta);
    AScrollPos := GetScrollPos(FirstVisibleDate);
  end;
  if AScrollCode = scTrack then
    ShowHintOnScroll(FirstVisibleDate);
  with Scheduler do
    SelectTime(ANewSelDate, ANewSelDate, SelResource);
end;

function TcxSchedulerCustomWeekView.GetController: TcxSchedulerCustomWeekViewController;
begin
  Result := TcxSchedulerCustomWeekViewController(inherited Controller);
end;

function TcxSchedulerCustomWeekView.GetScrollPos(
  const ADatePos: TDateTime; ACheckBounds: Boolean = True): Integer;
begin
  Result := Round(ADatePos - CheckDate(Date)) div 7;
  if ACheckBounds then
  begin
    if Result < GetMinScrollPos then
      Result := GetMinScrollPos;
    if Result > GetMaxScrollPos then
      Result := GetMaxScrollPos;
  end;
end;

procedure TcxSchedulerCustomWeekView.SetCompressWeekEnd(
  const AValue: Boolean);
begin
  if FCompressWeekEnd <> AValue then
  begin
    FCompressWeekEnd := AValue;
    LayoutChanged;
  end;
end;

procedure TcxSchedulerCustomWeekView.SetDaysLayout(
  Value: TcxSchedulerWeekViewDaysLayout);
begin
  if Value <> FDaysLayout then
  begin
    FDaysLayout := Value;
    LayoutChanged;
  end;
end;

{ TcxSchedulerCustomWeekViewNavigation }

procedure TcxSchedulerCustomWeekViewNavigation.KeyDown(
  var AKey: Word; AShift: TShiftState);
var
  APos: Integer;
begin
  DecodeDateWeek(FCurrentAnchor + 1 - Byte(View.StartOfWeek),
    FYear, FWeekOfYear, FDayOfWeek);
  Dec(FDayOfWeek);
  FWeekIndex := Max(0, Weeks.IndexOf(Trunc(EncodeDateWeek(FYear, FWeekOfYear, 1))));
  IsFirstWeek := (FWeekIndex = 0) and IsFirstResource;
  IsLastWeek := (FWeekIndex = Weeks.Count - 1) and IsLastResource;
  case AKey of
    VK_Left, VK_Right:
      GotoNextCellHorz(AKey = VK_RIGHT);
    VK_UP, VK_DOWN:
      GotoNextCellVert(AKey = VK_DOWN);
    VK_HOME, VK_END:
      GotoCornerCell(AKey = VK_END);
    VK_NEXT, VK_PRIOR:
      GotoNextPage(AKey = VK_NEXT);
  end;
  APos := View.GetScrollPos(View.FirstVisibleDate, False);
  if (ssShift in FShift) and ((FCurrentResource <> SelResource) or
    (DateOf(FCurrentAnchor) < FirstVisibleDate) or (DateOf(FCurrentAnchor) > LastVisibleDate)) then
    Exit
  else
    if DateOf(FCurrentAnchor) < FirstVisibleDate then
    begin
      View.Scroll(DateScrollBarKind, scLineUp, APos);
      SetSelAnchor(FCurrentAnchor, [], FCurrentResource);
    end
    else
      if DateOf(FCurrentAnchor) > LastVisibleDate then
      begin
        View.Scroll(DateScrollBarKind, scLineDown, APos);
        SetSelAnchor(FCurrentAnchor, [], FCurrentResource);
      end
      else
        SetSelAnchor(FCurrentAnchor, FShift, FCurrentResource);
end;

procedure TcxSchedulerCustomWeekViewNavigation.ValidateSelection(
  var ASelStart, ASelFinish: TDateTime;
  var AResource: TcxSchedulerStorageResourceItem);
begin
  inherited ValidateSelection(ASelStart, ASelFinish, AResource);
  if (DateOf(ASelFinish) < FirstVisibleDate) or (DateOf(ASelFinish) > LastVisibleDate) then
  begin
    ASelFinish := FirstVisibleDate;
    ASelStart := ASelFinish;
  end
end;

function TcxSchedulerCustomWeekViewNavigation.DateScrollBarKind: TScrollBarKind;
begin
  Result := View.GetDateScrollBarKind;
end;

function TcxSchedulerCustomWeekViewNavigation.GetWeekStart(AIndex: Integer): TDateTime;
begin
  Result := Weeks[FWeekIndex];
  if not View.GetCompressWeekEnd then
    Result := Result - View.GetDateOffset;
end;

procedure TcxSchedulerCustomWeekViewNavigation.GotoCornerCell(
  AGotoEnd: Boolean);
begin
  if ssCtrl in FShift then
  begin
    if AGotoEnd then
      FCurrentAnchor := LastVisibleDate
    else
      FCurrentAnchor := FirstVisibleDate;
  end
  else
  begin
    FCurrentAnchor := GetWeekStart(FWeekIndex);
    if AGotoEnd then
      FCurrentAnchor := FCurrentAnchor + 6;
  end;
end;

procedure TcxSchedulerCustomWeekViewNavigation.GotoNextCellHorz(
  AGotoNext: Boolean);
begin
  FCurrentAnchor := FCurrentAnchor + DayInc[AGoToNext];
end;

procedure TcxSchedulerCustomWeekViewNavigation.GotoNextCellVert(
  AGotoDown: Boolean);
begin
  Inc(FWeekIndex, DayInc[AGotoDown]);
  if (FWeekIndex >= 0) and (FWeekIndex < Weeks.Count) then
    FCurrentAnchor := GetWeekStart(FWeekIndex)
  else
    if AGotoDown then
    begin
      if IsLastWeek then
      begin
        if not IsResourceNavigation(AGoToDown) then
          FCurrentAnchor := LastVisibleDate + 1
        else
          Exit;
      end
      else
        if FWeekIndex = Weeks.Count then
        begin
          FCurrentAnchor := FirstVisibleDate;
          FCurrentResource := GetNextResource(True)
        end
    end
    else
    begin
      if IsFirstWeek then
      begin
        if not IsResourceNavigation(AGoToDown) then
          FCurrentAnchor := FirstVisibleDate - 7
        else
          Exit;
      end
      else
        if FWeekIndex <= 0 then
        begin
          FCurrentAnchor := LastVisibleDate - 7 + 1;
          FCurrentResource := GetNextResource(False);
        end
    end;
  FCurrentAnchor := FCurrentAnchor + FDayOfWeek;
end;

procedure TcxSchedulerCustomWeekViewNavigation.GotoNextPage(
  AGotoForward: Boolean);
begin
  if not (ssShift in FShift) then
  begin
    FCurrentAnchor := FCurrentAnchor + DayInc[AGotoForward] * Weeks.Count * 7;
    View.ScrollSelectedDays(DayInc[not AGotoForward] * Weeks.Count);
  end
  else
  begin
    if AGotoForward then
      FCurrentAnchor := LastVisibleDate
    else
      FCurrentAnchor := FirstVisibleDate;
  end;
end;

function TcxSchedulerCustomWeekViewNavigation.IsResourceNavigation(AGoToDown: Boolean): Boolean;
begin
  Result := (ViewInfo.GroupingKind <> gkNone);
  if Result then
    Result := ScrollResourcesEx(AGoToDown, FCurrentResource);
  if Result then
    FCurrentAnchor := FCurrentAnchor - DayInc[AGoToDown] * (View.WeekCount - 1) * 7;
end;

function TcxSchedulerCustomWeekViewNavigation.GetCompress: Boolean;
begin
  Result := View.GetCompressWeekEnd;
end;

function TcxSchedulerCustomWeekViewNavigation.GetFirstVisibleDate: TDateTime;
begin
  Result := View.FirstVisibleDate;
end;

function TcxSchedulerCustomWeekViewNavigation.GetLastVisibleDate: TDateTime;
begin
  Result := View.LastVisibleDate;
end;

function TcxSchedulerCustomWeekViewNavigation.GetView: TcxSchedulerCustomWeekView;
begin
  Result := TcxSchedulerCustomWeekView(inherited View);
end;

function TcxSchedulerCustomWeekViewNavigation.GetWeeks: TcxSchedulerDateList;
begin
  Result := View.FWeeks;
end;

{ TcxSchedulerWeekView }

function TcxSchedulerWeekView.CreateNavigation: TcxSchedulerViewNavigation;
begin
  Result := TcxSchedulerWeekViewNavigation.Create(Self);
end;

function TcxSchedulerWeekView.CreateViewInfo: TcxSchedulerSubControlViewInfo;
begin
  Result := TcxSchedulerWeekViewViewInfo.Create(Self);
end;

function TcxSchedulerWeekView.GetCompressWeekEnd: Boolean;
begin
  Result := ViewInfo.CompressWeekEnd;
end;

function TcxSchedulerWeekView.GetViewInfo: TcxSchedulerWeekViewViewInfo;
begin
  Result := TcxSchedulerWeekViewViewInfo(inherited ViewInfo);
end;

{ TcxSchedulerWeekViewNavigation }

procedure TcxSchedulerWeekViewNavigation.GotoNextCellHorz(AGotoNext: Boolean);
const
  DateInc: array[Boolean, 0..6] of Integer =
    ((-4, -4, -4, -3, -3, -3, -4), (3, 3, 3, 4, 4, 4, 3));
begin
  if (View.DaysLayout = wdlOneColumn) and (GroupingKind <> gkByDate) then
  begin
    if IsFirstWeek and not AGotoNext then
    begin
      if not ScrollResourcesEx(AGotoNext, FCurrentResource) then
        FCurrentAnchor := FCurrentAnchor - 7
    end
    else
      if IsLastWeek and AGotoNext then
      begin
        if not ScrollResourcesEx(AGotoNext, FCurrentResource) then
          FCurrentAnchor := FCurrentAnchor + 7;
      end
      else
        FCurrentResource := GetNextResource(AGotoNext);
  end
  else
    if GroupingKind <> gkByDate then
    begin
      FCurrentAnchor := FCurrentAnchor + DateInc[AGotoNext, FDayOfWeek];
      if (AGotoNext and not IsLastWeek and (FDayOfWeek in [3..6])) or
        (not AGotoNext and not IsFirstWeek and (FDayOfWeek in [0..2])) then
      begin
        FCurrentAnchor := FCurrentAnchor - DayInc[AGotoNext] * 7;
        FCurrentResource := GetNextResource(AGotoNext);
      end
      else
      begin
        if (IsLastWeek and AGotoNext and (FDayOfWeek in [3..6]))
          or (IsFirstWeek and not AGotoNext and (FDayOfWeek in [0..2])) then
        begin
          if IsResourceNavigation(AGotoNext) then
            FCurrentAnchor := FCurrentAnchor - DayInc[AGoToNext] * 7;
        end;
      end;
    end
    else
      inherited GoToNextCellHorz(AGotoNext);
end;

procedure TcxSchedulerWeekViewNavigation.GotoNextCellVert(AGotoDown: Boolean);
begin
  if GroupingKind <> gkByDate then
    inherited GotoNextCellHorz(AGotoDown)
  else
    inherited GotoNextCellVert(AGotoDown)
end;

function TcxSchedulerWeekViewNavigation.GetViewInfo: TcxSchedulerWeekViewViewInfo;
begin
  Result := TcxSchedulerWeekViewViewInfo(inherited ViewInfo);
end;

{ TcxSchedulerWeeksView }

function TcxSchedulerWeeksView.CreateNavigation: TcxSchedulerViewNavigation;
begin
  Result := TcxSchedulerWeeksViewNavigation.Create(Self);
end;

function TcxSchedulerWeeksView.CreateViewInfo: TcxSchedulerSubControlViewInfo;
begin
  Result := TcxSchedulerWeeksViewViewInfo.Create(Self);
end;

function TcxSchedulerWeeksView.GetMaxScrollPos: Integer;
begin
  Result := 51;
end;

function TcxSchedulerWeeksView.GetMinScrollPos: Integer;
begin
  Result := -51;
end;

function TcxSchedulerWeeksView.GetViewInfo: TcxSchedulerWeeksViewViewInfo;
begin
  Result := TcxSchedulerWeeksViewViewInfo(inherited ViewInfo);
end;

{ TcxSchedulerWeeksViewNavigation }

procedure TcxSchedulerWeeksViewNavigation.GotoNextCellHorz(AGotoNext: Boolean);
begin
  if ViewInfo.GroupByResource then
  begin
    if IsScrollResource(AGoToNext) then Exit;
    if (AGoToNext and (FDayOfWeek = 6) and not IsLastResource) or
       (not AGoToNext and (FDayOfWeek = 0) and not IsFirstResource) then
    begin
      if not AGoToNext then
        FCurrentAnchor := FCurrentAnchor + 6
      else
        FCurrentAnchor := GetWeekStart(FWeekIndex);
      FCurrentResource := GetNextResource(AGoToNext);
      Exit;
   end
   else
     inherited GotoNextCellHorz(AGotoNext);
  end
  else
    inherited GotoNextCellHorz(AGotoNext);
end;

procedure TcxSchedulerWeeksViewNavigation.GotoNextCellVert(AGotoDown: Boolean);
begin
  if not AGotoDown and (FWeekIndex <= 0) then
    FCurrentAnchor :=  FCurrentAnchor - 7
  else
    if AGotoDown and (FWeekIndex >= Weeks.Count - 1) then
      FCurrentAnchor :=  FCurrentAnchor + 7
    else
      inherited GotoNextCellVert(AGoToDown);
end;

function TcxSchedulerWeeksViewNavigation.IsScrollResource(AGotoNext: Boolean): Boolean;
begin
  Result := (AGoToNext and (FDayOfWeek = 6) and IsLastResource) or
    (not AGoToNext and (FDayOfWeek = 0) and IsFirstResource);
  if Result then
    Result := ScrollResourcesEx(AGotoNext, FCurrentResource);
  if Result then
  begin
    if not AGoToNext then
      FCurrentAnchor := FCurrentAnchor + 6
    else
      FCurrentAnchor := GetWeekStart(FWeekIndex);
  end;
end;

function TcxSchedulerWeeksViewNavigation.GetViewInfo: TcxSchedulerWeeksViewViewInfo;
begin
  Result := TcxSchedulerWeeksViewViewInfo(inherited ViewInfo);
end;

{ TcxSchedulerWeekViewEventCellViewInfo }

procedure TcxSchedulerWeekViewEventCellViewInfo.CalculateBorders;
begin
  if ViewData.ContentFinish < EventFinish then
    Exclude(FBorders, bRight);
  if ViewData.ContentStart > EventStart then
    Exclude(FBorders, bLeft);
end;

procedure TcxSchedulerWeekViewEventCellViewInfo.CalculateCaptions;
begin
  if (DateOf(EventStart) <> DateOf(EventFinish)) and (Event.Duration < 1) then
  begin
    FStartText := DateTimeHelper.TimeToStrEx(Max(EventStart, ContentStart));
    FFinishText := DateTimeHelper.TimeToStrEx(Min(EventFinish, ContentFinish));
  end
  else
    inherited CalculateCaptions;
end;

procedure TcxSchedulerWeekViewEventCellViewInfo.CalculateEventTimeVisibility;
begin
  CalculateNonDetailEventTimeVisibility;
  if not IsHeaderEvent then
    ViewData.ShowStartTime := True
  else
    if ViewData.ShowTimeAsClock and not Event.AllDayEvent then
    begin
      ViewData.ShowStartTime := ViewData.ShowStartTime and (TimeOf(Event.Start) <> 0);
      ViewData.ShowFinishTime := ViewData.ShowFinishTime and (TimeOf(Event.Finish) <> 0);
    end;
end;

procedure TcxSchedulerWeekViewEventCellViewInfo.CalculateItemsLayout;
begin
  if IsHeaderEvent then
    CalculateHeaderEventLayout
  else
    CalculateNonDetailEventLayout;
end;

function TcxSchedulerWeekViewEventCellViewInfo.GetEditingRect: TRect;
begin
  Result := inherited GetEditingRect;
  with Result do
  begin
    if not IsHeaderEvent then
    begin
      if not cxRectIsEmpty(FFinishRect) then
        Left := FFinishRect.Right
      else
        if not cxRectIsEmpty(FStartRect) then
          Left := FStartRect.Right
        else
          Left := FBounds.Left;
      Inc(Left, cxTextOffset + cxEventImagesGap);
      Dec(Right);
      Inc(Top);
      Dec(Bottom);
    end;
  end;
end;

procedure TcxSchedulerWeekViewEventCellViewInfo.InitHitTest(
  AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
  inherited InitHitTest(AHitTest);
  if IsHeaderEvent then
    InitHitTestForHorzEvent(AHitTest)
  else
    if (ShowStartTime and (AHitTest.HitX <= FStartRect.Right)) or
      (ShowFinishTime and (AHitTest.HitX <= FFinishRect.Right)) then
        AHitTest.SetDragKind(edkEventDragRect);
end;

{ TcxSchedulerWeekViewViewInfo }

constructor TcxSchedulerWeekViewViewInfo.Create(AOwner: TcxSchedulerSubControl);
begin
  inherited Create(AOwner);
  Builder := TcxSchedulerEventLayoutBuilder.Create;
end;

destructor TcxSchedulerWeekViewViewInfo.Destroy;
begin
  Builder.Free;
  inherited Destroy;
end;

procedure TcxSchedulerWeekViewViewInfo.ScrollVertical(
  AScrollCode: TScrollCode; var AScrollPos: Integer);
var
  ADelta: Integer;
begin
  ADelta := View.GetScrollPos(StartDates[0], False);
  if not (AScrollCode in [scPosition, scTrack]) then
    AScrollPos := ADelta;
  case AScrollCode of
    scLineUp:
      Dec(AScrollPos, 1);
    scLineDown:
      Inc(AScrollPos, 1);
    scPageUp:
      Dec(AScrollPos, Weeks.Count);
    scPageDown:
      Inc(AScrollPos, Weeks.Count);
    scTop:
      AScrollPos := -View.GetMinScrollPos;
    scBottom:
      AScrollPos := View.GetMaxScrollPos;
  end;
  ADelta := ADelta - AScrollPos;
  if ADelta <> 0 then
  begin
    View.ScrollSelectedDays(ADelta);
    View.LayoutChanged;
    AScrollPos := View.GetScrollPos(StartDates[0]);
  end;
end;

function TcxSchedulerWeekViewViewInfo.AddContentCell(const ARect: TRect;
  const AStart, AFinish: TDateTime; AResourceIndex: Integer): TcxSchedulerContentCellViewInfo;
begin
  Result := inherited AddContentCell(ARect, AStart, AFinish, AResourceIndex);
  Result.DontPrint := PrintExactlyOneMonth and (MonthOf(AStart) <> PrintedMonth);
end;

procedure TcxSchedulerWeekViewViewInfo.AddDayCellEvent(
  APlace: TcxSchedulerEventPlace);
var
  I, AOfs: Integer;
  AStart, AFinish: TDateTime;
  ABounds, AVisibleRect: TRect;
  AResource: TcxSchedulerResourceViewInfo;
  AViewData: TcxSchedulerEventViewData;
  ACell: TcxSchedulerEventCellViewInfo;
  AEvent: TcxSchedulerControlEvent;
begin
  AOfs := DayCells[APlace.ColStart].Bounds.Top + GetDayCellHeaderHeight;
  AEvent := TcxSchedulerControlEvent(APlace.Event);
  ABounds.Top := 0;
  ABounds.Bottom := FContentLineHeight;
  GetEventInfo(APlace.ColStart, APlace.ColFinish, ABounds.Left,
    ABounds.Right, AStart, AFinish, AVisibleRect, AResource);
  OffsetRect(ABounds, 0, AOfs + APlace.LineStart * (FContentLineHeight + cxTextOffset));
  if ABounds.Bottom <= AVisibleRect.Bottom then
  begin
    AViewData := CreateEventViewData(AEvent, ABounds, AStart, AFinish, AResource);
    AViewData.VisibleRect := AVisibleRect;
    if AEvent.Selected then
      with Styles.GetSelectionParams do
      begin
        AViewData.ViewParams.Color := Color;
        AViewData.ViewParams.TextColor := TextColor;
        AViewData.ViewParams.Font := Font;
      end;
    ACell := AddEventCell(AViewData);
    if not (AEvent.AllDayEvent or (AEvent.Duration >= 1)) then
    begin
      ACell.Transparent := not (AEvent.Selected or Styles.IsEventStyleAssigned(AEvent));
      ACell.Borders := [];
    end;
  end
  else
    for I := APlace.ColStart to APlace.ColFinish do
    begin
       if DayCells[I].LineCount <> MaxInt then
       begin
         AddButton(DayCells[I].Bounds, DayCells[I].TimeStart, -1, True);
         DayCells[I].LineCount := MaxInt;
       end;
    end;
end;

procedure TcxSchedulerWeekViewViewInfo.AddDayCellEventPlace(
  AEvent: TcxSchedulerControlEvent; var AIndex: Integer);
var
  I, J: Integer;
  ADay: TcxSchedulerContentCellViewInfo;
begin
  if not CanEventVisible(AEvent) then
  begin
    Inc(AIndex);
    Exit;
  end;
  J := -1;
  for I := AIndex to DayCellCount - 1 do
  begin
    ADay := DayCells[I];
    if IsSingleLine(DayCells[AIndex], ADay)  and IsCellEvent(AEvent, ADay) then
    begin
      if CanVisibleNextLine(ADay) then
      begin
        J := I;
        ADay.LineCount := ADay.LineCount + 1;
      end
      else
      begin
        AddButton(ADay.Bounds, ADay.TimeStart, -1, True);
        ADay.LineCount := MaxInt;
        Break;
      end;
      if AEvent.Duration < 1 then Break;
    end
    else
    begin
      if J = -1 then
        AIndex := I + 1;
      Break;
    end;
  end;
  if (J <> -1) and (J >= AIndex) then
  begin
    Builder.AddEventPlace(AEvent, AIndex, J);
    AIndex := J + 1;
  end;
end;

function TcxSchedulerWeekViewViewInfo.AddWeekDayHeader(
  AWeekDay: Integer; ALeft, ARight: Integer): TcxSchedulerWeekDayHeaderCellViewInfo;
begin
  Inc(AWeekDay, Integer(View.StartOfWeek));
  if AWeekDay >= 7 then Dec(AWeekDay, 7);
  CreateCellInstance(TcxSchedulerWeekDayHeaderCellViewInfo, cxRect(ALeft, FDayHeaderOffsetTop,
    ARight, FDayHeaderOffsetTop + FDayHeaderHeight),
      StylesAdapter.GetDayHeaderParams(View.FirstVisibleDate + AWeekDay), Result);
  if CompressWeekEnd and (AWeekDay >= 6) then
    Result.DateTime := 8
  else
    Result.DateTime := AWeekDay;
  DayHeaderCells.Add(Result);
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateDaysLayout;
begin
  if GroupByResource then
    ProcessGroupByResource
  else
    if GroupByDate then
      ProcessGroupByDate
    else
      ProcessGroupByNone;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateDaysLayoutForResource(
  const ABounds: TRect; AResourceIndex: Integer);
const
  AddBorders: array[Boolean] of TcxBorders = ([bRight], []);
begin
  CalculateWeekDisplayRectsVert(StartDates[0], AResourceIndex, ABounds,
    AddBorders[HasSeparator or (AResourceIndex = (ResourceCount - 1))]);
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateDaysLayoutForDates(
  const ABounds: TRect; AResourceIndex: Integer);
begin

end;

procedure TcxSchedulerWeekViewViewInfo.CalculateEventsViewInfo;
var
  I, J: Integer;
  AEvent: TcxSchedulerControlEvent;
begin
  for I := 0 to Events.AbsoluteCount - 1 do
  begin
    J := 0;
    AEvent := Events.AbsoluteItems[I];
    while J < DayCellCount do
    begin
      if IsCellEvent(AEvent, DayCells[J]) then
        AddDayCellEventPlace(AEvent, J)
      else
        Inc(J);
    end;
  end;
  Builder.Calculate;
  for I := 0 to Builder.EventPlaceCount - 1 do
    AddDayCellEvent(Builder.EventPlaces[I]);
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateGroupByDateForResource(
  const ABounds: TRect; AResourceIndex: Integer);
begin
  CalculateWeekDisplayRectsHorz(StartDates[0], AResourceIndex, ABounds, True, True);
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateHeaderViewInfo;
var
  R: TRect;
  I, AIndex: Integer;
  ACell: TcxSchedulerContentCellViewInfo;
  AHeader: TcxSchedulerDayHeaderCellViewInfo;
const
  ANeighbors: array[Boolean] of TcxNeighbors = ([], [nLeft]);
begin
  if GroupByDate then
    for I := 0 to RowCols - 1 do
    begin
      ACell := DayCells[I];
      AHeader := AddWeekDayHeader(I + RowColsStart, ACell.Bounds.Left, ACell.Bounds.Right);
      AHeader.Compressed := (I = 5) and CompressWeekEnd;
    end
  else
  begin
    AIndex := Byte(ResourceCount > 0) - 1;
    for I := 0 to ContentCells.Count - 1 do
    begin
      ACell := TcxSchedulerContentCellViewInfo(ContentCells[I]);
      R := cxRectSetHeight(ACell.Bounds, FDayHeaderHeight);
      OffsetRect(R, 0, 1);
      if HasVisibleBounds then
      begin
        Inc(R.Right);
        OffsetRect(R, 0, -1);
      end;
      if (View.DaysLayout <> wdlOneColumn) and (not HasSeparator or ((I mod 7) <= 2)) then
        Dec(R.Right);
      with AddDayHeader(ACell.TimeStart, R, AIndex) do
      begin
        AlignHorz := taRightJustify;
        Selected := IsTimeSelected(DateTime, Resource);
        if Selected and not HideSelection then
        begin
          SelectionColor := FSelectionParams.Color;
          SelectionTextColor := FSelectionParams.TextColor;
        end; 
      end;
      if (I + 1) mod 7 = 0 then Inc(AIndex);
    end;
  end;
  ProcessDateToDisplayText(True);
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateMetrics;
begin
  inherited CalculateMetrics;
  FDayHeaderOffsetTop := Bounds.Top;
  FHeaderOffsetLeft := Bounds.Left;
  FResourceHeaderWidth := FResourceHeaderHeight;
  Weeks.Clear;
  CalculatePrintRowCols;
  CalculateWeekDates;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculatePrintRowCols;
begin
  FWeekEndCells := Byte(not PrintWeekEnds) * (Byte(not CompressWeekEnd) + 1);
  FRowColsStart := 0;
  FRowCols := 7 - Byte(CompressWeekEnd) - FWeekEndCells;
  CalculateStartFinishCellIndexes;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateResourceHeadersAutoHeight(
  AWidth: Integer);
begin
  if GroupByDate and not RotateCaptions then
    FResourceHeaderHeight := CalculateResourceHeaderWidth
  else
    inherited CalculateResourceHeadersAutoHeight(AWidth);
  FResourceHeaderWidth := FResourceHeaderHeight;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateStartFinishCellIndexes;
begin
  if PagesPerWeek = 1 then Exit;
  if PrimaryPage then
    FRowCols := 3
  else
  begin
    FRowColsStart := 3;
    FRowCols := FRowCols - FRowColsStart;
  end;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateWeekDates;
var
  I, ADate: Integer;
  AYear, APrevYear, AWeek, APrevWeek, AWeekDay: Word;
begin
  APrevYear := 0;
  APrevWeek := 0;
  for I := 0 to DayCount - 1 do
  begin
    DecodeDateWeek(Days[I] + View.GetDateOffset, AYear, AWeek, AWeekDay);
    if (AYear <> APrevYear) or (AWeek <> APrevWeek) then
    begin
      APrevYear := AYear;
      APrevWeek := AWeek;
      //DELPHI8! check Trunc(EncodeDateWeek(AYear, AWeek, 1))
      ADate := Trunc(EncodeDateWeek(AYear, AWeek, 1));
      Weeks.Add(ADate);
    end;
  end;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateWeekDisplayRectsHorz(
  const AStartDate: TDateTime; AResourceID: Integer;
  {const }ABounds: TRect; AIsTopWeek, AIsLastWeek: Boolean);
var
  I, J, W: Integer;
  ARects: TcxSchedulerDaysRect;
  ACellBorders: TcxBorders;
const
  ABorders: array[Boolean] of TcxBorders = ([bTop, bRight], [bTop]);
begin
  W := ABounds.Right - ABounds.Left;
  for I := 0 to RowCols - 1 do
  begin
    J := I + RowColsStart;
    ARects[J] := cxRect(ABounds.Left + MulDiv(W, I, RowCols),
      ABounds.Top - 1, ABounds.Left + MulDiv(W, I + 1, RowCols), ABounds.Bottom);
    if CompressWeekEnd and (J = 5) then
      cxRectSplitVert(ARects[5], ARects[5], ARects[6]);
  end;
  for I := 0 to RowCols - 1 + Byte(CompressWeekEnd) * Byte(PrintWeekEnds) do
  begin
    ACellBorders := ABorders[(I >= (RowCols - 1)) and (HasSeparator or (AResourceID = (ResourceCount - 1)))];
    if AIsTopWeek and (I <> RowCols) then
      Exclude(ACellBorders, bTop);
    if AIsLastWeek and not HasSeparator and (I <> RowCols - 1) and (AResourceID <> ResourceCount - 1) then
      Include(ACellBorders, bBottom);
    J := I + RowColsStart;
    AddContentCell(ARects[J], AStartDate + J,
      AStartDate + J + 1, AResourceID).Borders := ACellBorders;
  end;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateWeekDisplayRectsVert(
  const AStartDate: TDateTime; AResourceID: Integer;
  const ABounds: TRect; AddBorders: TcxBorders = []);
var
  R: TRect;
  I, J: Integer;
  ARects: TcxSchedulerDaysRect;
  ASize: TSize;
begin
  if View.DaysLayout = wdlOneColumn then
  begin
    CalculateWeekDisplayRectsVertEx(AStartDate, AResourceID, ABounds, AddBorders);
    Exit;
  end;
  FillChar(ARects, SizeOf(ARects), 0);
  ASize := cxRectSize(ABounds);
  for I := 0 to 2 do
  begin
    R := cxRect(ABounds.Left, ABounds.Top + MulDiv(ASize.CY, I, 3),
      ABounds.Right, ABounds.Top + MulDiv(ASize.CY, I + 1, 3));
    if PagesPerWeek = 1 then
      cxRectSplitHorz(R, ARects[I], ARects[I + 3])
    else
    begin
      ARects[I] := R;
      ARects[I + 3] := R;
    end;
  end;
  cxRectSplitVert(ARects[5], ARects[5], ARects[6]);
  for I := 0 to RowCols do
  begin
    J := RowColsStart + I;
    AddContentCell(ARects[J], AStartDate + J, AStartDate + J + 1,
      AResourceID).Borders := WeekViewDayBorders[J] + AddBorders;
  end;
end;

procedure TcxSchedulerWeekViewViewInfo.CalculateWeekDisplayRectsVertEx(
  const AStartDate: TDateTime; AResourceID: Integer;
  const ABounds: TRect; AddBorders: TcxBorders = []);
var
  R: TRect;
  I, J, C: Integer;
  ARects: TcxSchedulerDaysRect;
  ASize: TSize;
begin
  FillChar(ARects, SizeOf(ARects), 0);
  ASize := cxRectSize(ABounds);
  C := RowCols + 1 - Byte(View.CompressWeekEnd);
  for I := 0 to C - 1  do
  begin
    R := cxRect(ABounds.Left, ABounds.Top + MulDiv(ASize.CY, I, C),
      ABounds.Right, ABounds.Top + MulDiv(ASize.CY, I + 1, C));
    ARects[RowColsStart + I] := R;
  end;
  if View.CompressWeekEnd then
    cxRectSplitVert(ARects[5], ARects[5], ARects[6]);
  C := RowCols;
  if (PagesPerWeek > 1) and PrimaryPage then
    Dec(C);
  for I := 0 to C do
  begin
    J := RowColsStart + I;
    AddContentCell(ARects[J], AStartDate + J, AStartDate + J + 1,
      AResourceID).Borders := [bTop] + AddBorders;
  end;
end;

function TcxSchedulerWeekViewViewInfo.CanEventVisible(
  AEvent: TcxSchedulerControlEvent): Boolean;
begin
  Result := not (AEvent.IsClone and FHideClones);
end;

function TcxSchedulerWeekViewViewInfo.CanVisibleNextLine(
  ADay: TcxSchedulerContentCellViewInfo; ALine: Integer = -1): Boolean;
begin
  if ALine = -1 then
    ALine := ADay.LineCount;
  Result := (GetDayCellContentHeight(ADay))  >=
    (ALine + 1) * FContentLineHeight;
end;

procedure TcxSchedulerWeekViewViewInfo.CheckHeaderBorders;
var
  I: Integer; 
const
  ANeigbors: array[Boolean] of TcxNeighbors =
    ([], [nTop]);
  ADayHeader: array[Boolean] of TcxNeighbors =
    ([], [nLeft]);
  ABorders: array[Boolean] of TcxBorders =
    ([], [bBottom]);
begin
  ProcessCheckBorders(DayHeaderCells, GroupingKind = gkByDate,
    ANeigbors[not GroupByDate] + ADayHeader[GroupByDate]);
  ProcessCheckBorders(ResourceHeaderCells, False, [], ABorders[GroupByResource]);
  if not GroupByDate then
  begin
    if GroupByResource then
      with TcxSchedulerDayHeaderCellViewInfo(ResourceHeaderCells[0]) do
        Borders := Borders - [bLeft];
    for I := 0 to DayHeaderCells.Count - 1 do
      with TcxSchedulerDayHeaderCellViewInfo(DayHeaderCells[I]) do
        Borders := [bBottom, bTop] * LookAndFeelPainter.HeaderBorders([nTop]);
  end;
end;

function TcxSchedulerWeekViewViewInfo.ContentCellClass: TcxSchedulerContentCellViewInfoClass;
begin
  if GroupByDate then
    Result := TcxSchedulerMonthDayContentCellViewInfo
  else
    Result := inherited ContentCellClass;
end;

function TcxSchedulerWeekViewViewInfo.CreateEventCellViewInfo(
  AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo;
begin
  Result := TcxSchedulerWeekViewEventCellViewInfo.Create(AViewData);
end;

function TcxSchedulerWeekViewViewInfo.CompressWeekEnd: Boolean;
begin
  if GroupByDate then
    Result := View.CompressWeekEnd
  else
    Result := True;
end;

procedure TcxSchedulerWeekViewViewInfo.DoCalculate;
begin
  FPrintWeekEnds := True; 
  Builder.Clear;
  inherited DoCalculate;
  FPrintExactlyOneMonth := Adapter.PrintExactlyOneMonth;
  if FPrintExactlyOneMonth then
    FPrintedMonth := MonthOf(Days[DayCount div 2]);
  if IsCalculateHeaderFirst then
  begin
    CalculateHeaderViewInfo;
    CalculateDaysLayout;
  end
  else
  begin
    CalculateDaysLayout;
    CalculateHeaderViewInfo;
  end;
  CalculateEventsViewInfo;
  CheckHeaderBorders;
end;

procedure TcxSchedulerWeekViewViewInfo.DoMoreEventsButtonClick(
  Sender: TcxSchedulerMoreEventsButtonViewInfo);
begin
  SelectedDays.Clear;
  SelectedDays.Add(Sender.DateTime);
  View.PeriodChanged;
end;

procedure TcxSchedulerWeekViewViewInfo.GetEventInfo(AColStart, AColFinish: Integer;
  var ALeft, ARight: Integer; var AStart, AFinish: TDateTime;
  var AVisibleRect: TRect; var AResource: TcxSchedulerResourceViewInfo);
begin
  with DayCells[AColStart] do
  begin
    ALeft := Bounds.Left + cxTextOffset;
    AStart := TimeStart;
    AResource := Resource;
    AVisibleRect := Bounds;
  end;
  with DayCells[AColFinish] do
  begin
    ARight := Bounds.Right - cxTextOffset - 1;
    AFinish := TimeFinish;
    AVisibleRect.Right := Bounds.Right;
  end;
  Dec(AVisibleRect.Bottom, cxTextOffset);
end;

function TcxSchedulerWeekViewViewInfo.GetResourcesContentWidth: Integer;
begin
  if GroupByResource then
    Result := Bounds.Right - Bounds.Left
  else
    Result := inherited GetResourcesContentWidth;
end;

function TcxSchedulerWeekViewViewInfo.GetResourceImagesSize: TSize;
begin
  if ResourceImages = nil then
    Result := TSize(cxNullSize)
  else
  begin
    Result := inherited GetResourceImagesSize;
    if GroupByDate and ResourceHeaders.RotateCaptions then
      Result := cxSize(ResourceImages.Height, ResourceImages.Width);
  end;
end;

function TcxSchedulerWeekViewViewInfo.GetResourceScrollBarKind: TScrollBarKind;
begin
  if (FGroupingKind = gkByDate) and ResourceNavigator.NeedScrollBar then
    Result := sbVertical
  else
    Result := sbHorizontal
end;

function TcxSchedulerWeekViewViewInfo.GetContentParams(
  const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams;
begin
  if AResource = nil then
    Result := StylesAdapter.GetContentParams(ATime, True, nil)
  else
    Result := StylesAdapter.GetContentParams(ATime, True, AResource.ResourceItem);
end;

function TcxSchedulerWeekViewViewInfo.GetDayCellContentHeight(
  ADay: TcxSchedulerContentCellViewInfo): Integer;
begin
  Result := cxRectHeight(PainterHelper.ExcludeBorders(ADay.Bounds,
    ADay.Borders)) - GetDayCellHeaderHeight - cxTextOffset;
end;

function TcxSchedulerWeekViewViewInfo.GetDayCellHeaderHeight: Integer;
begin
  if GroupByDate then
    Result := cxTextOffset + FContentFontHeight
  else
    Result := FDayHeaderHeight + cxTextOffset;
end;

function TcxSchedulerWeekViewViewInfo.IsCalculateHeaderFirst: Boolean;
begin
  Result := False;
end;

function TcxSchedulerWeekViewViewInfo.IsCellEvent(
  AEvent: TcxSchedulerControlEvent; ACell: TcxSchedulerContentCellViewInfo): Boolean;
begin
  Result := (ACell <> nil) and AEvent.IsDayEvent(ACell.TimeStart);
  if Result and (GroupingKind <> gkNone) then
    Result := AEvent.IsResourceEvent(ACell.Resource.ResourceItem, ShowEventsWithoutResource);
  if Result and PrintExactlyOneMonth then
    Result := MonthOf(ACell.TimeStart) = PrintedMonth; 
end;

function TcxSchedulerWeekViewViewInfo.IsSingleLine(
  ADay1, ADay2: TcxSchedulerContentCellViewInfo): Boolean;
begin
  Result := (ADay1 <> nil) and (ADay2 <> nil) and
    (ADay1.Bounds.Top = ADay2.Bounds.Top);
end;

function TcxSchedulerWeekViewViewInfo.IsTimeSelected(
  ATime: TDateTime; AResource: TObject): Boolean;
begin
  ATime := DateTimeHelper.RoundTime(ATime);
  Result := not HideSelection and (AResource = FSelResource) and
    (ATime >= SelStart) and (ATime <= SelFinish);
  Result := Result and CanSelected;
end;

procedure TcxSchedulerWeekViewViewInfo.ProcessGroupByDate;

  function IsSameMonth(ACell1, ACell2: TcxSchedulerMonthDayContentCellViewInfo): Boolean;
  begin
    Result := (ACell1 <> nil) and (ACell2 <> nil);
    if Result then
      Result := ACell1.Resource = ACell2.Resource;    
    if Result then
      Result := MonthOf(ACell1.TimeStart) = MonthOf(ACell2.TimeStart);
  end;

var
  I, H: Integer;
  ABounds: TRect;

  ACell: TcxSchedulerHeaderCellViewInfo;
  APrevCell, AContentCell: TcxSchedulerMonthDayContentCellViewInfo;
begin
  ABounds := Bounds;
  Inc(ABounds.Left, ResourceHeaderWidth);
  H := cxRectHeight(ABounds) - DayHeaderHeight -
    SeparatorWidth * (ResourceCount - 1);
  AddResourceHeader(-1, cxRectSetSize(Bounds, ResourceHeaderWidth, DayHeaderHeight));
  for I := 0 to ResourceCount - 1 do
  begin
    ABounds.Top := Bounds.Top + DayHeaderHeight +
      MulDiv(H, I, ResourceCount) + SeparatorWidth * I + 1;
    ABounds.Bottom := Bounds.Top + DayHeaderHeight +
      MulDiv(H, I + 1, ResourceCount) + SeparatorWidth * I;
    CalculateGroupByDateForResource(ABounds, I);
    if I < (ResourceCount - 1) then
      AddGroupHorzSeparator(ABounds.Bottom);
    Dec(ABounds.Top);
    ACell := AddResourceHeader(I, cxRectSetWidth(ABounds,
      Bounds.Left, ResourceHeaderWidth));
    ACell.RotateText := RotateCaptions;
    ACell.RotateHeader := True;
  end;
  APrevCell := nil;
  for I := 0 to ContentCells.Count - 1 do
  begin
    AContentCell := TcxSchedulerMonthDayContentCellViewInfo(ContentCells[I]);
    AContentCell.SetContentState(IsSameMonth(APrevCell, AContentCell),
      IsTimeSelected(AContentCell.TimeStart, AContentCell.Resource),
      FContentFontHeight, FSelectionParams);
    APrevCell := AContentCell;
  end;
end;

procedure TcxSchedulerWeekViewViewInfo.ProcessGroupByNone;
begin
  CalculateWeekDisplayRectsVert(StartDates[0], -1, Bounds);
end;

procedure TcxSchedulerWeekViewViewInfo.ProcessGroupByResource;
var
  I, W: Integer;
  ABounds: TRect;
  ACell: TcxSchedulerHeaderCellViewInfo;
begin
  ABounds := Bounds;
  W := ABounds.Right - ABounds.Left - SeparatorWidth * (ResourceCount - 1);
  Inc(ABounds.Top, ResourceHeaderHeight);
  for I := 0 to ResourceCount - 1 do
  begin
    ABounds.Left := MulDiv(W, I, ResourceCount) + SeparatorWidth * I;
    ABounds.Right := MulDiv(W, I + 1, ResourceCount) + SeparatorWidth * I;
    CalculateDaysLayoutForResource(ABounds, I);
    if I < (ResourceCount - 1) then
      AddGroupVertSeparator(ABounds.Right);
    ACell := AddResourceHeader(I, cxRectSetTop(ABounds, Bounds.Top, ResourceHeaderHeight));
    ACell.Borders := LookAndFeelPainter.HeaderBorders([nLeft, nRight, nBottom]);
    if not (bLeft in ACell.Borders) then
      ACell.Borders := ACell.Borders - [bRight, bBottom];
  end;
end;

function TcxSchedulerWeekViewViewInfo.GetDayCell(
  ADay: Integer): TcxSchedulerContentCellViewInfo;
begin
  Result := TcxSchedulerContentCellViewInfo(ContentCells[ADay]);
end;

function TcxSchedulerWeekViewViewInfo.GetDayCellCount: Integer;
begin
  Result := ContentCells.Count;
end;

function TcxSchedulerWeekViewViewInfo.GetRotateCaptions: Boolean;
begin
  Result := View.OptionsView.RotateResourceCaptions;
end;

function TcxSchedulerWeekViewViewInfo.GetStartDate(AWeek: Integer): TDateTime;
begin
  Result := Weeks[AWeek];
  if not CompressWeekEnd then
    Result := Result - View.GetDateOffset;
end;

function TcxSchedulerWeekViewViewInfo.GetView: TcxSchedulerWeekView;
begin
  Result := TcxSchedulerWeekView(inherited View);
end;

function TcxSchedulerWeekViewViewInfo.GetWeeks: TcxSchedulerDateList;
begin
  Result := View.FWeeks;
end;

{ TcxSchedulerWeeksViewEventCellViewInfo }

function TcxSchedulerWeeksViewEventCellViewInfo.CanAutoHideStandardImages: Boolean;
begin
  Result := True;
end;

{ TcxSchedulerWeeksViewViewInfo }

procedure TcxSchedulerWeeksViewViewInfo.CalculateDaysLayoutForResource(
  const ABounds: TRect; AResourceIndex: Integer);
var
  R: TRect;
  C, I, H, ATop, APrevMonth: Integer;
  ACell: TcxSchedulerMonthDayContentCellViewInfo;
begin
  ATop := ABounds.Top;
  if not GroupByDate then
    Inc(ATop, FDayHeaderHeight);
  H := ABounds.Bottom - ATop;
  C := ContentCells.Count;
  for I := 0 to Weeks.Count - 1 do
  begin
    R := cxRect(ABounds.Left, ATop + MulDiv(H, I, Weeks.Count),
      ABounds.Right, ATop + MulDiv(H, I + 1, Weeks.Count));
    if (I > 0) or not GroupByDate then Inc(R.Top);
    CalculateWeekDisplayRectsHorz(StartDates[I], AResourceIndex, R, I = 0, I = Weeks.Count - 1);
  end;
  APrevMonth := -1;
  for I := C to ContentCells.Count - 1 do
  begin
    ACell := TcxSchedulerMonthDayContentCellViewInfo(ContentCells[I]);
    ACell.SetContentState(APrevMonth = MonthOf(ACell.TimeStart),
      IsTimeSelected(ACell.TimeStart, ACell.Resource), FContentFontHeight, FSelectionParams);
    APrevMonth := MonthOf(ACell.TimeStart);
  end;
end;

procedure TcxSchedulerWeeksViewViewInfo.CalculateGroupByDateForResource(
  const ABounds: TRect; AResourceIndex: Integer);
begin
  CalculateDaysLayoutForResource(ABounds, AResourceIndex);
end;

procedure TcxSchedulerWeeksViewViewInfo.CalculateHeaderViewInfo;
var
  I, W: Integer;
begin
  if GroupByResource then Exit;
  if GroupByDate then
    FHeaderOffsetLeft := ResourceHeaderWidth + Bounds.Left;
  W := Bounds.Right - FHeaderOffsetLeft;
  for I := 0 to RowCols - 1 do
  begin
    AddWeekDayHeader(I + RowColsStart, MulDiv(W, I, RowCols) + FHeaderOffsetLeft,
      MulDiv(W, I + 1, RowCols) + FHeaderOffsetLeft);
  end;
  ProcessDateToDisplayText(True);
  FContentOffset := FDayHeaderHeight;
end;

procedure TcxSchedulerWeeksViewViewInfo.CheckHeaderBorders;
const
  ANeigbors: array[Boolean] of TcxNeighbors =
    ([], [nTop]);
begin
  ProcessCheckBorders(DayHeaderCells, False, ANeigbors[GroupByResource]);
  ProcessCheckBorders(ResourceHeaderCells, False);
  if not GroupByDate or not (bLeft in LookAndFeelPainter.HeaderBorders([nLeft])) then
  begin
    with TcxSchedulerHeaderCellViewInfo(DayHeaderCells[0]) do
      Borders := Borders - [bLeft];
    if GroupByResource then
      with TcxSchedulerDayHeaderCellViewInfo(ResourceHeaderCells[0]) do
        Borders := Borders - [bLeft];
  end;
end;

function TcxSchedulerWeeksViewViewInfo.CompressWeekEnd: Boolean;
begin
  Result := View.CompressWeekEnd;
end;

function TcxSchedulerWeeksViewViewInfo.ContentCellClass: TcxSchedulerContentCellViewInfoClass;
begin
  Result := TcxSchedulerMonthDayContentCellViewInfo;
end;

function TcxSchedulerWeeksViewViewInfo.CreateEventCellViewInfo(
  AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo;
begin
  Result := TcxSchedulerWeeksViewEventCellViewInfo.Create(AViewData);
end;

function TcxSchedulerWeeksViewViewInfo.GetContentParams(
  const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams;
begin
  if AResource = nil then
    Result := StylesAdapter.GetContentParams(ATime, not Odd(MonthOf(ATime)), nil)
  else
    Result := StylesAdapter.GetContentParams(ATime, not Odd(MonthOf(ATime)),
       AResource.ResourceItem);
end;

function TcxSchedulerWeeksViewViewInfo.GetDayCellHeaderHeight: Integer;
begin
  Result := cxTextOffset + FContentFontHeight;
end;

function TcxSchedulerWeeksViewViewInfo.IsCalculateHeaderFirst: Boolean;
begin
  Result := True;
end;

procedure TcxSchedulerWeeksViewViewInfo.ProcessGroupByNone;
begin
  CalculateDaysLayoutForResource(Bounds, -1);
end;

procedure TcxSchedulerWeeksViewViewInfo.ProcessGroupByResource;
var
  I, J, W: Integer;
  ACell: TcxSchedulerHeaderCellViewInfo;
begin
  inherited ProcessGroupByResource;
  Inc(FDayHeaderOffsetTop, FResourceHeaderHeight);
  for J := 0 to ResourceHeaderCells.Count - 1 do
  begin
    ACell := TcxSchedulerHeaderCellViewInfo(ResourceHeaderCells[J]);
    W := cxRectWidth(ACell.Bounds);
    for I := 0 to RowCols - 1 do
      AddWeekDayHeader(I + RowColsStart, MulDiv(W, I, RowCols) + ACell.Bounds.Left,
        MulDiv(W, I + 1, RowCols) +  + ACell.Bounds.Left).Resource := ACell.Resource;
    ProcessDateToDisplayText(True);
  end;
end;

{ TcxSchedulerWeekViewPainter }

procedure TcxSchedulerWeekViewPainter.Paint;
begin
  inherited Paint;
  ViewInfo.ContentCells.Draw(Canvas, DrawContentCell);
  ViewInfo.DayHeaderCells.Draw(Canvas, DrawHeaderCell);
  ViewInfo.ResourceHeaderCells.Draw(Canvas, DrawResourceHeaderCell);
  ViewInfo.GroupSeparatorCells.Draw(Canvas, DrawGroupSeparatorCell);
  ViewInfo.EventCells.Draw(Canvas, DrawEventCell);
  ViewInfo.Buttons.Draw(Canvas, DrawButtonCell);
end;

function TcxSchedulerWeekViewPainter.GetViewInfo: TcxSchedulerWeekViewViewInfo;
begin
  Result := TcxSchedulerWeekViewViewInfo(inherited ViewInfo);
end;

end.
