Componentes.Terceros.DevExp.../official/x.44/ExpressScheduler 2/Sources/cxSchedulerDialogs.pas

482 lines
16 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressScheduler }
{ }
{ Copyright (c) 2003-2009 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 cxSchedulerDialogs;
{$I cxVer.inc}
interface
uses
Classes, Controls, Forms, cxLookAndFeels, cxSchedulerStorage, cxDateUtils,
StdCtrls, cxSchedulerEventEditor, cxSchedulerRecurrenceEditor,
cxSchedulerCustomControls, cxSchedulerRecurrenceSelectionDialog,
cxSchedulerReminderWindow, cxDropDownEdit;
type
{ TcxDialogMetricsInfo }
TcxDialogMetricsInfo = class
private
FClientHeight: Integer;
FClientWidth: Integer;
FDialogClass: TClass;
FLeft: Integer;
FTop: Integer;
FMaximized: Boolean;
protected
procedure Restore(AForm: TForm);
procedure Store(AForm: TForm);
public
constructor Create(AForm: TForm);
property ClientHeight: Integer read FClientHeight;
property ClientWidth: Integer read FClientWidth;
property DialogClass: TClass read FDialogClass;
property Left: Integer read FLeft;
property Maximized: Boolean read FMaximized;
property Top: Integer read FTop;
end;
{ TcxDialogsMetricsStore }
TcxDialogsMetricsStore = class
private
FMetrics: TList;
protected
function CreateMetrics(AForm: TForm): TcxDialogMetricsInfo;
function FindMetrics(AForm: TForm): Integer;
property Metrics: TList read FMetrics;
public
constructor Create; virtual;
destructor Destroy; override;
procedure InitDialog(AForm: TForm);
procedure StoreMetrics(AForm: TForm);
end;
// component dialogs metrics storage
function cxDialogsMetricsStore: TcxDialogsMetricsStore;
// editors for scheduler events
function cxShowEventEditorEx(AEventInfo: TcxSchedulerEventEditInfo;
var AModified: Boolean): Boolean;
function cxShowEventEditor(AEvent: TcxSchedulerControlEvent;
ALookAndFeel: TcxLookAndFeel; ARecurrence: Boolean; var AModified: Boolean;
AReadOnly: Boolean = False; AllowDelete: Boolean = True;
ARecurrenceButton: Boolean = True;
AOnDeleteFunc: TcxOnDeleteEventFunc = nil;
AForcePatternEditing: Boolean = False;
ABiasTime: TDateTime = 0; AShowResources: Boolean = False): Boolean;
function cxShowRecurrenceEditor(AEvent: TcxSchedulerControlEvent;
ALookAndFeel: TcxLookAndFeel; out AModified: Boolean;
AReadOnly: Boolean = False; AConfirmLossOfExceptions: Boolean = True;
AIsInternalActivation: Boolean = False): Boolean;
procedure cxShowResourcesLayoutEditor(AStorage: TcxCustomSchedulerStorage;
ALookAndFeel: TcxLookAndFeel);
function cxShowRecurrenceSelectionDialog(AEvent: TcxSchedulerEvent;
AMode: TcxRecurrenceSelectionMode; ALookAndFeel: TcxLookAndFeel;
out AOccurrence: Boolean): Boolean;
function cxShowGoToDateDialog(AScheduler: TcxCustomScheduler;
ALookAndFeel: TcxLookAndFeel; var ADate: TDateTime;
out AViewMode: TcxSchedulerViewMode): Boolean;
function cxGetLabelGrowDelta(ALabel: TLabel): Integer;
procedure cxComboBoxPopulateWithTimeIntervals(ACombo: TcxComboBox);
procedure cxComboBoxSetNearestTimeInterval(ACombo: TcxComboBox; AMinutes: Integer);
procedure cxComboBoxCaretToEnd(AComboBox: TcxComboBox);
const
cxEventEditorClass: TcxSchedulerEventEditorClass = TcxSchedulerEventEditor;
cxRecurrenceEventEditorClass: TcxSchedulerRecurrenceEventEditorClass = TcxSchedulerRecurrenceEventEditor;
cxReminderFormClass: TcxSchedulerReminderFormClass = TcxSchedulerReminderForm;
UseSchedulerColorInDialogs: Boolean = True;
implementation
uses
Windows, Messages, SysUtils, cxClasses, cxGraphics, cxControls, cxEdit,
cxButtons, cxRadioGroup, cxContainer, cxSchedulerResourcesLayoutEditor,
cxSchedulerGoToDateDialog, cxSchedulerUtils;
type
TcxControlAccess = class(TcxControl);
TcxContainerAccess = class(TcxContainer);
var
FDialogs: TList;
FDialogsMetrics: TcxDialogsMetricsStore;
function cxDialogsMetricsStore: TcxDialogsMetricsStore;
begin
Result := FDialogsMetrics;
end;
function cxGetLabelGrowDelta(ALabel: TLabel): Integer;
var
R: TRect;
begin
with TcxScreenCanvas.Create do
try
R := cxEmptyRect;
R.Right := ALabel.Width;
Font.Assign(ALabel.Font);
TextExtent(ALabel.Caption, R, cxWordBreak);
finally
Free;
end;
Result := R.Bottom - ALabel.Height;
if Result < 0 then
Result := 0
else
ALabel.Height := ALabel.Height + Result;
end;
procedure cxComboBoxPopulateWithTimeIntervals(ACombo: TcxComboBox);
var
I: Integer;
begin
with ACombo.Properties.Items do
begin
BeginUpdate;
try
for I := Low(ComboBoxTimeIntervals) to High(ComboBoxTimeIntervals) do
AddObject(cxGetResourceString(ComboBoxTimeIntervals[I].P), TObject(ComboBoxTimeIntervals[I].M));
finally
EndUpdate;
end;
end;
end;
procedure cxComboBoxSetNearestTimeInterval(ACombo: TcxComboBox; AMinutes: Integer);
function GetMinutes(I: Integer): Integer;
begin
Result := Integer(ACombo.Properties.Items.Objects[I]);
end;
var
I, ACount, ADeltaPrev, ADelta: Integer;
begin
ADeltaPrev := Abs(GetMinutes(0) - AMinutes);
ACount := ACombo.Properties.Items.Count;
for I := 1 to ACount - 1 do
begin
ADelta := Abs(GetMinutes(I) - AMinutes);
if ADelta > ADeltaPrev then
begin
ACombo.SelectedItem := I - 1;
Exit;
end;
ADeltaPrev := ADelta;
end;
ACombo.SelectedItem := ACount - 1;
end;
procedure cxComboBoxCaretToEnd(AComboBox: TcxComboBox);
begin
PostMessage(AComboBox.InnerControl.Handle, EM_SETSEL, 4096, 4096);
end;
{ TcxDialogMetricsInfo }
constructor TcxDialogMetricsInfo.Create(AForm: TForm);
begin
Store(AForm);
end;
procedure TcxDialogMetricsInfo.Restore(AForm: TForm);
begin
if FMaximized then
begin
ShowWindow(AForm.Handle, WS_MAXIMIZE);
AForm.WindowState := wsMaximized;
end
else
begin
AForm.Left := FLeft;
AForm.Top := FTop;
if AForm.BorderStyle in [bsSizeable, bsSizeToolWin] then
begin
AForm.ClientHeight := FClientHeight;
AForm.ClientWidth := FClientWidth;
end;
end;
end;
procedure TcxDialogMetricsInfo.Store(AForm: TForm);
begin
FDialogClass := AForm.ClassType;
FLeft := AForm.Left;
FTop := AForm.Top;
FClientHeight := AForm.ClientHeight;
FClientWidth := AForm.ClientWidth;
FMaximized := AForm.WindowState = wsMaximized;
end;
{ TcxDialogsMetricsStore }
constructor TcxDialogsMetricsStore.Create;
begin
FMetrics := TList.Create;
end;
destructor TcxDialogsMetricsStore.Destroy;
var
I: Integer;
begin
for I := 0 to FMetrics.Count - 1 do
TObject(FMetrics[I]).Free;
FMetrics.Free;
inherited Destroy;
end;
procedure TcxDialogsMetricsStore.InitDialog(AForm: TForm);
begin
if FindMetrics(AForm) >= 0 then
begin
AForm.Position := poDesigned;
TcxDialogMetricsInfo(FMetrics[FindMetrics(AForm)]).Restore(AForm)
end
else
begin
AForm.Position := poMainFormCenter;
FMetrics.Add(CreateMetrics(AForm));
end;
end;
procedure TcxDialogsMetricsStore.StoreMetrics(AForm: TForm);
begin
if FindMetrics(AForm) >= 0 then
TcxDialogMetricsInfo(FMetrics[FindMetrics(AForm)]).Store(AForm)
end;
function TcxDialogsMetricsStore.CreateMetrics(
AForm: TForm): TcxDialogMetricsInfo;
begin
Result := TcxDialogMetricsInfo.Create(AForm);
end;
function TcxDialogsMetricsStore.FindMetrics(
AForm: TForm): Integer;
begin
Result := FMetrics.Count - 1;
while Result >= 0 do
begin
if TcxDialogMetricsInfo(FMetrics[Result]).DialogClass = AForm.ClassType then
Break;
Dec(Result);
end;
end;
function IsStorageValid(AStorage: TcxCustomSchedulerStorage): Boolean;
begin
Result := (AStorage <> nil) and AStorage.IsActive;
end;
function IsEventValid(AEvent: TcxSchedulerControlEvent): Boolean;
begin
Result := (AEvent <> nil) and IsStorageValid(AEvent.Storage);
end;
// showing editor functions
function cxShowEventEditorEx(AEventInfo: TcxSchedulerEventEditInfo;
var AModified: Boolean): Boolean;
var
AEditor: TcxSchedulerCustomEventEditor;
AEvent: TcxSchedulerControlEvent;
AOccurrence: Boolean;
APatternEvent: TcxSchedulerControlEvent;
begin
Result := False;
AEvent := AEventInfo.Event;
if not IsEventValid(AEvent) or (cxEventEditorClass = nil) then Exit;
if AEvent.IsRecurring and not AEventInfo.ForcePatternEditing then
begin
if not cxShowRecurrenceSelectionDialog(AEvent, rsmOpen,
AEventInfo.LookAndFeel, AOccurrence) then Exit;
AEventInfo.ForcePatternEditing := not AOccurrence;
end;
if AEventInfo.Recurrence and (AEvent.Source = nil) then
begin
AEvent.EventType := etPattern;
AEventInfo.ForcePatternEditing := True;
end;
if AEventInfo.ForcePatternEditing and (AEvent.Pattern <> nil) then
begin
APatternEvent := TcxSchedulerControlEvent.Create(AEvent.Pattern);
AEvent := APatternEvent;
end
else
APatternEvent := nil;
if AEvent.RecordIndex <> -1 then AEvent.BeginEditing;
AEditor := cxEventEditorClass.CreateEx(AEvent);
try
SetControlLookAndFeel(AEditor, AEventInfo.LookAndFeel);
AEditor.ShowResources := AEventInfo.ShowResources;
AEditor.ForceSeries := AEventInfo.ForcePatternEditing;
AEditor.RecurrenceActivate := AEventInfo.Recurrence;
AEditor.Intersection := AEventInfo.Intersection;
AEditor.AllowDelete := AEventInfo.AllowDelete and (AEvent.Source <> nil);
AEditor.AllowHiddenEvents := AEventInfo.AllowHiddenEvents;
AEditor.AllowRecurrence := AEventInfo.RecurrenceButton and Assigned(cxRecurrenceEventEditorClass) and
AEvent.Storage.IsRecurrenceAvailable;
AEditor.ReadOnly := AEventInfo.ReadOnly;
AEditor.OnDeleteFunc := AEventInfo.OnDeleteFunc;
AEditor.BiasTime := AEventInfo.BiasTime;
Result := AEditor.ShowModal = mrOk;
AModified := AEditor.Modified;
finally
AEditor.Release;
APatternEvent.Free;
end;
end;
function cxShowEventEditor(AEvent: TcxSchedulerControlEvent;
ALookAndFeel: TcxLookAndFeel; ARecurrence: Boolean; var AModified: Boolean;
AReadOnly: Boolean = False; AllowDelete: Boolean = True;
ARecurrenceButton: Boolean = True; AOnDeleteFunc: TcxOnDeleteEventFunc = nil;
AForcePatternEditing: Boolean = False; ABiasTime: TDateTime = 0; AShowResources: Boolean = False): Boolean;
var
AEventEditInfo: TcxSchedulerEventEditInfo;
begin
AEventEditInfo := TcxSchedulerEventEditInfo.Create;
try
AEventEditInfo.Event := AEvent;
AEventEditInfo.LookAndFeel := ALookAndFeel;
AEventEditInfo.Recurrence := ARecurrence;
AEventEditInfo.ReadOnly := AReadOnly;
AEventEditInfo.AllowDelete := AllowDelete;
AEventEditInfo.RecurrenceButton := ARecurrenceButton;
AEventEditInfo.OnDeleteFunc := AOnDeleteFunc;
AEventEditInfo.ForcePatternEditing := AForcePatternEditing;
AEventEditInfo.BiasTime := ABiasTime;
AEventEditInfo.ShowResources := AShowResources;
Result := cxShowEventEditorEx(AEventEditInfo, AModified);
finally
AEventEditInfo.Free;
end;
end;
function cxShowRecurrenceEditor(AEvent: TcxSchedulerControlEvent;
ALookAndFeel: TcxLookAndFeel; out AModified: Boolean;
AReadOnly: Boolean = False; AConfirmLossOfExceptions: Boolean = True;
AIsInternalActivation: Boolean = False): Boolean;
var
AEditor: TcxSchedulerCustomRecurrenceEventEditor;
begin
Result := False;
if not IsEventValid(AEvent) or (cxRecurrenceEventEditorClass = nil) then Exit;
AEditor := cxRecurrenceEventEditorClass.CreateEx(AEvent);
try
SetControlLookAndFeel(AEditor, ALookAndFeel);
AEditor.IsInternalActivation := AIsInternalActivation;
AEditor.ReadOnly := AReadOnly;
AEditor.NeedCheckLossOfExceptions := AConfirmLossOfExceptions;
Result := AEditor.ShowModal = mrOk;
AModified := AEditor.Modified;
finally
AEditor.Release;
end;
end;
procedure cxShowResourcesLayoutEditor(AStorage: TcxCustomSchedulerStorage;
ALookAndFeel: TcxLookAndFeel);
var
AEditor: TfmResourcesLayoutEditor;
begin
if not IsStorageValid(AStorage) or (AStorage.ResourceCount = 0) then Exit;
AEditor := TfmResourcesLayoutEditor.Create(nil);
try
SetControlLookAndFeel(AEditor, ALookAndFeel);
AEditor.Storage := AStorage;
AEditor.ShowModal;
finally
AEditor.Release;
end;
end;
function cxShowRecurrenceSelectionDialog(AEvent: TcxSchedulerEvent;
AMode: TcxRecurrenceSelectionMode; ALookAndFeel: TcxLookAndFeel;
out AOccurrence: Boolean): Boolean;
var
ADialog: TfmRecurrenceSelectionForm;
begin
Result := False;
if AEvent = nil then Exit;
ADialog := TfmRecurrenceSelectionForm.CreateEx(AEvent, AMode);
try
SetControlLookAndFeel(ADialog, ALookAndFeel);
Result := ADialog.ShowModal = mrOk;
if Result then
AOccurrence := ADialog.rbOccurrence.Checked;
finally
ADialog.Free;
end;
end;
function cxShowGoToDateDialog(AScheduler: TcxCustomScheduler;
ALookAndFeel: TcxLookAndFeel; var ADate: TDateTime;
out AViewMode: TcxSchedulerViewMode): Boolean;
var
ADialog: TfmGoToDateForm;
begin
ADialog := TfmGoToDateForm.CreateEx(AScheduler, ADate);
try
SetControlLookAndFeel(ADialog, ALookAndFeel);
Result := ADialog.ShowModal = mrOk;
AViewMode := ADialog.GetViewMode;
if Result then
begin
ADate := ADialog.deDate.Date;
if ADate = NullDate then
ADate := 0;
end;
finally
ADialog.Free;
end;
end;
initialization
FDialogs := TList.Create;
FDialogsMetrics := TcxDialogsMetricsStore.Create;
finalization
FreeAndNil(FDialogs);
FreeAndNil(FDialogsMetrics);
end.