diff --git a/G940LEDControl/Forms/ButtonSelectFrm.dfm b/G940LEDControl/Forms/ButtonSelectFrm.dfm index 461ceda..9ea0bce 100644 --- a/G940LEDControl/Forms/ButtonSelectFrm.dfm +++ b/G940LEDControl/Forms/ButtonSelectFrm.dfm @@ -67,7 +67,6 @@ object ButtonSelectForm: TButtonSelectForm Default = True ModalResult = 1 TabOrder = 1 - ExplicitTop = 94 end object btnCancel: TButton Left = 401 @@ -79,7 +78,6 @@ object ButtonSelectForm: TButtonSelectForm Caption = 'Cancel' ModalResult = 2 TabOrder = 2 - ExplicitTop = 94 end object edtButton: TEdit Left = 80 diff --git a/G940LEDControl/Forms/ButtonSelectFrm.pas b/G940LEDControl/Forms/ButtonSelectFrm.pas index 575a45c..deeeb88 100644 --- a/G940LEDControl/Forms/ButtonSelectFrm.pas +++ b/G940LEDControl/Forms/ButtonSelectFrm.pas @@ -116,7 +116,7 @@ begin info.InstanceGUID := lpddi.guidInstance; info.ProductGUID := lpddi.guidProduct; - items.AddObject(String(lpddi.tszProductName), info); + items.AddObject(string(lpddi.tszProductName), info); Result := True; end; diff --git a/G940LEDControl/Forms/MainFrm.dfm b/G940LEDControl/Forms/MainFrm.dfm index f63ad32..85423db 100644 --- a/G940LEDControl/Forms/MainFrm.dfm +++ b/G940LEDControl/Forms/MainFrm.dfm @@ -275,10 +275,6 @@ object MainForm: TMainForm Caption = 'Extra' ImageIndex = 1 TabVisible = False - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object GroupBox1: TGroupBox AlignWithMargins = True Left = 6 diff --git a/G940LEDControl/G940LEDControl.dpr b/G940LEDControl/G940LEDControl.dpr index 0510214..6cc4657 100644 --- a/G940LEDControl/G940LEDControl.dpr +++ b/G940LEDControl/G940LEDControl.dpr @@ -10,7 +10,15 @@ uses G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas', LEDFunctionMap in 'Units\LEDFunctionMap.pas', LEDStateConsumer in 'Units\LEDStateConsumer.pas', - LEDStateProvider in 'Units\LEDStateProvider.pas'; + LEDStateProvider in 'Units\LEDStateProvider.pas', + LEDStateIntf in 'Units\LEDStateIntf.pas', + LEDState in 'Units\LEDState.pas', + LEDFunctionIntf in 'Units\LEDFunctionIntf.pas', + ObserverIntf in 'Units\ObserverIntf.pas', + LEDFunction in 'Units\LEDFunction.pas', + StaticLEDFunction in 'Units\StaticLEDFunction.pas', + ConfigConversion in 'Units\ConfigConversion.pas', + LEDFunctionRegistry in 'Units\LEDFunctionRegistry.pas'; {$R *.res} diff --git a/G940LEDControl/G940LEDControl.dproj b/G940LEDControl/G940LEDControl.dproj index 1e505f8..c4c26ff 100644 --- a/G940LEDControl/G940LEDControl.dproj +++ b/G940LEDControl/G940LEDControl.dproj @@ -173,6 +173,14 @@ + + + + + + + + Cfg_2 Base diff --git a/G940LEDControl/Units/ConfigConversion.pas b/G940LEDControl/Units/ConfigConversion.pas new file mode 100644 index 0000000..dd97bef --- /dev/null +++ b/G940LEDControl/Units/ConfigConversion.pas @@ -0,0 +1,57 @@ +unit ConfigConversion; + +interface + + { Version 0.x: registry -> 1.x: XML } + procedure Convert0To1; + + +implementation + +procedure Convert0To1; +begin +// FUNCTION_NONE = 0; +// FUNCTION_OFF = 1; +// FUNCTION_RED = 2; +// FUNCTION_AMBER = 3; +// FUNCTION_GREEN = 4; + +{ +FUNCTION_PROVIDER_OFFSET = 4 + + FUNCTION_FSX_GEAR = FUNCTION_PROVIDER_OFFSET + 1; + FUNCTION_FSX_LANDINGLIGHTS = FUNCTION_PROVIDER_OFFSET + 2; + FUNCTION_FSX_INSTRUMENTLIGHTS = FUNCTION_PROVIDER_OFFSET + 3; + FUNCTION_FSX_PARKINGBRAKE = FUNCTION_PROVIDER_OFFSET + 4; + FUNCTION_FSX_ENGINE = FUNCTION_PROVIDER_OFFSET + 5; + + FUNCTION_FSX_EXITDOOR = FUNCTION_PROVIDER_OFFSET + 6; + FUNCTION_FSX_STROBELIGHTS = FUNCTION_PROVIDER_OFFSET + 7; + FUNCTION_FSX_NAVLIGHTS = FUNCTION_PROVIDER_OFFSET + 8; + FUNCTION_FSX_BEACONLIGHTS = FUNCTION_PROVIDER_OFFSET + 9; + FUNCTION_FSX_FLAPS = FUNCTION_PROVIDER_OFFSET + 10; + FUNCTION_FSX_BATTERYMASTER = FUNCTION_PROVIDER_OFFSET + 11; + FUNCTION_FSX_AVIONICSMASTER = FUNCTION_PROVIDER_OFFSET + 12; + + FUNCTION_FSX_SPOILERS = FUNCTION_PROVIDER_OFFSET + 13; + + FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH = FUNCTION_PROVIDER_OFFSET + 14; + FUNCTION_FSX_CARBHEAT = FUNCTION_PROVIDER_OFFSET + 15; + FUNCTION_FSX_AUTOPILOT = FUNCTION_PROVIDER_OFFSET + 16; + FUNCTION_FSX_FUELPUMP = FUNCTION_PROVIDER_OFFSET + 17; + + FUNCTION_FSX_TAILHOOK = FUNCTION_PROVIDER_OFFSET + 18; + + FUNCTION_FSX_AUTOPILOT_AMBER = FUNCTION_PROVIDER_OFFSET + 19; + FUNCTION_FSX_AUTOPILOT_HEADING = FUNCTION_PROVIDER_OFFSET + 20; + FUNCTION_FSX_AUTOPILOT_APPROACH = FUNCTION_PROVIDER_OFFSET + 21; + FUNCTION_FSX_AUTOPILOT_BACKCOURSE = FUNCTION_PROVIDER_OFFSET + 22; + FUNCTION_FSX_AUTOPILOT_ALTITUDE = FUNCTION_PROVIDER_OFFSET + 23; + FUNCTION_FSX_AUTOPILOT_NAV = FUNCTION_PROVIDER_OFFSET + 24; + + FUNCTION_FSX_TAXILIGHTS = FUNCTION_PROVIDER_OFFSET + 25; + FUNCTION_FSX_RECOGNITIONLIGHTS = FUNCTION_PROVIDER_OFFSET + 26; + } +end; + +end. diff --git a/G940LEDControl/Units/LEDFunction.pas b/G940LEDControl/Units/LEDFunction.pas new file mode 100644 index 0000000..47f8770 --- /dev/null +++ b/G940LEDControl/Units/LEDFunction.pas @@ -0,0 +1,181 @@ +unit LEDFunction; + +interface +uses + Classes, + + LEDFunctionIntf, + LEDStateIntf, + ObserverIntf; + + +type + TCustomLEDFunctionProvider = class(TInterfacedObject, ILEDFunctionProvider) + private + FFunctions: TInterfaceList; + protected + procedure RegisterFunction(AFunction: ILEDFunction); + protected + { ILEDFunctionProvider } + function GetUniqueName: string; virtual; abstract; + + function GetEnumerator: ILEDFunctionEnumerator; virtual; + public + constructor Create; + destructor Destroy; override; + end; + + + TCustomLEDFunction = class(TInterfacedObject, IObservable, ILEDFunction) + private + FCurrentState: ILEDState; + FObservers: TInterfaceList; + protected + procedure SetCurrentState(AState: ILEDState); virtual; + + procedure NotifyObservers; virtual; + + property Observers: TInterfaceList read FObservers; + protected + { IObservable } + procedure Attach(AObserver: IObserver); + procedure Detach(AObserver: IObserver); + + { ILEDFunction } + function GetCategoryName: string; virtual; abstract; + function GetDisplayName: string; virtual; abstract; + function GetUniqueName: string; virtual; abstract; + + function GetCurrentState: ILEDState; virtual; + public + constructor Create; + destructor Destroy; override; + end; + + + TLEDFunctionEnumerator = class(TInterfacedObject, ILEDFunctionEnumerator) + private + FList: TInterfaceList; + FIndex: Integer; + protected + { ILEDFunctionEnumerator } + function GetCurrent: ILEDFunction; virtual; + function MoveNext: Boolean; virtual; + public + constructor Create(AList: TInterfaceList); + end; + + +implementation +uses + SysUtils; + + +{ TCustomLEDFunction } +constructor TCustomLEDFunction.Create; +begin + inherited Create; + + FObservers := TInterfaceList.Create; +end; + + +destructor TCustomLEDFunction.Destroy; +begin + FreeAndNil(FObservers); + + inherited Destroy; +end; + + +procedure TCustomLEDFunction.Attach(AObserver: IObserver); +begin + +end; + + +procedure TCustomLEDFunction.Detach(AObserver: IObserver); +begin + +end; + + +function TCustomLEDFunction.GetCurrentState: ILEDState; +begin + +end; + + +procedure TCustomLEDFunction.SetCurrentState(AState: ILEDState); +begin + FCurrentState := AState; + NotifyObservers; +end; + + +procedure TCustomLEDFunction.NotifyObservers; +var + observer: IInterface; + +begin + for observer in Observers do + (observer as IObserver).Update(Self); +end; + + +{ TCustomLEDFunctionProvider } +constructor TCustomLEDFunctionProvider.Create; +begin + inherited Create; + + FFunctions := TInterfaceList.Create; +end; + + +destructor TCustomLEDFunctionProvider.Destroy; +begin + FreeAndNil(FFunctions); + + inherited; +end; + + +procedure TCustomLEDFunctionProvider.RegisterFunction(AFunction: ILEDFunction); +begin + { Make sure to explicitly request the ILEDFunction interface; I've experienced + incomparable pointers otherwise if we ever need to write an UnregisterFunction. + My best, but unverified, guess is that it works kinda like a VMT. } + FFunctions.Add(AFunction as ILEDFunction); +end; + + +function TCustomLEDFunctionProvider.GetEnumerator: ILEDFunctionEnumerator; +begin + Result := TLEDFunctionEnumerator.Create(FFunctions); +end; + + +{ TLEDFunctionEnumerator } +constructor TLEDFunctionEnumerator.Create(AList: TInterfaceList); +begin + inherited Create; + + FList := AList; + FIndex := -1; +end; + + +function TLEDFunctionEnumerator.GetCurrent: ILEDFunction; +begin + Result := (FList[FIndex] as ILEDFunction); +end; + + +function TLEDFunctionEnumerator.MoveNext: Boolean; +begin + Result := (FIndex < Pred(FList.Count)); + if Result then + Inc(FIndex); +end; + +end. diff --git a/G940LEDControl/Units/LEDFunctionIntf.pas b/G940LEDControl/Units/LEDFunctionIntf.pas new file mode 100644 index 0000000..1c56fec --- /dev/null +++ b/G940LEDControl/Units/LEDFunctionIntf.pas @@ -0,0 +1,43 @@ +unit LEDFunctionIntf; + +interface +uses + LEDStateIntf, + ObserverIntf; + + +type + ILEDFunction = interface; + ILEDFunctionEnumerator = interface; + + + ILEDFunctionProvider = interface + ['{B38F6F90-DC96-42CE-B8F0-21F0DD8AA537}'] + function GetUniqueName: string; + + function GetEnumerator: ILEDFunctionEnumerator; + end; + + + ILEDFunction = interface(IObservable) + ['{7087067A-1016-4A7D-ACB1-BA1F388DAD6C}'] + function GetCategoryName: string; + function GetDisplayName: string; + function GetUniqueName: string; + + function GetCurrentState: ILEDState; + end; + + + ILEDFunctionEnumerator = interface + ['{A03E4E54-19CB-4C08-AD5F-20265817086D}'] + function GetCurrent: ILEDFunction; + function MoveNext: Boolean; + + property Current: ILEDFunction read GetCurrent; + end; + + +implementation + +end. diff --git a/G940LEDControl/Units/LEDFunctionRegistry.pas b/G940LEDControl/Units/LEDFunctionRegistry.pas new file mode 100644 index 0000000..1cd56bf --- /dev/null +++ b/G940LEDControl/Units/LEDFunctionRegistry.pas @@ -0,0 +1,216 @@ +unit LEDFunctionRegistry; + +interface +uses + Classes, + + LEDFunctionIntf; + + +type + TLEDFunctionProviderList = class; + + TLEDFunctionRegistry = class(TObject) + private + FProviders: TLEDFunctionProviderList; + protected + class function Instance: TLEDFunctionRegistry; + + procedure DoRegister(AProvider: ILEDFunctionProvider); + procedure DoUnregister(AProvider: ILEDFunctionProvider); + function DoFind(const AUniqueName: string): ILEDFunctionProvider; + + function GetProviders: TLEDFunctionProviderList; + public + constructor Create; + destructor Destroy; override; + + class procedure Register(AProvider: ILEDFunctionProvider); + class procedure Unregister(AProvider: ILEDFunctionProvider); + + class function Find(const AUniqueName: string): ILEDFunctionProvider; + + class function Providers: TLEDFunctionProviderList; + end; + + + TLEDFunctionProviderListEnumerator = class; + + TLEDFunctionProviderList = class(TObject) + private + FList: TInterfaceList; + protected + procedure Add(AProvider: ILEDFunctionProvider); + procedure Remove(AProvider: ILEDFunctionProvider); + public + constructor Create; + destructor Destroy; override; + + function Find(const AUniqueName: string): ILEDFunctionProvider; + + function GetEnumerator: TLEDFunctionProviderListEnumerator; + end; + + + TLEDFunctionProviderListEnumerator = class(TInterfaceListEnumerator) + public + function GetCurrent: ILEDFunctionProvider; inline; + property Current: ILEDFunctionProvider read GetCurrent; + end; + + +implementation +uses + SysUtils; + + +var + RegistryInstance: TLEDFunctionRegistry; + + +{ TLEDFunctionRegistry } +class procedure TLEDFunctionRegistry.Register(AProvider: ILEDFunctionProvider); +begin + Instance.DoRegister(AProvider); +end; + + +class procedure TLEDFunctionRegistry.Unregister(AProvider: ILEDFunctionProvider); +begin + Instance.DoUnregister(AProvider); +end; + + +class function TLEDFunctionRegistry.Find(const AUniqueName: string): ILEDFunctionProvider; +begin + Result := Instance.DoFind(AUniqueName); +end; + + +class function TLEDFunctionRegistry.Providers: TLEDFunctionProviderList; +begin + Result := Instance.GetProviders; +end; + + +class function TLEDFunctionRegistry.Instance: TLEDFunctionRegistry; +begin + if not Assigned(RegistryInstance) then + RegistryInstance := TLEDFunctionRegistry.Create; + + Result := RegistryInstance; +end; + + +constructor TLEDFunctionRegistry.Create; +begin + inherited Create; + + FProviders := TLEDFunctionProviderList.Create; +end; + + +destructor TLEDFunctionRegistry.Destroy; +begin + FreeAndNil(FProviders); + + inherited; +end; + + +procedure TLEDFunctionRegistry.DoRegister(AProvider: ILEDFunctionProvider); +begin + FProviders.Add(AProvider); +end; + + +procedure TLEDFunctionRegistry.DoUnregister(AProvider: ILEDFunctionProvider); +begin + FProviders.Remove(AProvider); +end; + + +function TLEDFunctionRegistry.DoFind(const AUniqueName: string): ILEDFunctionProvider; +begin + Result := FProviders.Find(AUniqueName); +end; + + +function TLEDFunctionRegistry.GetProviders: TLEDFunctionProviderList; +begin + Result := FProviders; +end; + + +{ TLEDFunctionProviderList } +constructor TLEDFunctionProviderList.Create; +begin + inherited Create; + + FList := TInterfaceList.Create; +end; + + +destructor TLEDFunctionProviderList.Destroy; +begin + FreeAndNil(FList); + + inherited; +end; + + +function TLEDFunctionProviderList.Find(const AUniqueName: string): ILEDFunctionProvider; +var + provider: ILEDFunctionProvider; + +begin + Result := nil; + + for provider in Self do + if provider.GetUniqueName = AUniqueName then + begin + Result := provider; + break; + end; +end; + +procedure TLEDFunctionProviderList.Add(AProvider: ILEDFunctionProvider); +var + stableReference: ILEDFunctionProvider; + +begin + stableReference := (AProvider as ILEDFunctionProvider); + if FList.IndexOf(stableReference) = -1 then + FList.Add(stableReference); +end; + + +procedure TLEDFunctionProviderList.Remove(AProvider: ILEDFunctionProvider); +var + index: Integer; + +begin + index := FList.IndexOf(AProvider as ILEDFunctionProvider); + if index > -1 then + FList.Delete(index); +end; + + +function TLEDFunctionProviderList.GetEnumerator: TLEDFunctionProviderListEnumerator; +begin + Result := TLEDFunctionProviderListEnumerator.Create(FList); +end; + + +{ TLEDFunctionProviderListEnumerator } +function TLEDFunctionProviderListEnumerator.GetCurrent: ILEDFunctionProvider; +begin + Result := ((inherited GetCurrent) as ILEDFunctionProvider); +end; + + +initialization +finalization + FreeAndNil(RegistryInstance); + +end. diff --git a/G940LEDControl/Units/LEDState.pas b/G940LEDControl/Units/LEDState.pas new file mode 100644 index 0000000..2241b4f --- /dev/null +++ b/G940LEDControl/Units/LEDState.pas @@ -0,0 +1,52 @@ +unit LEDState; + +interface +uses + SysUtils, + + LEDStateIntf; + + +type + TCustomLEDState = class(TInterfacedObject, ILEDState) + protected + { ILEDState } + procedure Tick; virtual; + function GetColor: TLEDColor; virtual; abstract; + end; + + + TStaticLEDState = class(TCustomLEDState) + private + FColor: TLEDColor; + protected + function GetColor: TLEDColor; override; + public + constructor Create(AColor: TLEDColor); + end; + + +implementation + + +{ TCustomLEDState } +procedure TCustomLEDState.Tick; +begin +end; + + +{ TStaticLEDState } +constructor TStaticLEDState.Create(AColor: TLEDColor); +begin + inherited Create; + + FColor := AColor; +end; + + +function TStaticLEDState.GetColor: TLEDColor; +begin + Result := FColor; +end; + +end. diff --git a/G940LEDControl/Units/LEDStateIntf.pas b/G940LEDControl/Units/LEDStateIntf.pas new file mode 100644 index 0000000..8e56f5c --- /dev/null +++ b/G940LEDControl/Units/LEDStateIntf.pas @@ -0,0 +1,17 @@ +unit LEDStateIntf; + +interface +type + TLEDColor = (lcOff, lcGreen, lcAmber, lcRed); + + ILEDState = interface + ['{B40DF462-B660-4002-A6B9-DD30AC69E8DB}'] + procedure Tick; + + function GetColor: TLEDColor; + end; + + +implementation + +end. diff --git a/G940LEDControl/Units/ObserverIntf.pas b/G940LEDControl/Units/ObserverIntf.pas new file mode 100644 index 0000000..c5b0123 --- /dev/null +++ b/G940LEDControl/Units/ObserverIntf.pas @@ -0,0 +1,20 @@ +unit ObserverIntf; + +interface +type + IObserver = interface + ['{B78415C9-9F64-4AF1-8983-BACE2B7225EF}'] + procedure Update(Sender: IInterface); + end; + + + IObservable = interface + ['{BC004BDA-14E4-4923-BE6D-98A0746852F1}'] + procedure Attach(AObserver: IObserver); + procedure Detach(AObserver: IObserver); + end; + + +implementation + +end. diff --git a/G940LEDControl/Units/StaticLEDFunction.pas b/G940LEDControl/Units/StaticLEDFunction.pas new file mode 100644 index 0000000..5bd2c39 --- /dev/null +++ b/G940LEDControl/Units/StaticLEDFunction.pas @@ -0,0 +1,107 @@ +unit StaticLEDFunction; + +interface +uses + LEDFunction, + LEDStateIntf; + + +type + TStaticLEDFunctionProvider = class(TCustomLEDFunctionProvider) + protected + function GetUniqueName: string; override; + public + constructor Create; + end; + + + TStaticLEDFunction = class(TCustomLEDFunction) + private + FColor: TLEDColor; + protected + function GetCategoryName: string; override; + function GetDisplayName: string; override; + function GetUniqueName: string; override; + public + constructor Create(AColor: TLEDColor); + end; + + +implementation +uses + LEDFunctionRegistry; + + +const + CategoryStatic = 'Static'; + + ProviderUniqueName = 'static'; + + FunctionUniqueName: array[TLEDColor] of string = + ( + 'off', + 'green', + 'amber', + 'red' + ); + + FunctionDisplayName: array[TLEDColor] of string = + ( + 'Off', + 'Green', + 'Amber', + 'Red' + ); + + + +{ TStaticLEDFunctionProvider } +constructor TStaticLEDFunctionProvider.Create; +var + color: TLEDColor; + +begin + inherited Create; + + for color := Low(TLEDColor) to High(TLEDColor) do + RegisterFunction(TStaticLEDFunction.Create(color)); +end; + + +function TStaticLEDFunctionProvider.GetUniqueName: string; +begin + Result := ProviderUniqueName; +end; + + +{ TStaticLEDFunction } +constructor TStaticLEDFunction.Create(AColor: TLEDColor); +begin + inherited Create; + + FColor := AColor; +end; + + +function TStaticLEDFunction.GetCategoryName: string; +begin + Result := CategoryStatic; +end; + + +function TStaticLEDFunction.GetDisplayName: string; +begin + Result := FunctionDisplayName[FColor]; +end; + + +function TStaticLEDFunction.GetUniqueName: string; +begin + Result := FunctionUniqueName[FColor]; +end; + + +initialization + TLEDFunctionRegistry.Register(TStaticLEDFunctionProvider.Create); + +end.