{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvYearGrid.PAS, released on 2002-06-15. The Initial Developer of the Original Code is Jan Verhoeven [jan1 dott verhoeven att wxs dott nl] Portions created by Jan Verhoeven are Copyright (C) 2002 Jan Verhoeven. All Rights Reserved. Contributor(s): Robert Love [rlove at slcdug dot org]. Olivier Sannier [obones at users dot sourceforge dot net] You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.delphi-jedi.org Known Issues: -----------------------------------------------------------------------------} // $Id$ unit JvYearGrid; {$mode objfpc}{$H+} interface uses LCLIntf, Types, Graphics, Controls, Forms, Dialogs, Grids, Menus, Clipbrd, SysUtils, StdCtrls, Classes, JvJVCLUtils, JvTypes; const JvDefaultBorderColor = TColor($EEF5FF); JvDefaultBookmarkColor = clYellow; JvDefaultWeekendColor = TColor($DFDFDF); type TYearData = record DisplayText: string; InfoText: string; DayInMonth: Integer; DefaultColor: TColor; CustomColor: TColor; Custom: Boolean; BookMark: Boolean; // this is not saved end; TJvYearGridOrientation = (yoHorizontal, yoVertical); TJvWeekDay = (wdMonday, wdTuesday, wdWednesday, wdThursday, wdFriday, wdSaturday, wdSunday); TJvWeekDaySet = set of TJvWeekDay; TJvMonthFormat = (mfShort, mfLong); TJvDayFormat = (dfInitial, dfShort, dfLong); TJvAutoSizeOptions = set of (aoGrid, aoFirstColumn, aoFirstRow, aoColumns, aoRows); TOnYearChanged = procedure(Sender: TObject; AYear: Integer) of object; TOnSelectDate = procedure(Sender: TObject; ADate: TDate; InfoText: string; InfoColor: TColor) of object; TOnInfoChanging = procedure(Sender: TObject; var InfoText: string; var CanChange: Boolean) of object; TDays = array [1..12] of Integer; TYearDataMatrix = array [0..37, 0..12] of TYearData; TJvYearGrid = class(TCustomDrawGrid) private FGridPop: TPopupMenu; FCurrentYear: Word; FCurrentMonth: Word; FCurrentDay: Word; FHTMLBorder: Boolean; FHTMLFontName: string; FBorderColor: TColor; FBookMarkColor: TColor; FWeekendColor: TColor; FAutoSize: Boolean; FDayFormat: TJvDayFormat; FMonthFormat: TJvMonthFormat; FReadOnly: Boolean; FOnInfoChanging: TOnInfoChanging; FOnSelectDate: TOnSelectDate; FOnYearChanged: TOnYearChanged; DaysInMonth: TDays; StartDays: TDays; FYearData: TYearDataMatrix; FYearFile: string; FOrientation: TJvYearGridOrientation; FSavedScrollBars: TScrollStyle; FFirstDayOfWeek: TJvWeekDay; FWeekendDays: TJvWeekDaySet; FAutoSizeOptions: TJvAutoSizeOptions; FCellMargins: TJvRect; FDaysAlignment: TAlignment; FDayNamesAlignment: TAlignment; FMonthNamesAlignment: TAlignment; FYearAlignment: TAlignment; FYear: Integer; // Getters, setters function GetFlat: Boolean; function IsHtmlFontNameStored: Boolean; procedure SetAutoSizeOptions(const Value: TJvAutoSizeOptions); procedure SetBookMarkColor(const Value: TColor); procedure SetBorderColor(const Value: TColor); procedure SetCellMargins(const Value: TJvRect); procedure SetDayFormat(const AValue: TJvDayFormat); procedure SetDayNamesAlignment(const Value: TAlignment); procedure SetDaysAlignment(const Value: TAlignment); procedure SetFirstDayOfWeek(const Value: TJvWeekDay); procedure SetFlat(AValue: Boolean); procedure SetHTMLBorder(const Value: Boolean); procedure SetHTMLFontName(const Value: string); procedure SetMonthFormat(const AValue: TJvMonthFormat); procedure SetMonthNamesAlignment(const Value: TAlignment); procedure SetOrientation(const Value: TJvYearGridOrientation); procedure SetReadOnly(const Value: Boolean); procedure SetWeekendColor(const AValue: TColor); procedure SetWeekendDays(const Value: TJvWeekDaySet); procedure SetYear(const Value: Integer); procedure SetYearAlignment(const Value: TAlignment); // Event handlers procedure DoShowHint(var HintStr: THintString; var CanShow: Boolean; var HintInfo: THintInfo); procedure mnuBookMarkColorClick(Sender: TObject); procedure mnuBorderColorClick(Sender: TObject); procedure mnuClearFindClick(Sender: TObject); procedure mnuColorClick(Sender: TObject); procedure mnuCopyClick(Sender: TObject); procedure mnuCutClick(Sender: TObject); procedure mnuDeleteClick(Sender: TObject); procedure mnuEditClick(Sender: TObject); procedure mnuFindClick(Sender: TObject); procedure mnuNoColorClick(Sender: TObject); procedure mnuPasteClick(Sender: TObject); procedure mnuSaveAsHTML(Sender: TObject); procedure mnuSaveFound(Sender: TObject); procedure mnuYearClick(Sender: TObject); procedure SetupGridPop(Sender: TObject); procedure SetYearChanged(const Value: TOnYearChanged); // Utilities procedure MakeHTML(AList: TStringList; Border, Filter: Boolean); procedure SetupYearData; procedure SetupMonths; function GetCellData(var S: string): Boolean; function SetCellData(S: string): Boolean; procedure CreatePopup; procedure Launch(AFile: string); procedure SetSelectDate(const Value: TOnSelectDate); procedure SetInfoChanging(const Value: TOnInfoChanging); procedure ClearBookMarks; function IsCurrentYear: Boolean; procedure CellMarginsChange(Sender: TObject); function GetDefaultColWidth: Integer; procedure SetDefaultColWidth(const Value: Integer); procedure SetDefaultRowHeihgt(const Value: Integer); procedure SetFirstColWidth(const Value: Integer); procedure SetFirstRowHeight(const Value: Integer); function GetFirstColWidth: Integer; function GetFirstRowHeight: Integer; procedure ColRowToDayMonthIndex(ACol, ARow: Integer; out DayIndex, MonthIndex: Integer); procedure DayMonthIndexToColRow(DayIndex: Integer; MonthIndex: Integer; out ACol, ARow: Integer); protected procedure DrawColumnText(aCol, aRow: Integer; aRect: TRect; aState: TGridDrawState); override; procedure DrawTextInCell(aCol, aRow: Integer; aRect: TRect; {%H-}aState: TGridDrawState); override; function SelectCell(ACol, ARow: Integer): Boolean; override; procedure DblClick; override; procedure FontChanged(Sender: TObject); override; procedure DoPrepareCanvas(aCol,aRow:Integer; {%H-}aState: TGridDrawState); override; procedure SetAutoSize(Value: Boolean); override; procedure UpdateAllSizes; procedure AdjustBounds; procedure Loaded; override; procedure SetParent( AParent: TWinControl); override; // function GetDefaultRowHeight: Integer; override; // Those three methods are used to provide support for reading // the GridYear property from DFM files that were using // this component before its rewrite. The writer does nothing // because the value is now stored as Year. procedure ReadGridYear(Reader: TReader); procedure WriteGridYear({%H-}Writer: TWriter); procedure DefineProperties(Filer: TFiler); override; { LCL scaling } procedure DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy; const AXProportion, AYProportion: Double); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure LoadYear(FileName: string = ''); procedure SaveYear(FileName: string = ''); function GetSelDateText: string; procedure SetSelDateText(AText: string); function GetDateInfo(ADate: TDate; var AText: string): Boolean; function SetDateInfo(ADate: TDate; AText: string): Boolean; function CellToDate(ACol, ARow: Integer): TDate; function DateToCell(ADate: TDate; out ACol, ARow: Integer): Boolean; // This procedure does the default drawing for a given cell // It is made public so that you can call it in your OnDrawCell event // procedure DefaultDrawCell(ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); // Converts a (col, row) pair to a (day, month) couple taking // into account the orientation. If no day is in the indicated cell // then the value of ADay is 0 on exit. procedure ColRowToDayMonth(ACol, ARow: Integer; var ADay, AMonth: Integer); // Converts a (day, month) couple to a (col, row) couple taking // into account the orientation. If the day doesn't exist in the month // the indicated cell may be outside the grid procedure DayMonthToColRow(ADay, AMonth: Integer; var ACol, ARow: Integer); procedure Find; published property HTMLBorder: Boolean read FHTMLBorder write SetHTMLBorder default false; property HTMLFontName: string read FHTMLFontName write SetHTMLFontName stored IsHtmlFontNameStored; property BorderColor: TColor read FBorderColor write SetBorderColor default JvDefaultBorderColor; property BookMarkColor: TColor read FBookMarkColor write SetBookMarkColor default JvDefaultBookmarkColor; property WeekendColor: TColor read FWeekendColor write SetWeekendColor default JvDefaultWeekendColor; property Orientation: TJvYearGridOrientation read FOrientation write SetOrientation default yoHorizontal; property FirstDayOfWeek: TJvWeekDay read FFirstDayOfWeek write SetFirstDayOfWeek default wdMonday; property ReadOnly: Boolean read FReadOnly write SetReadOnly default false; property Year: Integer read FYear write SetYear; property YearFile: string read FYearFile write FYearFile; property AutoSize: Boolean read FAutoSize write SetAutoSize default True; property AutoSizeOptions: TJvAutoSizeOptions read FAutoSizeOptions write SetAutoSizeOptions default [aoGrid, aoFirstColumn, aoFirstRow, aoColumns, aoRows]; property FirstColWidth: Integer read GetFirstColWidth write SetFirstColWidth; property FirstRowHeight: Integer read GetFirstRowHeight write SetFirstRowHeight; property CellMargins: TJvRect read FCellMargins write SetCellMargins; property DayFormat: TJvDayFormat read FDayFormat write SetDayFormat default dfInitial; property MonthFormat: TJvMonthFormat read FMonthFormat write SetMonthFormat default mfLong; property WeekendDays: TJvWeekDaySet read FWeekendDays write SetWeekendDays default [wdSaturday, wdSunday]; property MonthNamesAlignment: TAlignment read FMonthNamesAlignment write SetMonthNamesAlignment default taLeftJustify; property DayNamesAlignment: TAlignment read FDayNamesAlignment write SetDayNamesAlignment default taCenter; property DaysAlignment: TAlignment read FDaysAlignment write SetDaysAlignment default taCenter; property YearAlignment: TAlignment read FYearAlignment write SetYearAlignment default taLeftJustify; property OnSelectCell; property OnDrawCell; property OnYearChanged: TOnYearChanged read FOnYearChanged write SetYearChanged; property OnSelectDate: TOnSelectDate read FOnSelectDate write SetSelectDate; property OnInfoChanging: TOnInfoChanging read FOnInfoChanging write SetInfoChanging; property OnDblClick; property OnClick; property DefaultColWidth: Integer read GetDefaultColWidth write SetDefaultColWidth default 18; property DefaultRowHeight default 18; property Align; property Anchors; property BorderSpacing; property BorderStyle; property Flat read GetFlat write SetFlat default true; property Font; property ScrollBars default ssNone; property TitleStyle; end; implementation uses JvConsts, JvResources, JvYearGridEditForm; const TodayFontColor = clWhite; TodayBrushColor = clRed; READONLY_TAG = 2; constructor TJvYearGrid.Create(AOwner: TComponent); var AYear, AMonth, ADay: Word; begin inherited Create(AOwner); FCellMargins := TJvRect.Create; FCellMargins.Top := 2; FCellMargins.Left := 2; FCellMargins.Bottom := 2; FCellMargins.Right := 2; FCellMargins.OnChange := @CellMarginsChange; // Must be set last FOrientation := yoHorizontal; FDaysAlignment := taCenter; FDayNamesAlignment := taCenter; FMonthNamesAlignment := taLeftJustify; FDayFormat := dfInitial; FMonthFormat := mfLong; FFirstDayOfWeek := wdMonday; FWeekendDays := [wdSaturday, wdSunday]; FAutoSizeOptions := [aoGrid, aoFirstColumn, aoFirstRow, aoColumns, aoRows]; FBorderColor := JvDefaultBorderColor; FBookMarkColor := JvDefaultBookmarkColor; FWeekendColor := JvDefaultWeekendcolor; ShowHint := True; CreatePopup; PopupMenu := FGridPop; FGridPop.OnPopup := @SetupGridPop; // Those two must be set before setting DefaultColWidth and DefaultRowHeight FirstRowHeight := 18; FirstColWidth := 70; DefaultColWidth := 18; DefaultRowHeight := 18; ColCount := 38; RowCount := 13; FixedCols := 1; FixedRows := 1; Width := 512; Height := 213; Flat := true; DecodeDate(Now, FCurrentYear, FCurrentMonth, FCurrentDay); HTMLFontName := 'default'; DecodeDate(Now, AYear, AMonth, ADay); FYear := AYear; SetupYearData; FAutoSize := True; FSavedScrollBars := ScrollBars; Invalidate; end; destructor TJvYearGrid.Destroy; begin // SaveYear; FGridPop.Free; FCellMargins.Free; inherited Destroy; end; procedure TJvYearGrid.DoShowHint(var HintStr: THintString; var CanShow: Boolean; var HintInfo: THintInfo); var ACol, ARow, X, Y: Integer; S, DS: string; begin if HintInfo.HintControl = Self then begin X := HintInfo.CursorPos.X; Y := HintInfo.CursorPos.Y; MouseToCell(X, Y, ACol{%H-}, ARow{%H-}); if (ACol < 0) or (ARow < 0) then Exit; DS := FYearData[ACol, ARow].DisplayText; if IsCurrentYear and (ARow = FCurrentMonth) and (DS = IntToStr(FCurrentDay)) then S := RsToday; CanShow := False; if (ACol >= 0) and (ARow >= 0) then begin S := S + FYearData[ACol, ARow].InfoText; if S <> '' then begin HintInfo.CursorRect := CellRect(ACol, ARow); HintStr := S; CanShow := True; end; end; end; end; procedure TJvYearGrid.MakeHTML(AList: TStringList; Border, Filter: Boolean); var ACol, ARow: Integer; DS, Tbs, Infs: string; Month, Day: Word; ADate: TDate; CanAdd: Boolean; fontName: String; begin if SameText(HTMLFontName, 'default') then fontName := GetFontData(Font.Handle).Name else fontName := HTMLFontName; AList.Clear; if Border then Tbs := '1' else Tbs := '0'; AList.Append('
' + DS + ' | '); Infs := FYearData[ACol, ARow].InfoText; Infs := StringReplace(Infs, LineEnding, '' + Infs + ' | '); AList.Append('