diff --git a/G940LEDControl/Forms/ButtonFunctionFrm.dfm b/G940LEDControl/Forms/ButtonFunctionFrm.dfm
index a58a285..a9f3300 100644
--- a/G940LEDControl/Forms/ButtonFunctionFrm.dfm
+++ b/G940LEDControl/Forms/ButtonFunctionFrm.dfm
@@ -40,7 +40,7 @@ object ButtonFunctionForm: TButtonFunctionForm
Margins.Bottom = 0
Align = alBottom
BevelOuter = bvNone
- TabOrder = 2
+ TabOrder = 3
DesignSize = (
692
43)
@@ -93,7 +93,8 @@ object ButtonFunctionForm: TButtonFunctionForm
Header.Font.Name = 'Tahoma'
Header.Font.Style = []
Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
- TabOrder = 0
+ IncrementalSearch = isAll
+ TabOrder = 1
TreeOptions.AutoOptions = [toAutoDropExpand, toAutoScrollOnExpand, toAutoSort, toAutoTristateTracking, toAutoDeleteMovedNodes]
TreeOptions.MiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toInitOnSave, toWheelPanning, toEditOnClick]
TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages]
@@ -101,6 +102,7 @@ object ButtonFunctionForm: TButtonFunctionForm
OnFocusChanged = vstFunctionsFocusChanged
OnGetText = vstFunctionsGetText
OnPaintText = vstFunctionsPaintText
+ OnIncrementalSearch = vstFunctionsIncrementalSearch
Columns = <
item
Position = 0
@@ -120,7 +122,7 @@ object ButtonFunctionForm: TButtonFunctionForm
Margins.Bottom = 0
Align = alClient
BevelOuter = bvNone
- TabOrder = 1
+ TabOrder = 2
object pnlName: TPanel
Left = 0
Top = 0
@@ -203,7 +205,7 @@ object ButtonFunctionForm: TButtonFunctionForm
BevelOuter = bvNone
Color = clWindow
ParentBackground = False
- TabOrder = 3
+ TabOrder = 0
DesignSize = (
692
50)
diff --git a/G940LEDControl/Forms/ButtonFunctionFrm.pas b/G940LEDControl/Forms/ButtonFunctionFrm.pas
index f442d4c..a1e81bf 100644
--- a/G940LEDControl/Forms/ButtonFunctionFrm.pas
+++ b/G940LEDControl/Forms/ButtonFunctionFrm.pas
@@ -49,6 +49,7 @@ type
procedure vstFunctionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure vstFunctionsPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
procedure vstFunctionsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
+ procedure vstFunctionsIncrementalSearch(Sender: TBaseVirtualTree; Node: PVirtualNode; const SearchText: string; var Result: Integer);
procedure btnOKClick(Sender: TObject);
private
FProfile: TProfile;
@@ -97,6 +98,7 @@ type
implementation
uses
+ System.Math,
System.SysUtils,
Winapi.Windows,
@@ -377,6 +379,9 @@ var
color: TLEDColor;
begin
+ if not Assigned(Button) then
+ FButton := Profile.Buttons[ButtonIndex];
+
Button.ProviderUID := SelectedProvider.GetUID;
Button.FunctionUID := SelectedFunction.GetUID;
@@ -438,6 +443,24 @@ begin
end;
+procedure TButtonFunctionForm.vstFunctionsIncrementalSearch(Sender: TBaseVirtualTree; Node: PVirtualNode;
+ const SearchText: string; var Result: Integer);
+var
+ nodeData: PFunctionNodeData;
+ displayName: string;
+
+begin
+ nodeData := Sender.GetNodeData(Node);
+
+ if nodeData^.NodeType = ntFunction then
+ begin
+ displayName := nodeData^.LEDFunction.GetDisplayName;
+ Result := StrLIComp(PChar(displayName), PChar(SearchText), Min(Length(displayName), Length(searchText)));
+ end else
+ Result := -1;
+end;
+
+
procedure TButtonFunctionForm.vstFunctionsPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
var
diff --git a/G940LEDControl/Forms/MainFrm.dfm b/G940LEDControl/Forms/MainFrm.dfm
index f43fd5a..8fdca19 100644
--- a/G940LEDControl/Forms/MainFrm.dfm
+++ b/G940LEDControl/Forms/MainFrm.dfm
@@ -1,11 +1,12 @@
object MainForm: TMainForm
Left = 0
Top = 0
+ ActiveControl = cmbProfiles
BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle
Caption = 'G940 LED Control'
- ClientHeight = 562
- ClientWidth = 465
+ ClientHeight = 548
+ ClientWidth = 466
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
@@ -21,25 +22,25 @@ object MainForm: TMainForm
object PageControl: TPageControl
AlignWithMargins = True
Left = 8
- Top = 80
- Width = 449
- Height = 474
+ Top = 60
+ Width = 450
+ Height = 480
Margins.Left = 8
Margins.Top = 8
Margins.Right = 8
Margins.Bottom = 8
ActivePage = tsFSX
Align = alClient
- TabOrder = 1
+ TabOrder = 0
object tsFSX: TTabSheet
Caption = 'Configuration'
DesignSize = (
- 441
- 446)
+ 442
+ 452)
object lblP1Function: TLabel
Left = 64
Top = 73
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -51,21 +52,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP1Category: TLabel
Left = 64
Top = 89
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP2Function: TLabel
Left = 64
Top = 120
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -77,21 +80,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP2Category: TLabel
Left = 64
Top = 136
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP3Function: TLabel
Left = 64
Top = 167
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -103,21 +108,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP3Category: TLabel
Left = 64
Top = 183
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP4Function: TLabel
Left = 64
Top = 214
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -129,21 +136,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP4Category: TLabel
Left = 64
Top = 230
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP5Function: TLabel
Left = 64
Top = 261
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -155,21 +164,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP5Category: TLabel
Left = 64
Top = 277
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP6Function: TLabel
Left = 64
Top = 308
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -181,21 +192,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP6Category: TLabel
Left = 64
Top = 324
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP7Function: TLabel
Left = 64
Top = 355
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -207,21 +220,23 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP7Category: TLabel
Left = 64
Top = 371
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblP8Function: TLabel
Left = 64
Top = 402
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
@@ -233,16 +248,18 @@ object MainForm: TMainForm
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
+ ExplicitWidth = 364
end
object lblP8Category: TLabel
Left = 64
Top = 418
- Width = 364
+ Width = 365
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = '[runtime: category]'
EllipsisPosition = epEndEllipsis
+ ExplicitWidth = 364
end
object lblProfile: TLabel
Left = 11
@@ -264,7 +281,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P1'
- TabOrder = 0
+ TabOrder = 3
end
object btnP2: TButton
Left = 11
@@ -272,7 +289,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P2'
- TabOrder = 1
+ TabOrder = 4
end
object btnP3: TButton
Left = 11
@@ -280,7 +297,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P3'
- TabOrder = 2
+ TabOrder = 5
end
object btnP4: TButton
Left = 11
@@ -288,7 +305,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P4'
- TabOrder = 3
+ TabOrder = 6
end
object btnP5: TButton
Left = 11
@@ -296,7 +313,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P5'
- TabOrder = 4
+ TabOrder = 7
end
object btnP6: TButton
Left = 11
@@ -304,7 +321,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P6'
- TabOrder = 5
+ TabOrder = 8
end
object btnP7: TButton
Left = 11
@@ -312,7 +329,7 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P7'
- TabOrder = 6
+ TabOrder = 9
end
object btnP8: TButton
Left = 11
@@ -320,45 +337,43 @@ object MainForm: TMainForm
Width = 41
Height = 41
Caption = 'P8'
- TabOrder = 7
+ TabOrder = 10
end
object cmbProfiles: TComboBox
Left = 64
Top = 16
- Width = 234
+ Width = 208
Height = 21
Style = csDropDownList
Anchors = [akLeft, akTop, akRight]
Sorted = True
- TabOrder = 8
+ TabOrder = 0
OnClick = cmbProfilesClick
end
object btnSaveProfile: TButton
- Left = 304
- Top = 16
- Width = 54
- Height = 21
+ Left = 279
+ Top = 15
+ Width = 72
+ Height = 23
Anchors = [akTop, akRight]
- Caption = 'New'
- TabOrder = 9
+ Caption = 'Sa&ve As...'
+ TabOrder = 1
+ OnClick = btnSaveProfileClick
end
object btnDeleteProfile: TButton
- Left = 364
- Top = 16
- Width = 64
- Height = 21
+ Left = 357
+ Top = 15
+ Width = 72
+ Height = 23
Anchors = [akTop, akRight]
- Caption = 'Delete'
- TabOrder = 10
+ Caption = '&Delete'
+ TabOrder = 2
+ OnClick = btnDeleteProfileClick
end
end
object tsAbout: TTabSheet
Caption = 'About'
ImageIndex = 1
- ExplicitLeft = 0
- ExplicitTop = 0
- ExplicitWidth = 0
- ExplicitHeight = 0
object lblVersionCaption: TLabel
Left = 16
Top = 67
@@ -462,389 +477,537 @@ object MainForm: TMainForm
end
end
end
- object pnlG940: TPanel
+ object pnlState: TPanel
AlignWithMargins = True
- Left = 8
- Top = 8
- Width = 449
- Height = 64
- Margins.Left = 8
- Margins.Top = 8
- Margins.Right = 8
- Margins.Bottom = 0
+ Left = 3
+ Top = 3
+ Width = 460
+ Height = 46
Align = alTop
BevelOuter = bvNone
- TabOrder = 0
- DesignSize = (
- 449
- 64)
- object imgStateFound: TImage
- Left = 0
- Top = 0
- Width = 64
- Height = 64
- AutoSize = True
- Picture.Data = {
- 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000400000
- 00400806000000AA6971DE0000001974455874536F6674776172650041646F62
- 6520496D616765526561647971C9653C000016424944415478DAED5B09745465
- 96BEB5A4925452492A5B5565237B422A1B842D203620A233CD32EA8C23DD6D6B
- AB38CCA0D29E565BB6695A5C41A0C1BD955D96398D0B22626B1F1515B121812C
- 908DAC55D993CA5AD9AA2A5573BFBFF26241E3B4A860E6D87FCE3BAFB6B7DCEF
- FFEEBDDFBDFF8BCCE572251251276F72FA710D276F5A1903A01D01E0C7380400
- 61FCA2ED87BE931F6884FD03801F000095D56AD5DBEDF6009BCDE6373C3CECCD
- AFB179F1A6181C1854A9FDD4D69494943F0F0E0E6A9B9B9B93F9774AFE4EEE74
- 3A8937194E2297CB9D0A85C2A1542A6D5E5E5E761F1F9FDEB0B0B07A7EEF18B3
- 00B4B6B61ADFF8D3C16D1D1D1DE90EC7B0920D53381C0EF9D0D0909C8DA5FEFE
- 7EEAEAEAC2DE71DFFDF7AD292D29FDF7828282F49E9E1E396FD4D7DF47B6211B
- F131C4C091D3E574D96D76676868A833332B7378CE7573FE7CFBEDB7DFC6C0D8
- C61C00ED6DED098FFDFEB1BF984CA6581F6F1F72F11F06661506F17D505F5F1F
- 353535512783306DEA54F1596F6F2F3163686060801828F15B6683D8982D1417
- 1F4773E7CEA5F0F070EAE7DFDC7DCF5D130D06C399310500A8FEE8238F7E78FC
- F8F15C3F3F3F61984C26137B00803DCF1A7577775375753585EB741415192900
- 81D1D860B09875B71BE09C949E9E4E1919198239CC2A8A8D8BA5DB7EB6F8E149
- 3939CF8E2900DE39F4CEFD2B57ACDC0AE361288CF71CECCFE2B39A9A1A31E3E3
- C68D1B3512332EB1447A8DCF636262C4CC9796968A0DAF333233282030E0FC2D
- B7DC325BA3D1348C0900F88695BF7E60F9F1FCFCD353008064ACB461001450BF
- ACBC8CB45A2D2527258B59C78C63F3A43DDE0380D4D454CA9934897C7C7D68FB
- 6BDBE8D65B6FA5B884381CE75ABC787136BB44D19800A0B7B747F75F4B979570
- 700BF6F5F51500C0600C4F269CCA3B4595559594919E41498949170020190F20
- 603C3ECBC9C911B1019F7FF4F14774F34D37D3D4695369F69CD90F2425253DCF
- A7748D09001A1A1A8CCBEF5F9ECF37EFCD83384D11A7AD5157C01E061D3B768C
- 6A4C35343967F2280012ED3D37F83B8E9F316306718AA4BADA3AAA33D751CEC4
- 1C321AD368C97FDC3B272222E2E36F787B571E80A2A2A2EB1F79E8910F70D300
- 007B80800D6C50A954C2D88F3FF998EA1BEA39FA4FA3F8B878425AF47401C90D
- F0398E4B4B4B63838D545656466016B24A5FAF951EFCCD83F35252533F1C3300
- 7CFED967B7AE5CB1EA7FD46AB530569A7D0908EC01C0B14F8F51635323CD983E
- 8362A262687068F082E007E3A50088E358F40800CE9E3DCB2039E991471FA1A6
- C6C6F6DCE9D37374BA70D39801E0C30F3EB86BD5CAD5DBFCFDFD85B19E0C905E
- C3A8CF8F7F4EED1DED3463DA74D285EB69C83674010092F801587ABD9E58FC50
- 5D5D1D353636D21D77FC92162C5A4401019A0FF9BB791767991F1480B7DE7CF3
- A1B5BFFBFD06002031C0D305F01EB37DF2E449B19F3471120506068E467C4FE3
- A52D2424443080330BC7042B6D7D6EAB0051A7D79FCBCDCDCDE1CB0E8D190076
- EDDCB5EEA9279F5ACD79799401921B481B025BF9F9722183A74E9E2A7C5A8AFA
- 608104060413400300ACFD292F2F8FDADA5A69DE0D375050509073F9F2E54BB3
- B2B35EBD8CDBBBF200BCF4E24BEBD73FB3FE61CCAAA7EF63F304A0BAA69A7AAD
- BD8201F8CE53F8783200BFC7ECB3C1545E5E4E26CE0009F189347FE1828655AB
- 56A630407D630A802D7FD8B265C3FA0D0F80019E867B02009D5FC10C4030CBCE
- CA16E9F162C325198CEF38CD0937816A940223CF7CE1A6CD9B263300F63105C0
- E64D9BB63EFDD433F70300180B0A7BC6007C86D456535BC3CA88282D354D50DD
- 53F74B00482E00A98C8DD1A0B0F030FAE2F8173471C28477376CDCB0E0326FEF
- CA03F0C273CF3FFD5B1EC1C121C26849FC486048002005028044A6B35424499B
- E77B9C030C08E1F379FB780B006A590CCDBDEEBA5797DDBFECDE3107C0892F4E
- DCB86CD9B29D0DF50D3A501D0623C849AA102080C22DAD2DE2754C748C384E18
- EE74A1E6170048ACC0315CEE8A18A0F6558B7489E397FEE7D2DF2E5CB470FD98
- 030083357B585161E1A453274F5DC39A7F527151714E7D7D43080CF6E5683ECC
- C6593A2DACDE5D141A1C3ACA1430028A1EC64BA0E03BE800082B1457A80A2B2B
- 2B69D57FAFBAF99A19D7BC352601B8787475751A8A8A8AB3563EBA6273FEE9FC
- 541F6604040E0CD40669C58CE2B55C8178E1454EC7B0384E124F3A9D8E828383
- C566369B893546CBC1370F66325B1CBD3DBDDECCB06EFEAE7FCC0280515559F5
- 935FDDF9AB3D2525E7A255EC0E3DBD3D62D693129284F19DDD9D28A4C4ECC7C6
- 8C6323355C32378A78A1D5060F474545F5474545D6C4C5C79F0C0D0DB35A7B7B
- 354DCD4DC96C7C09EB864206AB2C3323B3F417BFFC4533DC6D4C01F0C1FB1F3C
- 5C5C5CFCC4C1837FF2AAA8382F440D00C08CC7C5C489C2A6974BDDE6966652F1
- 8CCF9E3D9B6EBCE146AAAEAEA2F3E72BE102676EBAE9A617144A45F7F1CF8FFF
- 339AA9D7CEBAF6DD59B3661D429394D9A432D599346FBFF5B67F557555F7DAB5
- 6BBBF506FDA5CAE3AB0B80B5D71AF0EEE1773773D172170C7EE38D3778961B85
- 44C67BCC5474543433C045DD3D5D34C0B31DCC2E71EDAC9F882AB1ABB3536806
- 8E2936DE0F984C260D8B28D9BC79F3F6C425C415707D50C7E9B19CB3441DBB8A
- 15D73C72E4880F03E1DCB869A33D2020E06210AE1E001CF4528F1C3EBCDD6EB7
- E56A3401A299B165EB16B2B47790973703D0D3C381CD9722F411C20598D38889
- E2F5D2A54B29392599BABABBA8AFAF9FAC3DBDD4C9604008E1B8969616B14796
- 60306D5AADB6695A6EEEB165F72D5B131E1E66DAB963A7A2BAAA4AF6D8E3EB2E
- 6E995F1D00CE9C39F34F1FFDE5A3577D7D7D220F1D3A44164B07F50FF4898686
- 52E1C5D457A073441AF673C85C180D790C46801D6969E3897D9E1C6CA028A038
- 304225221E801152E75800D2DD4336BB8302028368E1A2F9C50F3FFC9B397C8E
- F67B97DCAB5C72EF12E79429539C571580A3EF1D7D282F2FFFF1E8C848EFBDFB
- F6B21FD7607D80121212841126B349A442748071D3C15AED280032B94C748A7B
- 7ABA19086F217E50554203C4C6C68A521800201B203B747676513F33242C3C9C
- 8CE9E9AC39E434F7FAEB56DC70C3BCA7BF3CF1A59C63856CE6B53387AF0A006C
- 80EF81FD07B6D6D6D4DE83EECDE1C3EF504949A9C8DFA02CD45C9BA55D1867B7
- D90500A121A104C90C60F01EB466FD2798A00DD48A2A108C409A8C8E8E1620E1
- 77A816C10CBB7D98821840B4CBA572392252FFD9E6CD1B67738681E123CAE20A
- 03D0D4D814BD7DDBF6DD7CA3B392921239729FA78307DF10378616166E4E5A1F
- C00643C18AB0D030A1FC60100C03A5E53239F9F9FB89DC8F5906782884525252
- 04EDE146D87B31438238601AD38D02C892921271DD88088365E7AEED690C7CEB
- 256EF5FB07A0A8B068D26BAFBEF63AA7A394969656BEF170D6EAB5C24850B5A8
- A848F8B3541461762D160B718416F4961641F07BA9318AEFB081F2301840800D
- 7ECCA66176171F1F35A919502C92A05384365955559588117E6A5FE7CBAFBC38
- 333129E98B2B0EC091778FDC79F8D0E18D757575C1C8E9A02BA42AFC147255EA
- 00C3F8D14ACF394C1D1C140D1106CEF9AAD122C94D6937103016511F1523C002
- 2BB014C63A803541041B1D46E9C6740A0D0B15006375498087E33986ACF9DDEA
- 658B7FB6F8C52B0600FBB072DBF66DBFFBFCD867ABD38C4621642A2A2AC4CD77
- 777531BDDBC8DA67E51B97896006E1834A0E6B84608190BD6CB054F682099191
- 91D4D6D636BA6CC699843A3A3BF8782FD2EB0C5C04D9983DBE149F104F937272
- 845B15161609A0058B46E434D619391BECDEB8F1D93BAE0800EDEDED219B366F
- FDE3F9CACA9B53929349E3A7E674C61BFB29C6F98A4A3A95970711C411DA4A03
- FD0334281A9EEEFA5E21773747008A00865D0200A0629400C0AA11661E8085B3
- 4BC1405FB53FC5C7C7D3848913D8CDC2A8A0A0902ACACF8B0029DA69E822F3B1
- 880F29A9C927DE7CF3E0357C1DE745B7FFDD00282F2BCFDCF487AD2FFBD9ACB9
- B18670B2ABD82755BEA440DB8B8D191AB4513DEBF9C484586A696C26B3A9DEBD
- E2CB22C7CAE96AA0DF2A80E9636086871D9CE7DDA52F673F31EB5084727E03F1
- 0377822BD8386304040452744C344D9C982300013BCEB3A40630A3EB8960D348
- B7880596E5C87B87D338905E1C0843BF35002C6C166EDFB9FB95DCE8507D4643
- 15B59C2D25E39C9994A78BA3B25E0745A9B9D61FE8A5E68E6EB2D858DAF6BBFB
- FCC8E17E7E6AE1FB2E50B4A34300D5D9D5C972D84A8303FD0290418E1B76D113
- 441F5029D2A39CD982A2289A8BA38939D93CF37A2A3853C099A59C8D1F1C5D37
- 947A8938BF6364696DEDDA350FDEF2AFB7BCC40CF3EC18877C2B0076EED87DDF
- E1770E6D08090FF7991D1D4EC98D55A460BAB61B22E81355281902FD28ADCB44
- 75A74F5138DF6C6F5C2A1DADED6661E3A43E2B1A1F2ABE59A63DFB306656C12E
- D0DAD62ED82013DD1F6941D4C686D99815288D95423019583F4C98908DF446A7
- 617C6919477BB74B499DE4610030D245827B216DD6D7D701FC73D3A7E77EF2E8
- 8A15EB5887B45C36009C977DB76E79EEC9BF9EFAF4D7FE61323143319111E44F
- 6114E8E5478D5DECE3EC65330C8194DAD7448A965AEAF7F1A72F65A154452A76
- 11339536549292293E292D894C6715E492F9927CA88F382F507BDFA060035C40
- EA09628F3259C96EA5D7EB84F18608CC7C11950AE3072F584116C78C000070BD
- B9CEE86756595874B5715AC66F76EFDEBDE4E7B7FFFCB5CB7281FAFAFA88679E
- 5AFFC7D696869FC6E57851514B2959070768667A1AF5D7710A5386D2B0AC857A
- 07BA48ABD65094269C111BA6762E5CCE5B06B8E0B19336A1971A069901321769
- 0682C96689A0047687487339595ADB2922369A4AD421F469451D29C82D9220DB
- A0FDE1EBD913B2C860D071B42FA6D212B7F152E7D8F3010AEC11447D38A09A1B
- 4C42318E144A22083FBB71C3EABBEFBEFB896F0C00FB59CE9AD56B5E6A696E9D
- 3C79CA44F20DE9259B5737073BCE02B52E9EFD78D2EA07C9642FA573D566CACD
- 8EA7005B1C59DBC2C8EEECE2A8DF4676A6B28F8F8AB5A882DFDBA8ADD941722F
- 352D8E09A294CA52EA31379226399E0EC8FCA96C5046410C0CA2BF7C641D6002
- 1B1F1169A0C282223A77AE74D478CF45130900B5DA4FA44B93B97674995D4868
- FE6D7656E6D9EDDBB72FE2345BFD8D006061B3E0F9E75ED8C1371282A52BBDDE
- 400A414939A97DBD69D825E79CEE4B6A6D2F39FD2D6493338D3B5C34D81CCA2A
- CC8F9C41662A305793BF9F17658F4BA28E8A403EDE9F025D7DA41876B7F07D38
- 038429896A7AFAA8D2A1A2F15C3B984D26D11182E0C9CECEA4C8E8482A2E3CCB
- 2AEFDCE88C7ACE3A06F61A4EA11048B575B51C108784B4F6E5F48999CFCCCE2A
- DEB56BC702B6A1EEEF6701E61E2375F78EED3BD673DA090E0A0A142206BE2817
- 6B8F6E55C7DE3A5A5DA854729E6525CF869C733E5F58C36245D74E168785A33E
- 0BA67A5FF2B2479351ADA098F66A1AE8B050045785653EA1F476593D69183023
- D7FD90BC260600B2163E1F1D13C50AAF98CE9D2D11C67B2E984A6D736C087610
- 5426531DC727DB081BD4420D721D726EF79EDDF30D0643AD87955FAF030EBF73
- F8AE279F78F2153EA912911485147232F233E804FDCDF5BD0832022F178D0423
- 690183C4C28582B587028FEEB1DF5BDA988E0E17FD4B948612384BF80F769245
- 1940EF0FFA51A9C39B92B97002EDEBCD6691F3B398F6E3C645D3D9E2B3545C7C
- 4EE801CF4553C970188A3A0303C0391C765C9AFC35FED4C62A34DD682CDEBD77
- CF02835E5F7791999706802FE2BFE49E25F92C2E9259E9D100073B342B908B47
- D7F9C5D29652F4F1509C88A00335A7F61592177F0EBB8306850FBA7BFC2CE1C5
- EFB55E0A0A241B05CB1CD431E4A06A363E44AFA7D6A666045B0A64AD8080372E
- 3686835DA9A03E84130CF37C68C20DBC4B300520C078B176C0E8070469A891C1
- 4C4B1B5FBC67CF1EA6FDDF187F6900CC6673F2334F3DF3DAE9D3A76762D1014F
- 6041B448E908C602844056631035FE7EFEC27091CF47567CC018374BDCD2169F
- E146A5A035C4C0D8F97C03C2979D94CA121A52B7818DD770D5979595211E782A
- 2B2917FA1EA5318CB7E3385682F071F783922EAE0B7442F79B98356E692DA790
- E0208E017594323EB578FFFE7D3FE53862FE9A10270008E517ED7877F4BDA3F3
- 5F79F9951718841818696EA8A7162E3F316B9E6B73D22C6028990578522B4013
- 20000130124BA4AA0EBF517A292F783E00E7828E8066B7D91CD4CD85136A808C
- CC7496CEF154CED2B690F57D4FCFC80228723C5F339A75472333C5C6C76281C4
- C60CC3DA0018E670DAF9FA01D4C2339F929A5ABC77DFDE057AC32567FE020042
- D8988ECD9B36AF7C7DCFEB2B38C8F881CE30A2ACA24C94B252F92AEA770E842E
- 69B98A68341A4B01092CC1CC8319084AA2CE1F618978308AE308CA598929D8E0
- DBDE1CA9D38C6994989C40D55535ACEF0B447F4F620DF6B11C0FE2E262E9AF27
- F3C5B92197516B60383893201EB5B5B6A01D56B86FEFDE053ABDCE4CFFF71000
- 0472D455DF38EFC61A36DA5B4A2BB8281E5B931E6985C1A8D7BD1442A288FF36
- F07CD6CF73FD6E1414BE29C402188994A809D05050A09B256083B43638CC8133
- 8BA37D567616D5D6D4B2F185D4D5D9258E7757770E5150C1354EB2F11C4D38CB
- F45103670B5C1FEEA1F2F6A2D666186F2CDEC7B4E7C2E7EF19FF15004D8D4D7E
- 93A74C36A9942A055A5500008B95164E539E03F4C54CCAE55FFD73892700E8B8
- 31E9DD8D3799FB33113F1C5F0102AA4A9D20B88D8175055812C1F5FFF8B4F14C
- FB62F1D8AB98F991670273A74F65E002282FAF805D49258AA566369E46DC11F7
- D5DCDC40E9191985FB98F6DFD0F8AF62006F96FDFBF62F3B74E8D06206C388BE
- BAB5CFDACDC28703BACCC5741DC69E33421447DA28AE09E4122030447AFA5300
- F215349E6F4687E7834F985D1C9B9591254050B3AB208D4A353DCE9995696425
- 184A79F9057C3D959879F405C14B9C03B46F68AC479EBF5CE34701F0CC020A46
- DFC0AED0EDA5F21A90140E8CC7CD707CF0E7AC909E979797CBDB848282829CCA
- CACAF8EEEE6E2F111047A2BF686B21E77DCDC35A12583012C24617AE130F47DA
- D978C402E969B07096C053A7E6B0CF9F1631096D310BA7652980C27873BD995D
- 23F3CCEB7BF72CE2F35C8EF19704E0B206CF946F4545451A8331F5C48913D30A
- 0B0BB31890644B47870F8D640CE93980AF7B744D2C80706035A61947AA3E1547
- 7BA74871D0135A2DC78C202D07B756D13BC09C2023C078AC29188D6945070EEC
- 9F7F9933FFFD0070F1604AAA6A6B6B13199029A74E9D9ACA0CC92E292931B6B5
- B569A4B4E9F960C4C83182092949C9A28891C914A3A9169D5EF4FF9B39ADE109
- 32B796B08B42A796E56E464646D108EDBFE983915716808B079F5BC1054D4C7E
- 7EFE140663228332A9A8A86802FBB0167E8E219E08E3E0181511457A76058E91
- 0C8052C8D8C4C44432D5D6B146E816B1C1E1B0899947A648CB3016EDDFBF7FA1
- 5EAFABFB0EB778F597C7990D11881DC5C5C559701B569C13ABABAB0D620D3035
- 4D640C9D3E42B4C9F937ACE8AA455CD185E9C4E269554D3565A4A71771AA83BC
- FDB633FFC30170F1E8E9E90979FFFDF7E73FBE6EDDCAD696B664A4454E6742CA
- 82F6434303E277288EA04B8CC674F8FCC2AFD1F6FFFF0090467B5B9B61DD638F
- 6F3A70E0C06D580683DEE8EFEF631DE172477B96BB995999856EDA7FE7991F7B
- 00607040F479F2F12736EEDF7FE04E9E7D753B17488E61BBE8065F7FFDF52777
- EDDAF96FDF21E08D7D00A4C1622B85E3C414CE28B17C7F4E0E861573E7CE3DCA
- 19C4FA3D5F6A6C02701547D83FFE79FAC7FEEFF3FF0B43E930A009E1CAF90000
- 000049454E44AE426082}
- Visible = False
+ TabOrder = 1
+ object pnlFSX: TPanel
+ AlignWithMargins = True
+ Left = 233
+ Top = 3
+ Width = 224
+ Height = 40
+ Align = alRight
+ BevelOuter = bvNone
+ TabOrder = 0
+ object imgFSXStateNotConnected: TImage
+ Left = 4
+ Top = 4
+ Width = 32
+ Height = 32
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
+ 00200806000000737A7AF40000001974455874536F6674776172650041646F62
+ 6520496D616765526561647971C9653C000005774944415478DAC597C74B6C59
+ 10C64F9B737A9815DA8839A388115C28032266915988CE6660FE9199EDB8706F
+ C4D1850CA2A8288A2898338AA298033EF3336B4F7DA5E77A5B6DB5DF660E1CEE
+ EDDBB74FFD4ED55755A7353A9D4EFC9F4303008D46A33C282E2E76373535B536
+ 333313262626FC9DFC5EFDDE47436E0A57CCC7C747F1F0F08079DEDCDCFC5DFD
+ 9E02505A5AEA78727252ECECECEC636969C9CF2480BC1A33A461F5F5EAEA4A77
+ 7676B6E2E2E2D2DAD0D070AD07909D9DFD5B4040808F56AB153E3E3EC2C2C242
+ D9BDDA0B3FE301CCDBDB5BB1B5B525565757C5FAFAFA7C4747C73F0A40414181
+ 3BEDFAF798981891989868D0A8B121C0FBD8C8DDDD9DB8BFBFE7E7232323988F
+ E6E6E67F3535355D33406161A1D6DEDEBE22232343F8FAFAEAC55E6DD41800D2
+ 91080B0B131452717979294647471962737353747777E39DEAC6C6C6430620E1
+ 31406666A6F0F0F07803606C0820E0F0F070E1E4E4A400F5F7F7731876777745
+ 5757171E57D7D7D73F0194949430404A4A8AF0F2F262B7595959899B9B1B1690
+ 3100F86D545494A0F594671473B1B4B4C46B6D6F6F8BDEDE5EAC575D5757F704
+ 4019C000494949C2DFDF5F242424080707074E9DF3F37341CAE5EBE9E929EFC2
+ 50ED00747474B4B0B5B5559EEDEDED89E9E969FE0DD6DBD9D9110303031C0205
+ A0ACAC4C4B062BE2E3E35984212121BCD8EB5D630710D4F1F131C715D78B8B0B
+ 7E6663632362636385B5B5B5F23EA5B5127B590B00303C3C8CCFD5B5B5B52F00
+ 8E8E8E15701D42400A156E6E6E9C8E521386C4F69CDF1C77D40F39E0B5B1B131
+ 0E230C030020D000A0E8D95B808888083688C5A062188627BCBDBD393BE0DAAF
+ 68E1F0F0504C4D4D291A820D18070800262626DE07080D0D6500189710EA4A48
+ 158C61E0194320070707627C7C9C8DBD2AC30C2135F1068052A622282848B8BB
+ BB2BC6E57C5D8AE10D84EB3D0800A0D8C0B09CD238E6FEFEBE989B9BC3BDBE08
+ 01E0E7E7A700A821A406A4417C4E4F4F17E4B53700D003F25C6D5CC61F6205C0
+ E2E2E2FB00308E459182883DC408636A0FE01E9902B11A126667672767897AF7
+ 00432A2373500DDF0580F26118C5048AC60484DA1B308E8605202CBEBCBC2C82
+ 8383F53265707050ACADADB161D40D881113F7D7D7D75F07901E9061409141AE
+ C338DC89F28A0E87D0A5A5A529109393932C44E901BCFB2900B2002130040081
+ C2088C63319453C4530E9471BC8381546B6F6FFF10809EBDF482CF0002030305
+ 1A15EE115B7433C4523D90BE3939397C0F4394624AFABD06D8D8D8600FE801A0
+ 1463113A98700B45DC2500F21E5E4075EBE9E9E1EB7B83CE152C60ACD9DADA2A
+ 8E8E8EBE0680662401D090D013E00DB5B0D088A4BA0D0DFC0EF501030DE739DD
+ 18408A510D40C7B297760C0018453341083C3D3D051DD178413B3B3B313F3FCF
+ 4DE4A381142E2A2A629D2C2C2C30C47B1E407B46257C73208107A406301182E4
+ E4646ECFB3B3B39F0260E4E5E5B1F720508441ED017508004047B243BD23995A
+ 84302EBB627979B9989999114343439F024446468AD4D454365C5353C3460120
+ 21641600808EE84F00F9F9F90CE0EAEAAAE701D9942A2B2BF9348B02F3D9C0EF
+ ABAAAAB8E1F4F5F5293D00531624D40E00B4B4B43C01E4E6E6B206D0EDD4BB97
+ 15302E2E8EC5B7B2B2F22980AC0908973C0B604A4FE08A8645DFFDDDD6D6F69D
+ 01B2B2B2BE11C01FD4EF35EA562CA7B187520CD98AD5FD40C250463D5028FEA4
+ 7A72CB00546235B4E35F290401A09667007523FA993F261240FDEF08058E0EA6
+ 13B4C97FE960A263003A649850A7FA4622FC853CA125A38A3575173466C0A01A
+ E6F9D9239D1397E850D249E23EA386F50440954F432EB1A47B7BD2803DD1E164
+ 699CCFBFE0188AFF0F0AC5396DE69CDAF3ADDE7F432A4026746F8ACD1A1B6F23
+ 43F340000F246A1D3EFF0712759FFDF03F71A80000000049454E44AE426082}
+ end
+ object imgFSXStateConnected: TImage
+ Left = 4
+ Top = 4
+ Width = 32
+ Height = 32
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
+ 00200806000000737A7AF4000000097048597300000EC400000EC401952B0E1B
+ 000008124944415478DAC5977B7054D51DC7BFF7B177DF9BCDE649221188840D
+ 2492A243487C2C3E68476D29D599A2A53E3AAD5275A60FFFE91FDAD67F9CB68E
+ 33AD558A05E91F75C4222DA2B49476B4DD100832986002C612A76D90B0E4BDBB
+ D9DDECEE7DF677CEEE86242E26FCD53373F7DEB97BEEF97DCEF7F738E708F83F
+ 3761FE8B8AF61DCD922405645986284AD4837511F37761EE975691D1F83BFAB1
+ ACFCDD84699A300C9D2EF3D2E8F1C7078A0254DDBC73693A36F2A6ECAFDB20D8
+ 7D648FFDC500A4FC5D2CC67B8596330C187437F8DD2220331DB5AC44E4AFAE40
+ CDB648C7A3B13900BEA6674F3856843634D59761ED32179C6E0982457F8B22D9
+ 16721D8BCDBA88A656BE8F65E4402CC1443A65A277701A670646A00F75BD19ED
+ FDE9D61980D2F52F360B8AB7AFF9861B70FFCD15106DB9893315662BCFC558CC
+ FCF5DC37C40D9743443A6342CD92021AF087E363E8EDEA3414C5563E7A6C7B2C
+ 07D0FA7248F45487BFFAC5B568A1D98B9200E67E360087B06685C16200A8BF4C
+ 1F6F5AEF476DB9827852C7BEF7C691552DF49E4FE1E0A11390856C70F4E863E7
+ F890810D3B09A02AFC350268AC7390EA050001DCF382B068EFB3E650047CA9B5
+ 04D565F63C90855D6F8F209535F1F1A7691CF8731714510B0E87BF9D0768FB6D
+ 48745785EFDAD88CE6650E2E9BCF2B2291A6E8B5989A020B8585FD4FCD6517F1
+ E5363FCA4B6C33EF7A0692F86777028669E1CC600687FFCE007402F856016037
+ 77C11DB7AC41FB6A27B6DE164065A90D9A6E612CA66124AA632CAE2132AE619A
+ 6434CDE2243E9784CDED2528F55E367E8E667CA82B46C6019DBEEBFB4F16EFBE
+ F73E6C821A1CE978A400F02A01D4846F696BC44377FA70FB3A1FBC349830CFE9
+ CC7046353134AA6272CAC0D0988AF1B8C1DFF93D12EE0DF9E173CB33FD2F4DA8
+ 78E31F516435529226A3190C4045E7D15390580C743C9403286DDB13927CB5E1
+ D61B1BD07CAD02874D44439D82B5F52EACBAC601492A1E013CB7498CA9940E85
+ BE713B2EA7C96854C5BE700C094A3F9DFAE99A059520CE7EAAE2FD63DD145B99
+ E058C7837980F6DF85244F6D78DD1756A2E95A1B6CB2489700990C7B9D228138
+ D052EF44C0277F469562EDBF97B278AB33CE83CE20E306D5225537B94BCF0EAA
+ E839D9531CA0B979255613804286D9251388C4B281152232BCAC4AC6F52B1C04
+ E4BC22C8274359ECEB8843D7993ACCB8C59F5523A740FF7915677A7A28B5B3C1
+ F18E6FCE06B8261C0CD623B89400949C028A4DE0F92C3100F1722AAE5B69C7E6
+ 365F51884F2E66F1DABB711E2F2CEA59E06979F9558A958F2F6838D7779AFC97
+ 094ECC075876DD0A342E5560B793719A3D73814D2A005CAEDB32A9F2E4E600AA
+ 03B6CF004CA50CFCEC8D711EF50C4033732AB040CCE60106FB3FA4882680A3F3
+ 00BC55CB515B21A3DA2FA1C42DC24E81C514281426BE3CD1F38377F8D0B4DC71
+ C5C07C6EEF3826E239FFEBCC38F93F963431126399A32139D4474B442638391F
+ C053B91C5E5A845831712B123C2E114E52C34EAEB0B18B201EBED38BD6602E06
+ D8E01D7D296CBCDE3D27535EF94B0C5D1F65C8B085695A079254D05234FB74C6
+ E00AA52E2E02C045000EBACBF96C60F7FBDA5DF8FAAD1E6E9C49FAAB8371F4FC
+ 5BC54D8D763CF99512AE0E6BFB3B93D81B4E72E935EAC7EAC422006AC39E8A15
+ F07A8A03DCBED6C18D30E3A9B481170EC4D07F419F99F5E3777B4909177FFEE8
+ 7C16CFFC3EFA3900BDB4541340E74C1A5221721340657D518050B3033FBCD7CF
+ 17A768C2C0CFF74731386ACCF13DAB1F3F7E20C09FD394FFDB9E1FE52E2A0A30
+ F42129909D05C02A21956277E57578FA1B65A8ABB471BFB320B451656DA142C4
+ 54189ED4F18B3FC61099348A06E0AFB797A1AA54E681F8BD9DE3383FA253F199
+ 0540CA4D4D13C085D3D48701144AF186DD548A6BC2AE8A9578645309EEBFCD47
+ 25D8CEA3BFD08627353CFB7A0C1309F38A1570DB4637B6B47BF8F3CBEFC4F0B7
+ EE3434329CD17200D304902080E9A16E52400D4E1E7BB800B02B2479ABC38EF2
+ 551484325F8ED7D4D9716B93135B6EF2A08C4AF0E15329EC3E92F8DC125C1B90
+ F0D213E53C4E8E7C90C24B6FC7732EA04294CA92617241825C908E7C4031A006
+ A3C7F3CBB1BFF595904C1B12A5BC91528F0148947E221C548C1EBDDB87074891
+ 432793D87D38B1E0BEF485EF04D040EA9DBB90C5F77F33CE6B000348AB24FD34
+ 2991D6908D9C2205B460B42BBF21F1AFDF41315019B60556C3E950E0A6FCB753
+ 39E6AB62AD823D4F55E160570ABB0EC7B150DBD2EEC6F67BFCDCF7773D13E101
+ 99290422D5836C3A03F51201587A307A22BF25F3DFF822015485E5400364C53D
+ A3002B3EAC24EF7F7A098EF7A7B1F3D0C2003E82FFD34F96E0C0B1247EF9568C
+ AF822A03C8B2A24467032D0575F8347741ECE41339005FCBF321D9571D964B96
+ 43905D906C0E329E5F9629FAB76EF4F2F40B9FC92C08C0DA77EFF161CF91295E
+ 01355A14748D4168B42BCED08E39096D7C809E93ABE2DD4F0D70006FE38F1A24
+ F7927F89AE0A41A03DB9202AFC62FB7341620B4EFE847435DBE2FCC1C4A21311
+ 4C95CD985E6BFC6E242EAAA63A5596E87F2EC94774D6DC2742741DB1F91B3699
+ 6A32B7CC8A32372C08855391781507A3C2B18C00D8E9888E6630753AA0581015
+ 0FD491D3AF0A8AE3B1F4D05E8B0F69F3B448E6F4708354B26687E45C12A2A54F
+ E40315CE857C672C2ED27A9E814E43B95DB48999EDB4A9EB4672E81D3D71F607
+ B26FD54535DE65720049AE132C7DCA473D6A04D1552B88F6001B220731F3931F
+ 7901CBF3552A9CD30416F89951CBCA4428D022A635999CD35D14A88A5826399E
+ 0E2D10AFE61CB27855F81656D0C8A5AA694DF092FA3F8CC8125D22B18C700000
+ 000049454E44AE426082}
+ Visible = False
+ end
+ object lblFSX: TLabel
+ Left = 42
+ Top = 4
+ Width = 146
+ Height = 19
+ Caption = 'Flight Simulator X'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -16
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblFSXState: TLabel
+ Left = 42
+ Top = 23
+ Width = 70
+ Height = 13
+ Caption = 'Not connected'
+ end
end
- object imgStateNotFound: TImage
- Left = 0
- Top = 0
- Width = 64
- Height = 64
- AutoSize = True
- Picture.Data = {
- 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000400000
- 00400806000000AA6971DE0000001974455874536F6674776172650041646F62
- 6520496D616765526561647971C9653C000010B74944415478DAED9B096C5755
- 16C65F77282D5BA150CA2A4B45A050948285418442214E6140C74463C718B463
- C448C6688C6B8C44258A88041D9851B4A22D33A962D906991123B22450108A0A
- B21611690B48D94A59DAFF7CBF1B4EE759CB48070AFF89DEE4E5F5FFD6FB7DE7
- 9CEF9C7BEF6B48201068E9795EA5F7CB6C8D424440A35F3A01D1FAA3E26AF7E4
- 2AB5E85F09B80A04849D387122E6ECD9B35167CE9C89ACAAAA0AD3DFE1DA42D9
- 4E9D3A15D6A44993334949493B2B2B2B1B979494C4E93ACE855457577B6CB4D0
- D0D040585858757878785544444475A3468D4EB76EDDFA987E57072D01656565
- F1F9F9F9637FF8E187F873E7CE85024CFB90D3A74F8708AC575151E1959797B3
- AF7EF0C107576CDDBAB5F7A64D9BE28F1D3B16A2CD3B79F2A4A77B3CDDE38938
- C808889840AB56AD02C9C9C981112346ECCCCACACA1731554147C0C183075B3E
- F7DC737FF8F6DB6F9B474545D51CC7A200523F1CC003070E3812060E1CE88E1D
- 3F7EDC93C778F20C4F44B96B05DA6D1CBBE69A6BBCF4F4742F3E3EDEFD9E3871
- E29C84848403414500AEFED8638F65AD5EBDBA83DCDB010B0909717B08602FAB
- 79478F1EF576EFDEEDB569D3C64B4C4C7484009A0DC0E7ADEE363CA177EFDE5E
- 9F3E7D9CE7C8ABBCCE9D3B7B77DC71C7F21B6EB8614D501150505030F089279E
- 1803788002DEDF14CFEED89E3D7B9CC53B75EA5403128B9B97D8DF1CEFD8B1A3
- B3BCC2C46DFC0D19CD9A353B7CEBADB7E6C4C6C61E0B0A02D4E1D0C993274FDC
- B0614322041858DB689082EB6FDBB6CD6BD1A285D7A3470F67752CCEE6777B7E
- 43C0B5D75EEBC9D29EC4CF7BEBADB7BCDB6FBFDD8583EE0BC80B662B244A8382
- 008957CC030F3C304971DD58CD1100609ADF13D6AF5FEFEDDAB5CBB975F7EEDD
- 7F4480818708C073ECFAEBAF77DAC0F1152B567813264C70BA317CF8F07FE8FE
- 757A64202808D8BF7F7FFC430F3D94ADCE87237E4A539ED2564D28B007D0679F
- 7DE61517173BAB1A01E6F6FE8D78E7FEC183077B4A91EE1E09AB23A457AF5E5E
- 7676764EBB76EDF65C64F71A9E80A2A2A2AE8F3EFA68169D8600F690C0863744
- 46463AB09F7EFA2964392BE2CAA4457F085818709CFBAEBBEE3A0798B0C1B310
- 523CE2E1871F9EA7F0D81534047CFEF9E7BD2480BF8F8E8E7660CDFA46047B08
- C003D081B4B434AF43870EEE985FFC006F02C87D2A7A1C015F7EF9A5234959C6
- FBFEFBEF2B74FF1C6591A34143C0F2E5CB539E7CF2C9713131310EACDF03EC6F
- 40AD5AB5CA3B7CF8B023809CCE313F0156FC404CDBB66D3D153FDEDEBD7B01ED
- DD7DF7DDDED8B163BDA64D9BEED2B979B5B3CC5525E0C30F3F4C7BF6D9674741
- 8079803F04F88D5BAF5BB7CE81239695CA6A14DF0FDEB6B8B838E701CA2C4E13
- 66CE9CE90813F8B21B6FBCF12F7AEDB9A021E09D77DE19FEE28B2F0E555EAEF1
- 000B03DB00B17DFB765701A6A6A6BA9836D5C70B8C0CE21CD22080F457585848
- 85E98D1A35CA6BDEBC7940E97671BF7EFD36D4A37B0D4FC01B6FBC31F2A5975E
- 1A8C55FDB1CFE627800A1011C30338E72F7CFC1EC0F5585F80BD6FBEF9C66580
- AE5DBB7A999999C7146AB344D099A02260C68C19635E7EF9E58178801FB89F00
- 6A783C0080B2A04B8FB5815B19CC39A5391726548D268C7DFBF62D79F5D557FF
- 2A022E7620746508983E7DFA98A953A73A02008B0BFB35806368006530E07AF6
- ECE95CDD5FF71B01160294CA6C5C8F37AC59B3C64B4949D93E6DDAB4DC7A76AF
- E10998356B56BA52D490962D5B3AD056FC181946006ACE39DCD90649B6F97FF3
- 0C3C80E7A103104036D050788386D08B828E0059A7DBA449937EA72227065707
- 302267552124E0C2A5A5A5EE6F0639343F78DBF002EED170D76900CFE15EB6FB
- EFBFFF9FE3C68D5B1D7404D0246E4D366FDEDC4EF57E476DEDB66CD992F0DD77
- DF4503182B028E1A8086C29BA758E3BC91C239EA000A2B065710B673E74EEFA9
- A79EFADB902143B6062501B5DB9123476245429BC71F7F7CB472792B2C69951F
- 96B522C8C412CBD3AC7862BE801060DBB76F9FA71AE3C4071F7CF067DD532D61
- 0CD7F32A75EE6CD0124093D53ADF73CF3DE3BFFEFAEB661448283A56EFD6AD9B
- 034F4DC0D800EB2378145294CAE88586CCD5EDDBB73FABADBC4B972EFBA50367
- 747FA4CEC709FC41D50DA522EB507272F2C1ACACAC13FE19A8A020E0E38F3F1E
- 2C0F189E9F9F1F46FA230C98F3C3E280A5511330DAC3E237DF7CB3377AF46857
- 2BECD8B1831038307EFCF8F5BABE72F5EAD5DD994CBDE9A69BB60F1B366C1B93
- A4F2A6300963D4471F7D14A92176A52AD1D3D28DBA86C757960059296AF1E2C5
- A3A5F829585C6EEBAC8C0740009662208407303D76DEDA9EC07983060D22745C
- CD2072AAB43FAB22288A224A9560914690251A1F948BC0C3CA12E522CE15444B
- 962C095FB0604140E9B85A6385DA245C3902247AAD047E9CACD5819A000BBFF6
- DA6B4EFC8C00840D858700CE5BFA93C2BB592248619E10F220833DF79141D8A3
- 157A5695483BAE31C15E659F151A581D7DFBEDB743F19E2953A6D49E32BF3204
- 7CF1C517DD3FF9E4934CC567D3828202071ACBE1E25611020062C8EB80E63C1E
- 01398CFD15EFAE32B401147FE3217884CD1CB38724CE51296A8458FAC8238FE4
- E81915F7DD775F6876767640630DBF17343C014B972E4D93D20F4F4C4C0CCFCD
- CD75715C5656E60A1E3A4A2D4F16C0B2741A973702104500410E449022114332
- 0533C0144F1040368014BC82FB184E33B50659E9E9E9FFCAC8C858B576EDDA10
- 1657860E1DEAF7828623401D89C8CBCB1B535C5CDC1F0B2E5AB4C893E23B37C7
- 65A9E60E1D3AE4C091F62080313E5E0031FCE61C618027001A022082EBD10AC0
- 721DA345C0721F0402DE86CB7ACF5EC57F8EC80438C545C37B802CD36CEEDCB9
- E3D5D1CECCEFA1DC527CD731A6B0E89CAD0FB00114AF80007E03C8621D2FC0EA
- E47EAC0C79784A5252524DA6600F3180679688E74036EF95A6546848FEBA883F
- 5947572F3F01547C6FBEF9E604C5762B3A4BC799B80424AE5A5454E4E2D90645
- 58174D90423BA0B608C2F53631CA39365CDE5223DE8037112E841084B22E0078
- A6C998614623742E307BF6ECB932C4BE0627402ADF6FE1C28519CAC18D1136AC
- 42A94A9C52AEDA0C30E0FD233D5675507FAEB741129B110158E29B112364718E
- 38E75AEEB3F941F6108CCE189168C8D34F3FBDE4CE3BEF5CDF6004B0C829971F
- B672E5CAA1740437A6C0A1F37400F7C64D6D1698C207CBB3C70B20827336ECC5
- 13581A63B6C796CD94491C51DCCF58001DE07E6690994431F0100D782BA7A928
- 33333337BFF2CA2B0B1A84000959F48C193332156F3D894B5C1100B82C8D3864
- EA8A7826AE112E5BDC30709000182386FB716B23801218CB738E900220EF017C
- 4A4A8AF306859E239D67DB428A4D95AB5FFB5474CDD57B2E6F2124416BA362E6
- B77A46072CE69FF0A0B374944A8F8E12BB0C5C6CC5D714DC88F14F7AD89C8179
- 06E72D0D021011240B6079C0E31D106D96F72D9FBBDF22B34215E1EB22EFE465
- 2340854D524E4E4EA62AB41844C9567588775CDE4675580E006C36DA33F162C3
- ADE938318EB58C189E63738290417A840CF6E84AFFFEFD9D376CDAB4C965165B
- 4AF32FA89AC6E00DCF3CF3CCB2DB6EBBAD50863977C90428ADA44AEC4629EEC2
- 496D58CC263B008FDA633152119E41A751661A40F1101A2ECF75FCC6DDFDE5AF
- AD035A2C5B98503F306FC81ECB031EB5B7D9639B4CB5E7701F1E43C125F2CBD2
- D2D28A350C5FA9FB4FD49B00B96BC4CC993347AC59B3661031C88B0048CC0292
- C206C6C9FD8400220839581931C4BA780AC7D00BAEB785118E59EAE36F7361F6
- FCB67900621EE537CBDB129A7FF5C808805C368CC3BB300ED7BCFBEEBB0BEFBA
- EBAE8DF522408399D8A953A7662AB7F7807D80F072549F0E40080089692B5CE8
- 0416A71E0004D7A0CA3400E1D25C07017490FA002F40CD69361304495C87E5C9
- 009CE79B00DE6FF1EEFF8082BD4DBBA13BF4EBFC40C991316DDAB41513274E5C
- 79D104C8D5DA2997DE22208903060CA8C9D1EC01640B1500658292995D3C0200
- 741252B02C1DB23940EEA3433C8FEB2000902839BA611320B60E606E8FDA135A
- 06DEBF686204D83A247D316DE037D7F6EDDBB74C293B4F9E7BE4A20850AC27CD
- 9A356B9C3A12CD4B713FAC89556C5516F0FE3C0EE374048BD3013A62391B0B43
- 04C0CCC2DC4BA771514285B103314B0641E5D569176A5BB66CF1BEFAEAAB1A8B
- FAAD4E630F713CDBC0738C7763793DA754FA95270CE53F2B82744E4CF5D7587A
- A4727A63D4DBD6F6ECEB0E63DE1AA4700DE778B9A54513373A0129589A8E11F3
- CC000188B5413ACF971F94BC1040598BE549797EF0FE0553FFCC3162C7FB006F
- 7A00B1902AB12E9B376F5EAE0FFC7F2740964F79E1851732F5D050536D9BC707
- 24D6B7C2C508AB9DCBFD9FC1D06CD2028B5A594C27E9305A8178E2F6C42D6105
- 78521EE0C92280F72F9A1A709E41E6A1411CD7D8208AEC229D2A15F8BC5AE02F
- 4C801E1079EFBDF7FE51C5451CB189E58869368B2FFFD2165E6184B037E074C4
- DCD096B5B89E67D80713E47C2C8457502C496C5DAD60E0113B08E03AFF52197F
- 1BF1780ACF07BC8D35A8442153E1E4C04B3C6B83AF9B00B11F27B51FBB71E3C6
- 4E749E0ED44E4700E0057414962D9F1B21160AE62116EFFE8F9DF81B62792E29
- 11E1033CCF4D4E4EF6BA74E9E2D21C8A6F637EAB0D6CAA9C675A16B12A13F00C
- 8BF12A8553695E5E5E2ED3621790B81F13B074E9D21E73E6CCB9450F6B06483A
- 8455CC5DED0566059AADF4E01D10421C9A97D8A8CEBCC4FF7D406D42080FC864
- 488B5852DA92EB6D01D45C9F4C409FB897948891006F4632CB03FEFDF7DFAFCB
- ED7F4A806E3C357DFAF4DFBCF7DE7B43146791000204CBCF58C986AF66598B3D
- 9AA9B109125E82E5113BC8B0713EC7ECC32823C51649B130E7517FD60518F652
- E5418A91C49E90C033F8A28C67D33732058DF3781BA9588257027811F4739FCA
- 38021A497523323232260B74B809132F6568E9CF0A663DFBED1739FFFA9D9F14
- 4B991636749CCD74C4A6B2A8F010470A2C2C8F285A6DCFB3F00ACE932D7826A4
- D9822AE7791EE0113CDCFE22BF13FA0F01A9A9A97F12C0502C07013C8C12D6DF
- 20C072BE353F01F6DB7FAC36211CB3D12261435D0131E4790A28629EF7FABF09
- 644D80F0628E8F3E18780B478EF15BE153929B9B9B57EF8FA4B49DD28D030A0A
- 0AFA287E5A4B4494BA4F54F215F779E5AE66AF8CD0544ADB5471196284587557
- D78749751DF37FF80440EE45F42001F2FD56E77E34C12638B132E0318EB93DC7
- 0803DCBE9EE07F2A826AA1623F46EE7A5AE06A1617CDAAE883B2427C6161617B
- 6D0972D50485490BA531F7E9A76984C5FA85BED6B2E380B4696C6A0000E161F6
- 3518C0F96688982784080BD2B20928EF42A845E001E9D7FC7A82AF93807A3559
- 2A42B57B6B9191B876EDDAF6AAD3DB8A9038A534271458D7BE03B81019100010
- 06559666ADBAE337AE4F5AA34CB690B49847FDC9F3F3E7CFBFD898BFBC04D46E
- B24A9844AC2584C86AEDE5216D357069AD6A2CCAD2A6FFC388F3F738402C7D61
- 654B9D36C2A40CB6FF21B029731BE8283C4AE5F6FF2BF8CB4F40EDA667872A3E
- 9BF1A538E1C2C71112B9B68AE1C6C439CDBE0843046D086D3340A4449B5237A2
- 209034A99847ED2F54E105070175357943ACC8E02B9136848D2ACE84DDBB77C7
- 6255B20040C90C143C94C080E51C3A818730E57D1E7CEE45E4F9E023A0769375
- A3972D5BD663CA9429BF519CC751DDA1FCB8386ECF109CC6E088C50EF2BC62FE
- 522D1F3C0458C333444286C0F52614C80636AF6082C7B780E7DDFE522D1F7C04
- D0F89F82E79F7F3E4318FBC9FA110C906C497CE4C891FB737272FE7E098217FC
- 045853B1D54A3A9128016CAEFE05248687D3D3D3774800EBF319ECFF2F0157B0
- 45FFFACFD3BFF47F9FFF371E3422DF2CEB57F80000000049454E44AE426082}
- end
- object lblG940Throttle: TLabel
- Left = 79
- Top = 8
- Width = 281
- Height = 25
- Anchors = [akLeft, akTop, akRight]
- AutoSize = False
- Caption = 'G940 Throttle:'
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -21
- Font.Name = 'Tahoma'
- Font.Style = []
- ParentFont = False
- ExplicitWidth = 401
- end
- object lblG940ThrottleState: TLabel
- Left = 79
- Top = 35
- Width = 281
- Height = 16
- Anchors = [akLeft, akTop, akRight]
- AutoSize = False
- Caption = 'Searching...'
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -13
- Font.Name = 'Tahoma'
- Font.Style = []
- ParentFont = False
- ExplicitWidth = 401
+ object pnlG940: TPanel
+ AlignWithMargins = True
+ Left = 3
+ Top = 3
+ Width = 224
+ Height = 40
+ Align = alClient
+ BevelOuter = bvNone
+ TabOrder = 1
+ object imgStateFound: TImage
+ Left = 4
+ Top = 4
+ Width = 32
+ Height = 32
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
+ 00200806000000737A7AF4000000097048597300000B1300000B1301009A9C18
+ 00000A4F6943435050686F746F73686F70204943432070726F66696C65000078
+ DA9D53675453E9163DF7DEF4424B8880944B6F5215082052428B801491262A21
+ 09104A8821A1D91551C1114545041BC8A088038E8E808C15512C0C8A0AD807E4
+ 21A28E83A3888ACAFBE17BA36BD6BCF7E6CDFEB5D73EE7ACF39DB3CF07C0080C
+ 9648335135800CA9421E11E083C7C4C6E1E42E40810A2470001008B3642173FD
+ 230100F87E3C3C2B22C007BE000178D30B0800C04D9BC0301C87FF0FEA42995C
+ 01808401C07491384B08801400407A8E42A600404601809D98265300A0040060
+ CB6362E300502D0060277FE6D300809DF8997B01005B94211501A09100201365
+ 884400683B00ACCF568A450058300014664BC43900D82D00304957664800B0B7
+ 00C0CE100BB200080C00305188852900047B0060C8232378008499001446F257
+ 3CF12BAE10E72A00007899B23CB9243945815B082D710757572E1E28CE49172B
+ 14366102619A402EC27999193281340FE0F3CC0000A0911511E083F3FD78CE0E
+ AECECE368EB60E5F2DEABF06FF226262E3FEE5CFAB70400000E1747ED1FE2C2F
+ B31A803B06806DFEA225EE04685E0BA075F78B66B20F40B500A0E9DA57F370F8
+ 7E3C3C45A190B9D9D9E5E4E4D84AC4425B61CA577DFE67C25FC057FD6CF97E3C
+ FCF7F5E0BEE22481325D814704F8E0C2CCF44CA51CCF92098462DCE68F47FCB7
+ 0BFFFC1DD322C44962B9582A14E35112718E449A8CF332A52289429229C525D2
+ FF64E2DF2CFB033EDF3500B06A3E017B912DA85D6303F64B27105874C0E2F700
+ 00F2BB6FC1D4280803806883E1CF77FFEF3FFD47A02500806649927100005E44
+ 242E54CAB33FC708000044A0812AB0411BF4C1182CC0061CC105DCC10BFC6036
+ 844224C4C24210420A64801C726029AC82422886CDB01D2A602FD4401D34C051
+ 688693700E2EC255B80E3D700FFA61089EC128BC81090441C808136121DA8801
+ 628A58238E08179985F821C14804128B2420C9881451224B91354831528A5420
+ 55481DF23D720239875C46BA913BC8003282FC86BC47319481B2513DD40CB543
+ B9A8371A8446A20BD06474319A8F16A09BD072B41A3D8C36A1E7D0AB680FDA8F
+ 3E43C730C0E8180733C46C302EC6C342B1382C099363CBB122AC0CABC61AB056
+ AC03BB89F563CFB17704128145C0093604774220611E4148584C584ED848A820
+ 1C243411DA093709038451C2272293A84BB426BA11F9C4186232318758482C23
+ D6128F132F107B8843C437241289433227B9900249B1A454D212D246D26E5223
+ E92CA99B34481A2393C9DA646BB20739942C202BC885E49DE4C3E433E41BE421
+ F25B0A9D624071A4F853E22852CA6A4A19E510E534E5066598324155A39A52DD
+ A8A15411358F5A42ADA1B652AF5187A81334759A39CD8316494BA5ADA295D31A
+ 681768F769AFE874BA11DD951E4E97D057D2CBE947E897E803F4770C0D861583
+ C7886728199B18071867197718AF984CA619D38B19C754303731EB98E7990F99
+ 6F55582AB62A7C1591CA0A954A9526951B2A2F54A9AAA6AADEAA0B55F355CB54
+ 8FA95E537DAE46553353E3A909D496AB55AA9D50EB531B5367A93BA887AA67A8
+ 6F543FA47E59FD890659C34CC34F43A451A0B15FE3BCC6200B6319B3782C216B
+ 0DAB86758135C426B1CDD97C762ABB98FD1DBB8B3DAAA9A13943334A3357B352
+ F394663F07E39871F89C744E09E728A797F37E8ADE14EF29E2291BA6344CB931
+ 655C6BAA96979658AB48AB51AB47EBBD36AEEDA79DA6BD45BB59FB810E41C74A
+ 275C2747678FCE059DE753D953DDA70AA7164D3D3AF5AE2EAA6BA51BA1BB4477
+ BF6EA7EE989EBE5E809E4C6FA7DE79BDE7FA1C7D2FFD54FD6DFAA7F5470C5806
+ B30C2406DB0CCE183CC535716F3C1D2FC7DBF151435DC34043A561956197E184
+ 91B9D13CA3D5468D460F8C69C65CE324E36DC66DC6A326062621264B4DEA4DEE
+ 9A524DB9A629A63B4C3B4CC7CDCCCDA2CDD699359B3D31D732E79BE79BD79BDF
+ B7605A785A2CB6A8B6B86549B2E45AA659EEB6BC6E855A3959A558555A5DB346
+ AD9DAD25D6BBADBBA711A7B94E934EAB9ED667C3B0F1B6C9B6A9B719B0E5D806
+ DBAEB66DB67D6167621767B7C5AEC3EE93BD937DBA7D8DFD3D070D87D90EAB1D
+ 5A1D7E73B472143A563ADE9ACE9CEE3F7DC5F496E92F6758CF10CFD833E3B613
+ CB29C4699D539BD347671767B97383F3888B894B82CB2E973E2E9B1BC6DDC8BD
+ E44A74F5715DE17AD2F59D9BB39BC2EDA8DBAFEE36EE69EE87DC9FCC349F299E
+ 593373D0C3C843E051E5D13F0B9F95306BDFAC7E4F434F8167B5E7232F632F91
+ 57ADD7B0B7A577AAF761EF173EF63E729FE33EE33C37DE32DE595FCC37C0B7C8
+ B7CB4FC36F9E5F85DF437F23FF64FF7AFFD100A78025016703898141815B02FB
+ F87A7C21BF8E3F3ADB65F6B2D9ED418CA0B94115418F82AD82E5C1AD2168C8EC
+ 90AD21F7E798CE91CE690E85507EE8D6D00761E6618BC37E0C2785878557863F
+ 8E7088581AD131973577D1DC4373DF44FA449644DE9B67314F39AF2D4A352A3E
+ AA2E6A3CDA37BA34BA3FC62E6659CCD5589D58496C4B1C392E2AAE366E6CBEDF
+ FCEDF387E29DE20BE37B17982FC85D7079A1CEC2F485A716A92E122C3A96404C
+ 884E3894F041102AA8168C25F21377258E0A79C21DC267222FD136D188D8435C
+ 2A1E4EF2482A4D7A92EC91BC357924C533A52CE5B98427A990BC4C0D4CDD9B3A
+ 9E169A76206D323D3ABD31839291907142AA214D93B667EA67E66676CBAC6585
+ B2FEC56E8BB72F1E9507C96BB390AC05592D0AB642A6E8545A28D72A07B26765
+ 5766BFCD89CA3996AB9E2BCDEDCCB3CADB90379CEF9FFFED12C212E192B6A586
+ 4B572D1D58E6BDAC6A39B23C7179DB0AE315052B865606AC3CB88AB62A6DD54F
+ ABED5797AE7EBD267A4D6B815EC1CA82C1B5016BEB0B550AE5857DEBDCD7ED5D
+ 4F582F59DFB561FA869D1B3E15898AAE14DB1797157FD828DC78E51B876FCABF
+ 99DC94B4A9ABC4B964CF66D266E9E6DE2D9E5B0E96AA97E6970E6E0DD9DAB40D
+ DF56B4EDF5F645DB2F97CD28DBBB83B643B9A3BF3CB8BC65A7C9CECD3B3F54A4
+ 54F454FA5436EED2DDB561D7F86ED1EE1B7BBCF634ECD5DB5BBCF7FD3EC9BEDB
+ 5501554DD566D565FB49FBB3F73FAE89AAE9F896FB6D5DAD4E6D71EDC703D203
+ FD07230EB6D7B9D4D51DD23D54528FD62BEB470EC71FBEFE9DEF772D0D360D55
+ 8D9CC6E223704479E4E9F709DFF71E0D3ADA768C7BACE107D31F761D671D2F6A
+ 429AF29A469B539AFB5B625BBA4FCC3ED1D6EADE7AFC47DB1F0F9C343C59794A
+ F354C969DAE982D39367F2CF8C9D959D7D7E2EF9DC60DBA2B67BE763CEDF6A0F
+ 6FEFBA1074E1D245FF8BE73BBC3BCE5CF2B874F2B2DBE51357B8579AAF3A5F6D
+ EA74EA3CFE93D34FC7BB9CBB9AAEB95C6BB9EE7ABDB57B66F7E91B9E37CEDDF4
+ BD79F116FFD6D59E393DDDBDF37A6FF7C5F7F5DF16DD7E7227FDCECBBBD97727
+ EEADBC4FBC5FF440ED41D943DD87D53F5BFEDCD8EFDC7F6AC077A0F3D1DC47F7
+ 068583CFFE91F58F0F43058F998FCB860D86EB9E383E3939E23F72FDE9FCA743
+ CF64CF269E17FEA2FECBAE17162F7EF8D5EBD7CED198D1A197F29793BF6D7CA5
+ FDEAC0EB19AFDBC6C2C61EBEC97833315EF456FBEDC177DC771DEFA3DF0F4FE4
+ 7C207F28FF68F9B1F553D0A7FB93199393FF040398F3FC63332DDB000009C549
+ 44415478DA9D570B5094D7153EFB7EF0581658965704410444855D23D030680D
+ AD428805634631C6689B264ECD74DA344D26D3C9A4292A1AED34613A7D68673A
+ 93345640DB8ACA43790A62001D231A890875C37B9FB00FD85DF6D9732E6068C5
+ 84E69FF9877F97FFDEF3DD73BEEF3B67397EBF5F06002EF816977FF6C207FCC0
+ 01E072B91C9FCF37FBDDDCC5E170E8A66BB12D841C7C598C0FCE2507F5F961C6
+ 3D03629118EC763B381C0E70D81DE072B920441E42A0606A6A8AFDE5F3F92010
+ 08402E978350285C6C3B310190E0836329C1BD5E2FDBD86C3607F5F6F6FEC462
+ B6C4210091D566155A262DD3098909D78D46E37AAD56CB9B99992150BE808000
+ 6FEE86DCBE8D1B37FE01B3E3C52C018FC79BDF52B2240014D4E3F13C4CDBFB47
+ DF3FD570B9E179A140083EBF0FA6A7A76164640456AE5C097A9D1E2626275876
+ 444211A8D7A961F5EAD570E0A7AF6585CAE5DDB4974C2683B9927C33005A305F
+ 5342DFD6D6B6FDF59FBD7E363030909D846ECD971AC60379881CEC0E3B389D4E
+ 569A0D1B363070898989B07BCFEE8308E45DB7DB0D4141414B0380A966279FE7
+ 8F542A858AD395C72B4F57FE325C11CEEA4BE0EA2FD7436A4A2A848785B3FAD3
+ E969DD9A356BE0CEE7774095A1F2BDF3EE3B7961A1A1AD7494057C581C00D60A
+ 060606C03C39C94EFDF06D0470BEFAFCC74D8D4D7B140A050344EFD6D6D55210
+ 080D0D6527260074D2F4F47470CE38619D7A9D6573FEE60C2CD997A496A8A8A8
+ AFCF002D6E6C68983BFD57F2914824505B5BF7AFABED578BC3C3C31900AFCF0B
+ 1DD73A20636D06FB3CAF0C7AA6F531B131F0E65B6FDE5F959696C1998BB360CF
+ C50190A42A4E57B05A2ECC80582C063C7D437777F7F7C2C2C2182002DBFB452F
+ A4A4A4009FC767C14901243D2AC7C4C4041C3B7EEC4F45C545AFC1AC632CBC16
+ 07401B9C3C7102377B0400A7B1A1B1FDC68D1B39048000D12989842B56AC60DB
+ D35ABA294309090960301A61FFFE575F2E78A6E0AFC3C3C30C2071E36B0178F0
+ 5475F5F5E0240094AEB99449F1C435B5351FFDE3EC3F5FC4DA734522113324AD
+ 410BB1D1B12CB51EB7075C6E17E343F2CA6410880490979757A052A9EAABABAB
+ 19A81776BFF0CD3E407AD66834CCCD18A8391F085728A4D7AE5E5523BBD7F4DF
+ EFDFD9D2DABAD1ED71832C58F690C06E2CA15C1E0ACB972FA74C18DFFED5DB45
+ 28D7818ABF574CA8D42A4FF1B6E279337A3C00EDB81686068700DD0D7A6EF580
+ 3252C96A2A100A20521909C343C311353535151F967FB889C7E7416C4C2C8C8C
+ 8E62C03058BB7A2D984C266BF677B21B91271359D959EDE81B3DB77B6E8F2237
+ 2C3B4B76BA29068278BC0AEA6AEB41815A4F4A4E82D6E656C8CECE86F1F17198
+ 9A9E02A53272737767E789F3E7CFC7373537B3D344474503DA30E4E4E4C08E9D
+ 3B08A00BDFB7194D46C7B265CBDA51B6F7925352EA313BD7456211646565F983
+ 838317073089FA3FF5C9697C29139627C443DB9536C8CCCC648CBEDFDFFFF33B
+ 3D3D472E5CB820B6DA6C603018180065849249502215435C5C3CE3008FCB636B
+ F47A3D58AD36282ADE3651B26B47AEE6C183DEA7729E82E8E8E84701500DC7C6
+ C6A0E6621DA8D52A06A0E36A07F9B9E4E6CD9BBFC5BA1FB872A515B45A3DD639
+ 84F9BE6BC60564CD1488144046430A898989C1F7B4C82321AC7BF249DC771CB6
+ 3F5FFCD6F6E7B61D2762A3C21E05A0D3E9989B353634013217525293A1A9A929
+ AEE7B39E13B76FDFDE4206333434C42C988212E3490944565AC7E57001BB2393
+ 266545817766661666C00AED6DEDF04C61FEA9575EF9F18BC4AD4748481A45A2
+ 40547414D4D75D6275777A3D595567CE7E14201024BB313BF7BEB8079A7FF723
+ D3DD730D8A03429463705030604D190FFA07FA41887D4219198D010BC186C1BB
+ BBAF83C56281F8F8B85B9F9CFA58856D9A7AC97F03C01483C968825569AB3003
+ CDB8B1748FAEB9A63CD2E7941B57A9818BF380116B3A643083CBE98269EC7CE6
+ 491398903333F8ECC2F493F78B44124C7F2C6CC9DF02668B15BA3A3B1F3A247A
+ 87FD771F1CDF849ED19D9B9BFBD540423AAF3E57CD1C2C353515FE7CF28FBFFE
+ FCC167EFE561870B98E2825EA104B5A91F46BC4268E109C0E21A04B9301A7C76
+ 1198274C3089249B0DE284106CCB79DFCFC393DBE0DAB54EF61D05273BE360C6
+ F47AAD75DFDEBD1F1C2A3B7CF021007AA1E6620D2E0E096969BC523E6CBCF392
+ 275407324E1280800F2EEF08240B5240333E090EB1199CBC29F05815F0DD2917
+ 4458F4501310099A491B08D1BA373DBD114821D73A3EC57E3283B276314BF7E3
+ F0A2D58D3362BEF1C62F4E1E3B76EC000380A396834CA6B9A939AEB6A6EE6F23
+ 23A3B951514A6432F56D1EF0653670FB1DE0B7CBC01EA4C1FAFB20DABA02126D
+ 3AE0E13B7D76005B5018F3FDF5EBD781C3E940C275B066469E32DBFFFD30AE1D
+ 431E98A1A4A4E46CE9C1D21F29C2154E9A62258383830E742C41E97BA52DCDCD
+ CD39D4EB674925C3B62A41B2883009B809D78B785C30E57081C2CF851CAF1EFA
+ 3181B778A13085C155EA74B46C37FA463B7A8283D937C9917A84C1A0071BAA03
+ BBE299D2D2DFEC93C982ED229158C2C1BAF1D15223AE775DFFFDC58B179F1B78
+ 30C0BC801A4D803480313B147D9D8C854629A9241019CE071FC70F765402FE01
+ 271AD0EA356934BF416B6B1B3B39A9C0472A4159EA745AB0A3833EBBB5F0CCC1
+ C387F622204708CE85CC8AD1F514BB76EE6AE9EBEB4B9BB64F831E9152BDA412
+ 2926CDCF864E1AC5E93BD23B699F864AEAF7418134DB71616D463A8825626869
+ 6A65FD22292991AD19191D63B29C98304251D10FAA0E971DDE477C1361568270
+ 1FE60338F729F7BFBABF4AA7D5255BAC16331A8B0F3921460B8DC5FF09580D45
+ 421020F389C6349A538628AD64C14FC43EC18CC66030B11932252589B88E9D74
+ 900537998C74F2AA2347CAF6E1791C344191D2E6E60C2C81DD211A1C1AF44644
+ 44C8912CD3B8A91F83F2CF9D3B977CF7EE5D3576B59CEEAE6E954EAF4BC26C89
+ 695AA2F290F3111802B12A358DD9AD103BE5F2F87874CA6130A15F188C06282C
+ 2CA83A7A148303C741F3852C440664420FE7012221DE0EB2548958C2BE259BAD
+ ACAC64A9A61B1B8E082D38A9ABAB8B0065B7B7B7AB474747D330DD812CE5892B
+ 90230ADC5C0E5E2421353322DD96822D678E1E3D82C1FD76370E2A544202B0E8
+ 4C480E26E00B586AE864980136F3CD8F5D3482D3C2B8B838282F2FE7171414C4
+ 5FBA74291D3DFE6994EF4B9111518162EC131ACD005B9F9F9F5F5576A4EC87B8
+ 9F9DCC27501AC84AB9A499707E26989F6029232855068ED2D7D383038A520997
+ 2F5F86AD5BB7C2D8E8584ED9E1B2BFE0049532E39AF1173E5B5879E8D0A19711
+ BC833C804AF6984BF27FFF385DD8B6890F6C644380F7FAFA649D9F76AAB83CAE
+ A7A46457874824F42FF80DF8B88BF5826FFDF3FC7F2EAC94C73DA70E3A327709
+ 6B84FF0180E96622F4B22C130000000049454E44AE426082}
+ Visible = False
+ end
+ object imgStateNotFound: TImage
+ Left = 4
+ Top = 4
+ Width = 32
+ Height = 32
+ AutoSize = True
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
+ 00200806000000737A7AF4000000097048597300000B1300000B1301009A9C18
+ 00000A4F6943435050686F746F73686F70204943432070726F66696C65000078
+ DA9D53675453E9163DF7DEF4424B8880944B6F5215082052428B801491262A21
+ 09104A8821A1D91551C1114545041BC8A088038E8E808C15512C0C8A0AD807E4
+ 21A28E83A3888ACAFBE17BA36BD6BCF7E6CDFEB5D73EE7ACF39DB3CF07C0080C
+ 9648335135800CA9421E11E083C7C4C6E1E42E40810A2470001008B3642173FD
+ 230100F87E3C3C2B22C007BE000178D30B0800C04D9BC0301C87FF0FEA42995C
+ 01808401C07491384B08801400407A8E42A600404601809D98265300A0040060
+ CB6362E300502D0060277FE6D300809DF8997B01005B94211501A09100201365
+ 884400683B00ACCF568A450058300014664BC43900D82D00304957664800B0B7
+ 00C0CE100BB200080C00305188852900047B0060C8232378008499001446F257
+ 3CF12BAE10E72A00007899B23CB9243945815B082D710757572E1E28CE49172B
+ 14366102619A402EC27999193281340FE0F3CC0000A0911511E083F3FD78CE0E
+ AECECE368EB60E5F2DEABF06FF226262E3FEE5CFAB70400000E1747ED1FE2C2F
+ B31A803B06806DFEA225EE04685E0BA075F78B66B20F40B500A0E9DA57F370F8
+ 7E3C3C45A190B9D9D9E5E4E4D84AC4425B61CA577DFE67C25FC057FD6CF97E3C
+ FCF7F5E0BEE22481325D814704F8E0C2CCF44CA51CCF92098462DCE68F47FCB7
+ 0BFFFC1DD322C44962B9582A14E35112718E449A8CF332A52289429229C525D2
+ FF64E2DF2CFB033EDF3500B06A3E017B912DA85D6303F64B27105874C0E2F700
+ 00F2BB6FC1D4280803806883E1CF77FFEF3FFD47A02500806649927100005E44
+ 242E54CAB33FC708000044A0812AB0411BF4C1182CC0061CC105DCC10BFC6036
+ 844224C4C24210420A64801C726029AC82422886CDB01D2A602FD4401D34C051
+ 688693700E2EC255B80E3D700FFA61089EC128BC81090441C808136121DA8801
+ 628A58238E08179985F821C14804128B2420C9881451224B91354831528A5420
+ 55481DF23D720239875C46BA913BC8003282FC86BC47319481B2513DD40CB543
+ B9A8371A8446A20BD06474319A8F16A09BD072B41A3D8C36A1E7D0AB680FDA8F
+ 3E43C730C0E8180733C46C302EC6C342B1382C099363CBB122AC0CABC61AB056
+ AC03BB89F563CFB17704128145C0093604774220611E4148584C584ED848A820
+ 1C243411DA093709038451C2272293A84BB426BA11F9C4186232318758482C23
+ D6128F132F107B8843C437241289433227B9900249B1A454D212D246D26E5223
+ E92CA99B34481A2393C9DA646BB20739942C202BC885E49DE4C3E433E41BE421
+ F25B0A9D624071A4F853E22852CA6A4A19E510E534E5066598324155A39A52DD
+ A8A15411358F5A42ADA1B652AF5187A81334759A39CD8316494BA5ADA295D31A
+ 681768F769AFE874BA11DD951E4E97D057D2CBE947E897E803F4770C0D861583
+ C7886728199B18071867197718AF984CA619D38B19C754303731EB98E7990F99
+ 6F55582AB62A7C1591CA0A954A9526951B2A2F54A9AAA6AADEAA0B55F355CB54
+ 8FA95E537DAE46553353E3A909D496AB55AA9D50EB531B5367A93BA887AA67A8
+ 6F543FA47E59FD890659C34CC34F43A451A0B15FE3BCC6200B6319B3782C216B
+ 0DAB86758135C426B1CDD97C762ABB98FD1DBB8B3DAAA9A13943334A3357B352
+ F394663F07E39871F89C744E09E728A797F37E8ADE14EF29E2291BA6344CB931
+ 655C6BAA96979658AB48AB51AB47EBBD36AEEDA79DA6BD45BB59FB810E41C74A
+ 275C2747678FCE059DE753D953DDA70AA7164D3D3AF5AE2EAA6BA51BA1BB4477
+ BF6EA7EE989EBE5E809E4C6FA7DE79BDE7FA1C7D2FFD54FD6DFAA7F5470C5806
+ B30C2406DB0CCE183CC535716F3C1D2FC7DBF151435DC34043A561956197E184
+ 91B9D13CA3D5468D460F8C69C65CE324E36DC66DC6A326062621264B4DEA4DEE
+ 9A524DB9A629A63B4C3B4CC7CDCCCDA2CDD699359B3D31D732E79BE79BD79BDF
+ B7605A785A2CB6A8B6B86549B2E45AA659EEB6BC6E855A3959A558555A5DB346
+ AD9DAD25D6BBADBBA711A7B94E934EAB9ED667C3B0F1B6C9B6A9B719B0E5D806
+ DBAEB66DB67D6167621767B7C5AEC3EE93BD937DBA7D8DFD3D070D87D90EAB1D
+ 5A1D7E73B472143A563ADE9ACE9CEE3F7DC5F496E92F6758CF10CFD833E3B613
+ CB29C4699D539BD347671767B97383F3888B894B82CB2E973E2E9B1BC6DDC8BD
+ E44A74F5715DE17AD2F59D9BB39BC2EDA8DBAFEE36EE69EE87DC9FCC349F299E
+ 593373D0C3C843E051E5D13F0B9F95306BDFAC7E4F434F8167B5E7232F632F91
+ 57ADD7B0B7A577AAF761EF173EF63E729FE33EE33C37DE32DE595FCC37C0B7C8
+ B7CB4FC36F9E5F85DF437F23FF64FF7AFFD100A78025016703898141815B02FB
+ F87A7C21BF8E3F3ADB65F6B2D9ED418CA0B94115418F82AD82E5C1AD2168C8EC
+ 90AD21F7E798CE91CE690E85507EE8D6D00761E6618BC37E0C2785878557863F
+ 8E7088581AD131973577D1DC4373DF44FA449644DE9B67314F39AF2D4A352A3E
+ AA2E6A3CDA37BA34BA3FC62E6659CCD5589D58496C4B1C392E2AAE366E6CBEDF
+ FCEDF387E29DE20BE37B17982FC85D7079A1CEC2F485A716A92E122C3A96404C
+ 884E3894F041102AA8168C25F21377258E0A79C21DC267222FD136D188D8435C
+ 2A1E4EF2482A4D7A92EC91BC357924C533A52CE5B98427A990BC4C0D4CDD9B3A
+ 9E169A76206D323D3ABD31839291907142AA214D93B667EA67E66676CBAC6585
+ B2FEC56E8BB72F1E9507C96BB390AC05592D0AB642A6E8545A28D72A07B26765
+ 5766BFCD89CA3996AB9E2BCDEDCCB3CADB90379CEF9FFFED12C212E192B6A586
+ 4B572D1D58E6BDAC6A39B23C7179DB0AE315052B865606AC3CB88AB62A6DD54F
+ ABED5797AE7EBD267A4D6B815EC1CA82C1B5016BEB0B550AE5857DEBDCD7ED5D
+ 4F582F59DFB561FA869D1B3E15898AAE14DB1797157FD828DC78E51B876FCABF
+ 99DC94B4A9ABC4B964CF66D266E9E6DE2D9E5B0E96AA97E6970E6E0DD9DAB40D
+ DF56B4EDF5F645DB2F97CD28DBBB83B643B9A3BF3CB8BC65A7C9CECD3B3F54A4
+ 54F454FA5436EED2DDB561D7F86ED1EE1B7BBCF634ECD5DB5BBCF7FD3EC9BEDB
+ 5501554DD566D565FB49FBB3F73FAE89AAE9F896FB6D5DAD4E6D71EDC703D203
+ FD07230EB6D7B9D4D51DD23D54528FD62BEB470EC71FBEFE9DEF772D0D360D55
+ 8D9CC6E223704479E4E9F709DFF71E0D3ADA768C7BACE107D31F761D671D2F6A
+ 429AF29A469B539AFB5B625BBA4FCC3ED1D6EADE7AFC47DB1F0F9C343C59794A
+ F354C969DAE982D39367F2CF8C9D959D7D7E2EF9DC60DBA2B67BE763CEDF6A0F
+ 6FEFBA1074E1D245FF8BE73BBC3BCE5CF2B874F2B2DBE51357B8579AAF3A5F6D
+ EA74EA3CFE93D34FC7BB9CBB9AAEB95C6BB9EE7ABDB57B66F7E91B9E37CEDDF4
+ BD79F116FFD6D59E393DDDBDF37A6FF7C5F7F5DF16DD7E7227FDCECBBBD97727
+ EEADBC4FBC5FF440ED41D943DD87D53F5BFEDCD8EFDC7F6AC077A0F3D1DC47F7
+ 068583CFFE91F58F0F43058F998FCB860D86EB9E383E3939E23F72FDE9FCA743
+ CF64CF269E17FEA2FECBAE17162F7EF8D5EBD7CED198D1A197F29793BF6D7CA5
+ FDEAC0EB19AFDBC6C2C61EBEC97833315EF456FBEDC177DC771DEFA3DF0F4FE4
+ 7C207F28FF68F9B1F553D0A7FB93199393FF040398F3FC63332DDB000007EF49
+ 44415478DAA557494C5459147D9FFA50C52020833289322B4A83A248DA38A431
+ 22A24C894A42ECD00BDDB831313171E1C279484C74D5B8E9EE841834B62DA0E0
+ 80A222600403E21845914150041151849AFB9C177E350A38F54F7EA07EFDF7EE
+ B9E79E73EF2BC56EB71B841016F10317D63A6E455184939393B0D96CF2B376F1
+ B9768F73A90A5E56BF070003984C26613018C4C78F1FC5D0D090FCCB6793274F
+ 96C13F7CF820FFAAAA2A9C9D9DE573171797FF0FC06AB5CA8DFBFBFBF50F1F3E
+ 5CF0EEDD3B2F00500706067478660A0F0FEFECEDED0DEEEEEE5686878709CAEE
+ EEEE6E5FB26449EFD2A54BEB00DE4E96743ADDF70160508BC5F18AEEE0C18339
+ 972E5D5A80EC6CF8CE3E3838285EBC78618F8E8EB622B8FAF6ED5BC90AB34E4C
+ 4C749A33678E69F3E6CD053E3E3E9DDCCBCBCB4B2BC9D7016835E645F4555555
+ B15BB66CC9F3F0F0B020133BB379FEFCB9FC1E542B086C67F62C0D3217040766
+ F41B366CA800904AB3D92C264D9AF46D0040EBE8CC859B9B9B3871E2C40ADCBF
+ F8FBFB0FB3BE0477F1E2453173E64CE1E7E727EBCFECB92E2E2E4EDCBB774F99
+ 3B77AE7DC78E1D7F818156EE334A0FE303A0D09E3E7D2A4825B31E0DA0A4A424
+ FBCA952B490060E467BE5B5E5E2E10442080CC980098697C7CBC001B3A946130
+ 3535B50080FB99796060E09719E0E28A8A0A99C568FBB8BABA32586E7575F54F
+ C8D6440014666D6DAD0CC6CF9A33F83FD7070707ABDBB66DEB9E3D7BF6EF5A9C
+ 517B8E0F80962A2A2A22FA4F18A0F590FDAF75757531BEBEBE660222583842CC
+ 9A354BAA9BC18D46A3B41ECBD1D7D7E772E8D0A19AACACAC724AEA9B6CC80D8E
+ 1D3B2637FB0C8072F9F2E5DF6EDFBE1D0900260262961461545494D403D7F2A6
+ 1E203E015B3A6FDAB4E9EF55AB5635767474C83DA98D2F026056172E5C180380
+ B4969595659F3E7D3A11B577D2EBF53680B0C07AA45A52CBB5BCA907D85281E0
+ 949494944268A419FA91A0F2F2F2BEDE07B829336337E3A5B901E273AEA9A909
+ 82BAFD9F3C791277EDDAB5307C67A3B7C900454900B4645858980E4C0C6CDFBE
+ BD08E5E943598700C4969D9DAD35A38901BC7AF54AB4B5B549C477EEDC110101
+ 01B2A6B4D0D4A95305E874071B6B8F1C391201905632D0D9D929A907C5CA9B37
+ 6F869393935BA09321FC6D43DFE86E6A6A1A0033C3EBD7AFB7C98EA6D34D5C82
+ F3E7CFCBCD626262446565A5C026E2E5CB97D26600107EEBD6ADACD2D2523F88
+ D2C46C828282586FB168D122B16EDD3A02B4E27D239E59A64F9FDE0EE67AB157
+ 3304DE492D2D5CB8D0EEE9E9393E00FAFFF8F1E3022F09D028AE5FBF2E929292
+ A868D1DCDC9C7CF7EEDD1567CF9ED5BF7FFFDEFCFAF56B492759A105E90C0494
+ 1AC073056B14BC23E705A8EFCBCDCDFDE3D9B3673D040AD06301B0865D5D5D14
+ 9B98376F9E0400DF0BB451B5A1A12115007E06201B4A64A5D5088AB605C58260
+ E800361A3A84656129D931E7CF9FAF605F7D4E4E4E29EEDA91F13D1600C5479A
+ 6137D9DDD86241B317749081CC63E104537B7B3B67900CAA8D668A95EBE81A64
+ 2B054C56A64C992299E433CC117D5A5A5AFDC68D1BFF898888182B42DA0E4291
+ F5A40D597704083975EA540E8204A2EB191F3D7A245A5A5A64A6DA41037614A8
+ A7BCA903B024C54AE1A6A7A7CBE0F5F5F502E3DB79C68C191D8585850518D364
+ E65300A0586E80B62919C0C6F100948EE0EEB099995943DD92256DE2B104D40C
+ FF271B7C4E4021212102FD9F410504AB7548F60EE3E1C387FF04F0AEC58B17FF
+ 07803E2F2E2EA6CF655B2D28285876FFFEFD94D8D85805F44A80DC7864F6CBA0
+ DEDEDEB26C04C1405A1BE6F3E5CB97CBCC6FDEBCE9E88EBC502227E8C2949F9F
+ 5FBD77EFDE2A0700BE70EEDC393610036C97D6DADABA00945BF0D9C6BA327068
+ 68A8B422B3A4557951686486CFC90CB5B06CD9324770ED5DEEA1BD0700EE5BB7
+ 6EADC28C28930018884D0662F3C6B4CB41438946FD8CC8D8AED559DB449BF5B4
+ 19EB4C85B32CFC8EE583DA2513748E169CEF69C1799C83151B77EFDE5D02B62D
+ 0A6CA7A2E359E05FDDCE9D3BF3917D140F1B9AA8D8FFB981D692695306A08830
+ 9024F5CC9625A16B18F0C68D1B0EA0740813A045D137F49999998DBB76ED3A83
+ BDCDF84E55B09902CF7B60C4A6A304716812161E1E596F06270866CB9B47290D
+ 9036F934F750B8BCD8B4983999D1663F4B0386F5AB57AF6EDCB367CF193C3353
+ 27B21503B91B28C97FFCF87118501B891474DAC1886D24633BB366B723287A9F
+ 83874D888078252424C80E78F5EA55392F2223232540CE06960525D267646434
+ ECDBB7AF989D9EFB8CAC5515D4C403F37A2D50FA81CE61506887265428DB93F5
+ C26727646CE50998070A7C27013133829A366D9A6CD30CC4332467072F88D811
+ 1CBDA061FFFEFD67008AECCA193332E6559E6275EC6CE858060432F3A48BA03A
+ 58D2EFC1830701D82014E50984727D10C000AFEB780EE0042418BE0FAB4ACA79
+ B375633F69CD9E9E1E47703A8DA522F5D48FE33C4011E2B6B08990465EA4EFE4
+ C993926ADED84887DAFBA2A1040250084416047AFD41B72B6E15949BA1111B75
+ 42116AC157AE5CD978E0C0817F189CCF493D018C7B26D484436A78D064532220
+ EDD8C5EFB89093EEE8D1A34EE8E9DE388E07C00161B06F02FABE1B32B340C45C
+ EFC2E0CC1CFB99B98EDA19E7E7D9C40712ADD1703119E1E184E0481FE705070D
+ 7E1D89356BD6506CA1105826EAEE0F6728A0BD096A2F0178338332F309AEEFFF
+ 713A7A6CB36CEC0F04081719D0F902A1091B5CD5CE2636EA37E01701FCF0CFF3
+ CF31F16C38E20E4656BE618DFA2FD3308F8CBFBD23FB0000000049454E44AE42
+ 6082}
+ end
+ object lblG940Throttle: TLabel
+ Left = 42
+ Top = 4
+ Width = 114
+ Height = 19
+ Caption = 'G940 Throttle'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -16
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblG940ThrottleState: TLabel
+ Left = 42
+ Top = 23
+ Width = 59
+ Height = 13
+ Caption = 'Searching...'
+ end
end
end
end
diff --git a/G940LEDControl/Forms/MainFrm.pas b/G940LEDControl/Forms/MainFrm.pas
index abed7b8..3652440 100644
--- a/G940LEDControl/Forms/MainFrm.pas
+++ b/G940LEDControl/Forms/MainFrm.pas
@@ -19,6 +19,7 @@ uses
pngimage,
X2UtPersistIntf,
+ FSXSimConnectIntf,
LEDStateConsumer,
Profile,
Settings;
@@ -27,8 +28,9 @@ uses
const
CM_ASKAUTOUPDATE = WM_APP + 1;
- MSG_UPDATE = 1;
- MSG_NOUPDATE = 2;
+ TM_UPDATE = 1;
+ TM_NOUPDATE = 2;
+ TM_FSXSTATE = 3;
LED_COUNT = 8;
@@ -95,6 +97,12 @@ type
btnSaveProfile: TButton;
btnDeleteProfile: TButton;
bvlProfiles: TBevel;
+ pnlFSX: TPanel;
+ imgFSXStateNotConnected: TImage;
+ imgFSXStateConnected: TImage;
+ lblFSX: TLabel;
+ lblFSXState: TLabel;
+ pnlState: TPanel;
procedure FormCreate(Sender: TObject);
procedure lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
@@ -103,6 +111,8 @@ type
procedure FormDestroy(Sender: TObject);
procedure cmbProfilesClick(Sender: TObject);
procedure cbCheckUpdatesClick(Sender: TObject);
+ procedure btnSaveProfileClick(Sender: TObject);
+ procedure btnDeleteProfileClick(Sender: TObject);
private
FLEDControls: array[0..LED_COUNT - 1] of TLEDControls;
FEventMonitor: TOmniEventMonitor;
@@ -110,7 +120,7 @@ type
FProfilesFilename: string;
FProfiles: TProfileList;
FActiveProfile: TProfile;
- FLoadingProfiles: Boolean;
+ FLockChangeProfile: Boolean;
FStateConsumerTask: IOmniTaskControl;
FDeviceNotification: Pointer;
@@ -118,6 +128,8 @@ type
FSettingsFileName: string;
FSettings: TSettings;
+
+ procedure SetActiveProfile(const Value: TProfile);
protected
procedure RegisterDeviceArrival;
procedure UnregisterDeviceArrival;
@@ -135,7 +147,12 @@ type
procedure LoadActiveProfile;
procedure UpdateButton(AProfile: TProfile; AButtonIndex: Integer);
+ procedure AddProfile(AProfile: TProfile);
+ procedure UpdateProfile(AProfile: TProfile);
+ procedure DeleteProfile(AProfile: TProfile; ASetActiveProfile: Boolean);
+
procedure SetDeviceState(const AMessage: string; AFound: Boolean);
+ procedure SetFSXState(const AMessage: string; AConnected: Boolean);
// procedure SetFSXToggleZoomButton(const ADeviceGUID: TGUID; AButtonIndex: Integer; const ADisplayText: string);
procedure CheckForUpdatesThread(const ATask: IOmniTask);
@@ -144,11 +161,12 @@ type
procedure EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
procedure EventMonitorTerminated(const task: IOmniTaskControl);
- procedure HandleDeviceStateMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage);
+ procedure HandleDeviceStateMessage(AMessage: TOmniMessage);
+ procedure HandleFSXStateMessage(AMessage: TOmniMessage);
procedure CMAskAutoUpdate(var Msg: TMessage); message CM_ASKAUTOUPDATE;
- property ActiveProfile: TProfile read FActiveProfile;
+ property ActiveProfile: TProfile read FActiveProfile write SetActiveProfile;
property EventMonitor: TOmniEventMonitor read FEventMonitor;
property Profiles: TProfileList read FProfiles;
property Settings: TSettings read FSettings;
@@ -158,11 +176,11 @@ type
implementation
uses
- ComObj,
- Dialogs,
- Graphics,
- ShellAPI,
- SysUtils,
+ System.SysUtils,
+ System.Win.ComObj,
+ Vcl.Dialogs,
+ Vcl.Graphics,
+ Winapi.ShellAPI,
IdException,
IdHTTP,
@@ -172,6 +190,7 @@ uses
ButtonFunctionFrm,
ConfigConversion,
+ FSXSimConnectStateMonitor,
G940LEDStateConsumer,
LEDColorIntf,
LEDFunctionIntf,
@@ -184,15 +203,31 @@ uses
const
DefaultProfileName = 'Default';
+ ProfilePostfixModified = ' (modified)';
- FILENAME_PROFILES = 'G940LEDControl\Profiles.xml';
- FILENAME_SETTINGS = 'G940LEDControl\Settings.xml';
+ FilenameProfiles = 'G940LEDControl\Profiles.xml';
+ FilenameSettings = 'G940LEDControl\Settings.xml';
- SPECIAL_CATEGORY = -1;
+ TextStateSearching = 'Searching...';
+ TextStateNotFound = 'Not found';
+ TextStateFound = 'Connected';
- TEXT_STATE_SEARCHING = 'Searching...';
- TEXT_STATE_NOTFOUND = 'Not found';
- TEXT_STATE_FOUND = 'Connected';
+ TextFSXConnected = 'Connected';
+ TextFSXDisconnected = 'Not connected';
+ TextFSXFailed = 'Failed to connect';
+
+
+
+
+type
+ TFSXStateMonitorWorker = class(TOmniWorker, IFSXSimConnectStateObserver)
+ protected
+ function Initialize: Boolean; override;
+ procedure Cleanup; override;
+
+ { IFSXSimConnectStateObserver }
+ procedure ObserverStateUpdate(ANewState: TFSXSimConnectState);
+ end;
@@ -200,7 +235,7 @@ const
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
var
- consumer: IOmniWorker;
+ worker: IOmniWorker;
begin
lblVersion.Caption := App.Version.FormatVersion(False);
@@ -209,25 +244,25 @@ begin
FEventMonitor := TOmniEventMonitor.Create(Self);
- consumer := TG940LEDStateConsumer.Create;
- FStateConsumerTask := FEventMonitor.Monitor(CreateTask(consumer)).MsgWait;
+ worker := TG940LEDStateConsumer.Create;
+ FStateConsumerTask := EventMonitor.Monitor(CreateTask(worker)).MsgWait;
EventMonitor.OnTaskMessage := EventMonitorMessage;
EventMonitor.OnTaskTerminated := EventMonitorTerminated;
StateConsumerTask.Run;
+ worker := TFSXStateMonitorWorker.Create;
+ EventMonitor.Monitor(CreateTask(worker)).Run;
+
FindLEDControls;
- FProfilesFilename := App.UserPath + FILENAME_PROFILES;
+ FProfilesFilename := App.UserPath + FilenameProfiles;
FProfiles := TProfileList.Create(True);
LoadProfiles;
- FSettingsFileName := App.UserPath + FILENAME_SETTINGS;
+ FSettingsFileName := App.UserPath + FilenameSettings;
LoadSettings;
- // #ToDo1 -oMvR: 22-2-2013: implement profile changing properly
- FStateConsumerTask.Comm.Send(TM_LOADPROFILE, ActiveProfile);
-
RegisterDeviceArrival;
end;
@@ -336,13 +371,15 @@ begin
defaultProfile := ConfigConversion.ConvertProfile0To1;
if not Assigned(defaultProfile) then
- defaultProfile := CreateDefaultProfile;
-
- if Assigned(defaultProfile) then
+ defaultProfile := CreateDefaultProfile
+ else
begin
defaultProfile.Name := DefaultProfileName;
- Profiles.Add(defaultProfile);
+ defaultProfile.IsTemporary := True;
end;
+
+ if Assigned(defaultProfile) then
+ Profiles.Add(defaultProfile);
end else
begin
persistXML := TX2UtPersistXML.Create;
@@ -354,7 +391,11 @@ begin
end;
end;
- FLoadingProfiles := True;
+ { Make sure we always have a profile }
+ if Profiles.Count = 0 then
+ Profiles.Add(CreateDefaultProfile);
+
+ FLockChangeProfile := True;
try
cmbProfiles.Items.BeginUpdate;
try
@@ -364,17 +405,9 @@ begin
cmbProfiles.Items.AddObject(profile.Name, profile);
finally
cmbProfiles.Items.EndUpdate;
-
- if cmbProfiles.Items.Count > 0 then
- begin
- cmbProfiles.ItemIndex := 0;
-
- FActiveProfile := TProfile(cmbProfiles.Items.Objects[0]);
- LoadActiveProfile;
- end;
end;
finally
- FLoadingProfiles := False;
+ FLockChangeProfile := False;
end;
end;
@@ -397,6 +430,7 @@ end;
procedure TMainForm.LoadSettings;
var
persistXML: TX2UtPersistXML;
+ profile: TProfile;
begin
if not FileExists(FSettingsFileName) then
@@ -419,6 +453,18 @@ begin
end;
end;
+ { Default profile }
+ profile := nil;
+ if Length(Settings.ActiveProfile) > 0 then
+ profile := Profiles.Find(Settings.ActiveProfile);
+
+ { LoadProfiles ensures there's always at least 1 profile }
+ if (not Assigned(profile)) and (Profiles.Count > 0) then
+ profile := Profiles[0];
+
+ SetActiveProfile(profile);
+
+ { Auto-update }
cbCheckUpdates.Checked := Settings.CheckUpdates;
if not Settings.HasCheckUpdates then
@@ -447,6 +493,8 @@ function TMainForm.CreateDefaultProfile: TProfile;
begin
{ Default button functions are assigned during UpdateButton }
Result := TProfile.Create;
+ Result.Name := DefaultProfileName;
+ Result.IsTemporary := True;
end;
@@ -460,6 +508,9 @@ begin
for buttonIndex := 0 to Pred(LED_COUNT) do
UpdateButton(ActiveProfile, buttonIndex);
+
+ if Assigned(StateConsumerTask) then
+ StateConsumerTask.Comm.Send(TM_LOADPROFILE, ActiveProfile);
end;
@@ -496,16 +547,75 @@ begin
end;
+procedure TMainForm.AddProfile(AProfile: TProfile);
+begin
+ Profiles.Add(AProfile);
+ cmbProfiles.Items.AddObject(AProfile.Name, AProfile);
+ SetActiveProfile(AProfile);
+end;
+
+
+procedure TMainForm.UpdateProfile(AProfile: TProfile);
+var
+ itemIndex: Integer;
+ oldItemIndex: Integer;
+
+begin
+ itemIndex := cmbProfiles.Items.IndexOfObject(AProfile);
+ if itemIndex > -1 then
+ begin
+ oldItemIndex := cmbProfiles.ItemIndex;
+ FLockChangeProfile := True;
+ try
+ cmbProfiles.Items[itemIndex] := AProfile.Name;
+ cmbProfiles.ItemIndex := oldItemIndex;
+ finally
+ FLockChangeProfile := False;
+ end;
+ end;
+end;
+
+
+procedure TMainForm.DeleteProfile(AProfile: TProfile; ASetActiveProfile: Boolean);
+var
+ itemIndex: Integer;
+
+begin
+ if AProfile = ActiveProfile then
+ FActiveProfile := nil;
+
+ itemIndex := cmbProfiles.Items.IndexOfObject(AProfile);
+ if itemIndex > -1 then
+ begin
+ Profiles.Remove(AProfile);
+ cmbProfiles.Items.Delete(itemIndex);
+
+ if Profiles.Count = 0 then
+ AddProfile(CreateDefaultProfile);
+
+ if ASetActiveProfile then
+ begin
+ if itemIndex >= Profiles.Count then
+ itemIndex := Pred(Profiles.Count);
+
+ FLockChangeProfile := True;
+ try
+ cmbProfiles.ItemIndex := itemIndex;
+ SetActiveProfile(TProfile(cmbProfiles.Items.Objects[itemIndex]));
+ finally
+ FLockChangeProfile := False;
+ end;
+ end;
+ end;
+end;
+
+
procedure TMainForm.cmbProfilesClick(Sender: TObject);
begin
- if not FLoadingProfiles then
+ if not FLockChangeProfile then
begin
if cmbProfiles.ItemIndex > -1 then
- FActiveProfile := TProfile(cmbProfiles.Items.Objects[cmbProfiles.ItemIndex])
- else
- FActiveProfile := nil;
-
- LoadActiveProfile;
+ SetActiveProfile(TProfile(cmbProfiles.Items.Objects[cmbProfiles.ItemIndex]));
end;
end;
@@ -525,6 +635,33 @@ begin
end;
+procedure TMainForm.SetActiveProfile(const Value: TProfile);
+begin
+ if Value <> FActiveProfile then
+ begin
+ FActiveProfile := Value;
+
+ if Assigned(ActiveProfile) then
+ begin
+ if Settings.ActiveProfile <> ActiveProfile.Name then
+ begin
+ Settings.ActiveProfile := ActiveProfile.Name;
+ SaveSettings;
+ end;
+
+ FLockChangeProfile := True;
+ try
+ cmbProfiles.ItemIndex := cmbProfiles.Items.IndexOfObject(ActiveProfile);
+ finally
+ FLockChangeProfile := False;
+ end;
+
+ LoadActiveProfile;
+ end;
+ end;
+end;
+
+
procedure TMainForm.SetDeviceState(const AMessage: string; AFound: Boolean);
begin
lblG940ThrottleState.Caption := AMessage;
@@ -537,20 +674,74 @@ begin
end;
+procedure TMainForm.SetFSXState(const AMessage: string; AConnected: Boolean);
+begin
+ lblFSXState.Caption := AMessage;
+ lblFSXState.Update;
+
+ imgFSXStateConnected.Visible := AConnected;
+ imgFSXStateNotConnected.Visible := not AConnected;
+end;
+
+
procedure TMainForm.LEDButtonClick(Sender: TObject);
+
+ function GetUniqueProfileName(const AName: string): string;
+ var
+ counter: Integer;
+
+ begin
+ Result := AName;
+ counter := 0;
+
+ while Assigned(Profiles.Find(Result)) do
+ begin
+ Inc(counter);
+ Result := Format('%s (%d)', [AName, counter]);
+ end;
+ end;
+
+
var
buttonIndex: NativeInt;
+ profile: TProfile;
+ newProfile: Boolean;
begin
if not Assigned(ActiveProfile) then
exit;
- buttonIndex := (Sender as TComponent).Tag;
- if TButtonFunctionForm.Execute(ActiveProfile, buttonIndex) then
+ { Behaviour similar to the Windows System Sounds control panel;
+ when a change occurs, create a temporary profile "(modified)"
+ so the original profile can still be selected }
+ if not ActiveProfile.IsTemporary then
begin
- UpdateButton(ActiveProfile, buttonIndex);
- FStateConsumerTask.Comm.Send(TM_LOADPROFILE, ActiveProfile);
+ profile := TProfile.Create;
+ profile.Assign(ActiveProfile);
+ profile.Name := GetUniqueProfileName(profile.Name + ProfilePostfixModified);
+ profile.IsTemporary := True;
+ newProfile := True;
+ end else
+ begin
+ profile := ActiveProfile;
+ newProfile := False;
+ end;
+
+ buttonIndex := (Sender as TComponent).Tag;
+ if TButtonFunctionForm.Execute(profile, buttonIndex) then
+ begin
+ if newProfile then
+ AddProfile(profile);
+
SaveProfiles;
+ UpdateButton(profile, buttonIndex);
+
+ if Assigned(StateConsumerTask) then
+ StateConsumerTask.Comm.Send(TM_LOADPROFILE, profile);
+ end else
+ begin
+ if newProfile then
+ FreeAndNil(profile);
end;
end;
@@ -622,11 +813,11 @@ begin
try
latestVersion := httpClient.Get('http://g940.x2software.net/version');
if VersionIsNewer(Format('%d.%d.%d', [App.Version.Major, App.Version.Minor, App.Version.Release]), latestVersion) then
- ATask.Comm.Send(MSG_UPDATE, latestVersion)
+ ATask.Comm.Send(TM_UPDATE, latestVersion)
else
begin
if ATask.Param.ByName('ReportNoUpdates').AsBoolean then
- ATask.Comm.Send(MSG_NOUPDATE, True);
+ ATask.Comm.Send(TM_NOUPDATE, True);
end;
msgSent := True;
@@ -638,7 +829,82 @@ begin
on E:Exception do
begin
if not msgSent then
- ATask.Comm.Send(MSG_NOUPDATE, False);
+ ATask.Comm.Send(TM_NOUPDATE, False);
+ end;
+ end;
+end;
+
+
+procedure TMainForm.btnSaveProfileClick(Sender: TObject);
+var
+ name: string;
+ profile: TProfile;
+ existingProfile: TProfile;
+ newProfile: TProfile;
+
+begin
+ name := '';
+ profile := ActiveProfile;
+ existingProfile := nil;
+
+ repeat
+ if InputQuery('Save profile as', 'Save this profile as:', name) then
+ begin
+ existingProfile := Profiles.Find(name);
+ if Assigned(existingProfile) then
+ begin
+ case MessageBox(Self.Handle, PChar(Format('A profile named "%s" exists, do you want to overwrite it?', [name])),
+ 'Save profile as', MB_ICONQUESTION or MB_YESNOCANCEL) of
+ ID_YES:
+ break;
+
+ ID_CANCEL:
+ exit;
+ end;
+ end else
+ break;
+ end else
+ exit;
+ until False;
+
+ if Assigned(existingProfile) then
+ begin
+ existingProfile.Assign(profile);
+ existingProfile.Name := name;
+ UpdateProfile(existingProfile);
+ SetActiveProfile(existingProfile);
+
+ if profile.IsTemporary then
+ DeleteProfile(profile, False);
+ end else
+ begin
+ if profile.IsTemporary then
+ begin
+ profile.Name := name;
+ profile.IsTemporary := False;
+ UpdateProfile(profile);
+ end else
+ begin
+ newProfile := TProfile.Create;
+ newProfile.Assign(profile);
+ newProfile.Name := name;
+ AddProfile(newProfile);
+ end;
+ end;
+
+ SaveProfiles;
+end;
+
+
+procedure TMainForm.btnDeleteProfileClick(Sender: TObject);
+begin
+ if Assigned(ActiveProfile) then
+ begin
+ if MessageBox(Self.Handle, PChar(Format('Do you want to remove the profile named "%s"?', [ActiveProfile.Name])),
+ 'Remove profile', MB_ICONQUESTION or MB_YESNO) = ID_YES then
+ begin
+ DeleteProfile(ActiveProfile, True);
+ SaveProfiles;
end;
end;
end;
@@ -666,15 +932,18 @@ procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg:
begin
case msg.MsgID of
TM_NOTIFY_DEVICESTATE:
- HandleDeviceStateMessage(task, msg);
+ HandleDeviceStateMessage(msg);
- MSG_UPDATE:
+ TM_FSXSTATE:
+ HandleFSXStateMessage(msg);
+
+ TM_UPDATE:
if MessageBox(Self.Handle, PChar('Version ' + msg.MsgData + ' is available on the G940 LED Control website.'#13#10 +
'Do you want to open the website now?'), 'Update available',
MB_YESNO or MB_ICONINFORMATION) = ID_YES then
ShellExecute(Self.Handle, 'open', PChar('http://g940.x2software.net/category/releases/'), nil, nil, SW_SHOWNORMAL);
- MSG_NOUPDATE:
+ TM_NOUPDATE:
if msg.MsgData.AsBoolean then
MessageBox(Self.Handle, 'You are using the latest version.', 'No update available', MB_OK or MB_ICONINFORMATION)
else
@@ -694,17 +963,37 @@ begin
end;
-procedure TMainForm.HandleDeviceStateMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage);
+procedure TMainForm.HandleDeviceStateMessage(AMessage: TOmniMessage);
begin
case AMessage.MsgData.AsInteger of
DEVICESTATE_SEARCHING:
- SetDeviceState(TEXT_STATE_SEARCHING, False);
+ SetDeviceState(TextStateSearching, False);
DEVICESTATE_FOUND:
- SetDeviceState(TEXT_STATE_FOUND, True);
+ SetDeviceState(TextStateFound, True);
DEVICESTATE_NOTFOUND:
- SetDeviceState(TEXT_STATE_NOTFOUND, False);
+ SetDeviceState(TextStateNotFound, False);
+ end;
+end;
+
+
+procedure TMainForm.HandleFSXStateMessage(AMessage: TOmniMessage);
+var
+ state: TFSXSimConnectState;
+
+begin
+ state := TFSXSimConnectState(AMessage.MsgData.AsInteger);
+
+ case state of
+ scsDisconnected:
+ SetFSXState(TextFSXDisconnected, False);
+
+ scsConnected:
+ SetFSXState(TextFSXConnected, True);
+
+ scsFailed:
+ SetFSXState(TextFSXFailed, False);
end;
end;
@@ -720,4 +1009,27 @@ begin
ShellExecute(Self.Handle, 'open', PChar(Link), nil, nil, SW_SHOWNORMAL);
end;
+
+{ TFSXStateMonitorWorker }
+function TFSXStateMonitorWorker.Initialize: Boolean;
+begin
+ Result := inherited Initialize;
+
+ if Result then
+ TFSXSimConnectStateMonitor.Instance.Attach(Self);
+end;
+
+
+procedure TFSXStateMonitorWorker.Cleanup;
+begin
+ TFSXSimConnectStateMonitor.Instance.Detach(Self);
+
+ inherited Cleanup;
+end;
+
+procedure TFSXStateMonitorWorker.ObserverStateUpdate(ANewState: TFSXSimConnectState);
+begin
+ Task.Comm.Send(TM_FSXSTATE, Integer(ANewState));
+end;
+
end.
diff --git a/G940LEDControl/G940LEDControl.dpr b/G940LEDControl/G940LEDControl.dpr
index 382ee4e..87b0bc9 100644
--- a/G940LEDControl/G940LEDControl.dpr
+++ b/G940LEDControl/G940LEDControl.dpr
@@ -29,7 +29,8 @@ uses
FSXLEDFunction in 'Units\FSXLEDFunction.pas',
LEDResources in 'Units\LEDResources.pas',
Settings in 'Units\Settings.pas',
- FSXLEDFunctionWorker in 'Units\FSXLEDFunctionWorker.pas';
+ FSXLEDFunctionWorker in 'Units\FSXLEDFunctionWorker.pas',
+ FSXSimConnectStateMonitor in 'Units\FSXSimConnectStateMonitor.pas';
{$R *.res}
diff --git a/G940LEDControl/G940LEDControl.dproj b/G940LEDControl/G940LEDControl.dproj
index 25ff0fd..37832db 100644
--- a/G940LEDControl/G940LEDControl.dproj
+++ b/G940LEDControl/G940LEDControl.dproj
@@ -8,7 +8,7 @@
VCL
13.4
True
- Debug
+ Release
Win32
1
Application
@@ -49,6 +49,7 @@
true
+ rtl;dbrtl;$(DCC_UsePackage)
Lib
0
Bin
@@ -81,8 +82,9 @@
RELEASE;$(DCC_Define)
- 6
- CompanyName=X²Software;FileDescription=G940 LED Control;FileVersion=0.6.0.0;InternalName=;LegalCopyright=© 2011 X²Software;LegalTrademarks=;OriginalFilename=G940LEDControl.exe;ProductName=G940 LED Control;ProductVersion=0.6;Comments=
+ 1
+ 0
+ CompanyName=X²Software;FileDescription=G940 LED Control;FileVersion=1.0.0.0;InternalName=;LegalCopyright=© 2011 X²Software;LegalTrademarks=;OriginalFilename=G940LEDControl.exe;ProductName=G940 LED Control;ProductVersion=1.0;Comments=
1033
$(BDS)\bin\default_app.manifest
@@ -144,6 +146,110 @@
+ ExpressCoreLibrary by Developer Express Inc.
+ Express Cross Platform Library by Developer Express Inc.
+ ExpressPageControl by Developer Express Inc.
+ ExpressEditors Library by Developer Express Inc.
+ ExpressBars by Developer Express Inc.
+ ExpressBars Ribbon controls by Developer Express Inc.
+ ExpressScheduler by Developer Express Inc.
+ ExpressSkins Library by Developer Express Inc.
+ ExpressPrinting System by Developer Express Inc.
+ ExpressPivotGrid by Developer Express Inc.
+ ExpressOrgChart by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper by Developer Express Inc.
+ ExpressSkins Library Painter for PageControl by Developer Express Inc.
+ ExpressSkins Library Painter for Scheduler by Developer Express Inc.
+ ExpressSkins Library Painter for Bars by Developer Express Inc.
+ ExpressSkins Library Painter for NavBar by Developer Express Inc.
+ ExpressSkins Library Painter for Ribbon by Developer Express Inc.
+ ExpressSkins Library Painter for Docking Library by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressLayoutControl by Developer Express Inc.
+ ExpressEditors FieldLink by Developer Express Inc.
+ ExpressBars DBNavigator by Developer Express Inc.
+ ExpressBars extended DB items by Developer Express Inc.
+ ExpressBars extended items by Developer Express Inc.
+ ExpressBars Tabbed MDI by Developer Express Inc.
+ ExpressLayout Control by Developer Express Inc.
+ ExpressQuantumTreeList 5 by Developer Express Inc.
+ ExpressQuantumGrid by Developer Express Inc.
+ ExpressVerticalGrid by Developer Express Inc.
+ ExpressMemData by Developer Express Inc.
+ ExpressSpellChecker 2 by Developer Express Inc.
+ ExpressSpreadSheet by Developer Express Inc.
+ ExpressDocking Library by Developer Express Inc.
+ ExpressNavBar by Developer Express Inc.
+ ExpressSkins - Black Skin by Developer Express Inc.
+ ExpressSkins - Blue Skin by Developer Express Inc.
+ ExpressSkins - Blueprint Skin by Developer Express Inc.
+ ExpressSkins - Caramel Skin by Developer Express Inc.
+ ExpressSkins - Coffee Skin by Developer Express Inc.
+ ExpressSkins - Darkroom Skin by Developer Express Inc.
+ ExpressSkins - DarkSide Skin by Developer Express Inc.
+ ExpressSkins - DevExpressDarkStyle Skin by Developer Express Inc.
+ ExpressSkins - DevExpressStyle Skin by Developer Express Inc.
+ ExpressSkins - Foggy Skin by Developer Express Inc.
+ ExpressSkins - GlassOceans Skin by Developer Express Inc.
+ ExpressSkins - HighContrast Skin by Developer Express Inc.
+ ExpressSkins - iMaginary Skin by Developer Express Inc.
+ ExpressSkins - Lilian Skin by Developer Express Inc.
+ ExpressSkins - LiquidSky Skin by Developer Express Inc.
+ ExpressSkins - LondonLiquidSky Skin by Developer Express Inc.
+ ExpressSkins - McSkin Skin by Developer Express Inc.
+ ExpressSkins - MoneyTwins Skin by Developer Express Inc.
+ ExpressSkins - Office2007Black Skin by Developer Express Inc.
+ ExpressSkins - Office2007Blue Skin by Developer Express Inc.
+ ExpressSkins - Office2007Green Skin by Developer Express Inc.
+ ExpressSkins - Office2007Pink Skin by Developer Express Inc.
+ ExpressSkins - Office2007Silver Skin by Developer Express Inc.
+ ExpressSkins - Office2010Black Skin by Developer Express Inc.
+ ExpressSkins - Office2010Blue Skin by Developer Express Inc.
+ ExpressSkins - Office2010Silver Skin by Developer Express Inc.
+ ExpressSkins - Pumpkin Skin by Developer Express Inc.
+ ExpressSkins - SevenClassic Skin by Developer Express Inc.
+ ExpressSkins - Seven Skin by Developer Express Inc.
+ ExpressSkins - Sharp Skin by Developer Express Inc.
+ ExpressSkins - SharpPlus Skin by Developer Express Inc.
+ ExpressSkins - Silver Skin by Developer Express Inc.
+ ExpressSkins - Springtime Skin by Developer Express Inc.
+ ExpressSkins - Stardust Skin by Developer Express Inc.
+ ExpressSkins - Summer2008 Skin by Developer Express Inc.
+ ExpressSkins - TheAsphaltWorld Skin by Developer Express Inc.
+ ExpressSkins - Valentine Skin by Developer Express Inc.
+ ExpressSkins - VS2010 Skin by Developer Express Inc.
+ ExpressSkins - Whiteprint Skin by Developer Express Inc.
+ ExpressSkins - Xmas2008Blue Skin by Developer Express Inc.
+ ExpressPrinting System ReportLinks (Standard) by Developer Express Inc.
+ ExpressPrinting System ContainerProducer for ExpressPageControl by Developer Express Inc.
+ ExpressDBTree by Developer Express Inc.
+ ExpressTreePrintedDataSet by Developer Express Inc.
+ ExpressDBOrgChart by Developer Express Inc.
+ ExpressFlowChart by Developer Express Inc.
+ ExpressPageControl dxBar Popup Menu by Developer Express Inc.
+ ExpressBars cxEditor item by Developer Express Inc.
+ ExpressScheduler connection to ExpressQuantumGrid by Developer Express Inc.
+ ExpressQuantumTreeList 5 dxBar Built-In Menu by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for ExpressEditors by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for PageControl Painter by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for Scheduler Painter by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for Bars Painters by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for NavBar Painter by Developer Express Inc.
+ ExpressSkins Library Uses Clause Auto Fill Helper for Ribbon Painters by Developer Express Inc.
+ ExpressPrinting System Cross Platform Library by Developer Express Inc.
+ ExpressPrinting System Extended Cross Platform Library by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressPivotGrid by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressScheduler by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressSpreadSheet by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressQuantumTreeList by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressVerticalGrid by Developer Express Inc.
+ ExpressPrinting System ReportLinks for ExpressDBOrgChart by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressDBTree by Developer Express Inc.
+ ExpressPrinting System ReportLinks for ExpressFlowChart by Developer Express Inc.
+ ExpressPrinting System ReportLink for ExpressQuantumGrid by Developer Express Inc.
+ ExpressPrinting System ReportLinks for ExpressOrgChart by Developer Express Inc.
+ ExpressPrinting System Advanced Preview Window by Developer Express Inc.
+ ExpressPrinting System Ribbon Preview Window by Developer Express Inc.
+ ExpressPivotGrid 2 connection to ExpressQuantumGrid Chart View by Developer Express Inc.
ExpressPivotGrid 2 OLAP by Developer Express Inc.
@@ -192,6 +298,7 @@
+
Cfg_2
Base
diff --git a/G940LEDControl/G940LEDControl.res b/G940LEDControl/G940LEDControl.res
index d98ff0a..b2c5061 100644
Binary files a/G940LEDControl/G940LEDControl.res and b/G940LEDControl/G940LEDControl.res differ
diff --git a/G940LEDControl/Resources/Images/FSXConnected.png b/G940LEDControl/Resources/Images/FSXConnected.png
new file mode 100644
index 0000000..d67a18e
Binary files /dev/null and b/G940LEDControl/Resources/Images/FSXConnected.png differ
diff --git a/G940LEDControl/Resources/Images/FSXDisconnected.png b/G940LEDControl/Resources/Images/FSXDisconnected.png
new file mode 100644
index 0000000..d4a892d
Binary files /dev/null and b/G940LEDControl/Resources/Images/FSXDisconnected.png differ
diff --git a/G940LEDControl/Resources/Images/Found.png b/G940LEDControl/Resources/Images/Found.png
index 0d56a57..1b53fa9 100644
Binary files a/G940LEDControl/Resources/Images/Found.png and b/G940LEDControl/Resources/Images/Found.png differ
diff --git a/G940LEDControl/Resources/Images/NotFound.png b/G940LEDControl/Resources/Images/NotFound.png
index 5b84d6c..738d1c2 100644
Binary files a/G940LEDControl/Resources/Images/NotFound.png and b/G940LEDControl/Resources/Images/NotFound.png differ
diff --git a/G940LEDControl/Units/ConfigConversion.pas b/G940LEDControl/Units/ConfigConversion.pas
index a7e6790..b86bbc8 100644
--- a/G940LEDControl/Units/ConfigConversion.pas
+++ b/G940LEDControl/Units/ConfigConversion.pas
@@ -106,20 +106,61 @@ begin
V0_FUNCTIONFSX_ENGINEANTIICE: SetButton(FSXProviderUID, FSXFunctionUIDEngineAntiIce);
V0_FUNCTIONFSX_AUTOPILOT:
begin
- { The only exception regarding states; the new default is Amber / Off }
+ { The new default is Green / Off }
SetButton(FSXProviderUID, FSXFunctionUIDAutoPilot);
AButton.SetStateColor(FSXStateUIDOn, lcGreen);
AButton.SetStateColor(FSXStateUIDOff, lcRed);
end;
- V0_FUNCTIONFSX_FUELPUMP: SetButton(FSXProviderUID, FSXFunctionUIDFuelPump);
V0_FUNCTIONFSX_TAILHOOK: SetButton(FSXProviderUID, FSXFunctionUIDTailHook);
- V0_FUNCTIONFSX_AUTOPILOT_AMBER: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilot);
- V0_FUNCTIONFSX_AUTOPILOT_HEADING: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotHeading);
- V0_FUNCTIONFSX_AUTOPILOT_APPROACH: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotApproach);
- V0_FUNCTIONFSX_AUTOPILOT_BACKCOURSE: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotBackcourse);
- V0_FUNCTIONFSX_AUTOPILOT_ALTITUDE: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotAltitude);
- V0_FUNCTIONFSX_AUTOPILOT_NAV: SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotNav);
+ V0_FUNCTIONFSX_AUTOPILOT_AMBER:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilot);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
+ V0_FUNCTIONFSX_AUTOPILOT_HEADING:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotHeading);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
+ V0_FUNCTIONFSX_AUTOPILOT_APPROACH:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotApproach);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
+ V0_FUNCTIONFSX_AUTOPILOT_BACKCOURSE:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotBackcourse);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
+ V0_FUNCTIONFSX_AUTOPILOT_ALTITUDE:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotAltitude);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
+ V0_FUNCTIONFSX_AUTOPILOT_NAV:
+ begin
+ { The new default is Green / Off }
+ SetButton(FSXProviderUID, FSXFunctionUIDAutoPilotNav);
+ AButton.SetStateColor(FSXStateUIDOn, lcAmber);
+ AButton.SetStateColor(FSXStateUIDOff, lcOff);
+ end;
+
V0_FUNCTIONFSX_TAXILIGHTS: SetButton(FSXProviderUID, FSXFunctionUIDTaxiLights);
V0_FUNCTIONFSX_RECOGNITIONLIGHTS: SetButton(FSXProviderUID, FSXFunctionUIDRecognitionLights);
V0_FUNCTIONFSX_DEICE: SetButton(FSXProviderUID, FSXFunctionUIDDeIce);
diff --git a/G940LEDControl/Units/FSXLEDFunction.pas b/G940LEDControl/Units/FSXLEDFunction.pas
index 1283ede..0206860 100644
--- a/G940LEDControl/Units/FSXLEDFunction.pas
+++ b/G940LEDControl/Units/FSXLEDFunction.pas
@@ -13,83 +13,89 @@ type
procedure RegisterStates; override;
end;
+ TCustomFSXInvertedOnOffFunction = class(TCustomFSXFunction)
+ protected
+ procedure RegisterStates; override;
+ end;
+
+ { Systems }
+ TCustomFSXSystemsFunction = class(TCustomFSXFunction)
+ protected
+ function GetCategoryName: string; override;
+ end;
+
+ TFSXBatteryMasterFunction = class(TCustomFSXOnOffFunction)
+ protected
+ function GetCategoryName: string; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXDeIceFunction = class(TCustomFSXInvertedOnOffFunction)
+ protected
+ function GetCategoryName: string; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXExitDoorFunction = class(TCustomFSXSystemsFunction)
+ protected
+ procedure RegisterStates; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXGearFunction = class(TCustomFSXSystemsFunction)
+ protected
+ procedure RegisterStates; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXParkingBrakeFunction = class(TCustomFSXInvertedOnOffFunction)
+ protected
+ function GetCategoryName: string; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXPressDumpSwitchFunction = class(TCustomFSXInvertedOnOffFunction)
+ protected
+ function GetCategoryName: string; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+ TFSXTailHookFunction = class(TCustomFSXSystemsFunction)
+ protected
+ procedure RegisterStates; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+
+ { Engines }
+ TFSXEngineAntiIceFunction = class(TCustomFSXFunction)
+ protected
+ function GetCategoryName: string; override;
+ procedure RegisterStates; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
- { Misc }
TFSXEngineFunction = class(TCustomFSXFunction)
protected
+ function GetCategoryName: string; override;
procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
- TFSXGearFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXParkingBrakeFunction = class(TCustomFSXOnOffFunction)
- protected
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXExitDoorFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXTailHookFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
+ { Control surfaces }
TFSXFlapsFunction = class(TCustomFSXFunction)
protected
+ function GetCategoryName: string; override;
procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXSpoilersFunction = class(TCustomFSXFunction)
protected
+ function GetCategoryName: string; override;
procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXBatteryMasterFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXAvionicsMasterFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXPressDumpSwitchFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXEngineAntiIceFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXFuelPumpFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- end;
-
- TFSXDeIceFunction = class(TCustomFSXFunction)
- protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
@@ -98,8 +104,8 @@ type
protected
function GetCategoryName: string; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
- function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): TCustomLEDFunctionWorker; override;
protected
function GetLightMask: Integer; virtual; abstract;
end;
@@ -143,43 +149,46 @@ type
{ Autopilot }
TCustomFSXAutoPilotFunction = class(TCustomFSXFunction)
protected
+ procedure RegisterStates; override;
function GetCategoryName: string; override;
end;
TFSXAutoPilotFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXAutoPilotHeadingFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXAutoPilotApproachFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXAutoPilotBackcourseFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXAutoPilotAltitudeFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
TFSXAutoPilotNavFunction = class(TCustomFSXAutoPilotFunction)
protected
- procedure RegisterStates; override;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
+ end;
+
+
+ { Radios }
+ TFSXAvionicsMasterFunction = class(TCustomFSXOnOffFunction)
+ protected
+ function GetCategoryName: string; override;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; override;
end;
@@ -200,21 +209,59 @@ begin
end;
-{ TFSXEngineFunction }
-procedure TFSXEngineFunction.RegisterStates;
+{ TCustomFSXInvertedOnOffFunction }
+procedure TCustomFSXInvertedOnOffFunction.RegisterStates;
begin
- RegisterState(TLEDState.Create(FSXStateUIDEngineNoEngines, FSXStateDisplayNameEngineNoEngines, lcOff));
- RegisterState(TLEDState.Create(FSXStateUIDEngineAllRunning, FSXStateDisplayNameEngineAllRunning, lcGreen));
- RegisterState(TLEDState.Create(FSXStateUIDEnginePartiallyRunning, FSXStateDisplayNameEnginePartiallyRunning, lcAmber));
- RegisterState(TLEDState.Create(FSXStateUIDEngineAllOff, FSXStateDisplayNameEngineAllOff, lcRed));
- RegisterState(TLEDState.Create(FSXStateUIDEngineFailed, FSXStateDisplayNameEngineFailed, lcFlashingRedNormal));
- RegisterState(TLEDState.Create(FSXStateUIDEngineOnFire, FSXStateDisplayNameEngineOnFire, lcFlashingRedFast));
+ RegisterState(TLEDState.Create(FSXStateUIDOn, FSXStateDisplayNameOn, lcRed));
+ RegisterState(TLEDState.Create(FSXStateUIDOff, FSXStateDisplayNameOff, lcGreen));
end;
-function TFSXEngineFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+{ TCustomFSXSystemsFunction }
+function TCustomFSXSystemsFunction.GetCategoryName: string;
begin
- Result := TFSXEngineFunctionWorker;
+ Result := FSXCategorySystems;
+end;
+
+
+{ TFSXBatteryMasterFunction }
+function TFSXBatteryMasterFunction.GetCategoryName: string;
+begin
+ Result := FSXCategorySystems;
+end;
+
+
+function TFSXBatteryMasterFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXBatteryMasterFunctionWorker;
+end;
+
+
+{ TFSXDeIceFunction }
+function TFSXDeIceFunction.GetCategoryName: string;
+begin
+ Result := FSXCategorySystems;
+end;
+
+
+function TFSXDeIceFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXDeIceFunctionWorker;
+end;
+
+
+{ TFSXExitDoorFunction }
+procedure TFSXExitDoorFunction.RegisterStates;
+begin
+ RegisterState(TLEDState.Create(FSXStateUIDExitDoorClosed, FSXStateDisplayNameExitDoorClosed, lcGreen));
+ RegisterState(TLEDState.Create(FSXStateUIDExitDoorBetween, FSXStateDisplayNameExitDoorBetween, lcAmber));
+ RegisterState(TLEDState.Create(FSXStateUIDExitDoorOpen, FSXStateDisplayNameExitDoorOpen, lcRed));
+end;
+
+
+function TFSXExitDoorFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXExitDoorFunctionWorker;
end;
@@ -230,31 +277,33 @@ begin
end;
-function TFSXGearFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXGearFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXGearFunctionWorker;
end;
{ TFSXParkingBrakeFunction }
-function TFSXParkingBrakeFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXParkingBrakeFunction.GetCategoryName: string;
+begin
+ Result := FSXCategorySystems;
+end;
+
+function TFSXParkingBrakeFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXParkingBrakeFunctionWorker;
end;
-{ TFSXExitDoorFunction }
-procedure TFSXExitDoorFunction.RegisterStates;
+{ TFSXPressDumpSwitchFunction }
+function TFSXPressDumpSwitchFunction.GetCategoryName: string;
begin
- RegisterState(TLEDState.Create(FSXStateUIDExitDoorClosed, FSXStateDisplayNameExitDoorClosed, lcGreen));
- RegisterState(TLEDState.Create(FSXStateUIDExitDoorBetween, FSXStateDisplayNameExitDoorBetween, lcAmber));
- RegisterState(TLEDState.Create(FSXStateUIDExitDoorOpen, FSXStateDisplayNameExitDoorOpen, lcRed));
+ Result := FSXCategorySystems;
end;
-
-function TFSXExitDoorFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXPressDumpSwitchFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
- Result := TFSXExitDoorFunctionWorker;
+ Result := TFSXPressDumpSwitchFunctionWorker;
end;
@@ -267,29 +316,89 @@ begin
end;
-function TFSXTailHookFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXTailHookFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXTailHookFunctionWorker;
end;
-{ TFSXFlapsFunction }
-procedure TFSXFlapsFunction.RegisterStates;
+{ TFSXEngineAntiIceFunction }
+function TFSXEngineAntiIceFunction.GetCategoryName: string;
begin
- RegisterState(TLEDState.Create(FSXStateUIDFlapsNotAvailable, FSXStateDisplayNameFlapsNotAvailable, lcOff));
- RegisterState(TLEDState.Create(FSXStateUIDFlapsRetracted, FSXStateDisplayNameFlapsRetracted, lcGreen));
- RegisterState(TLEDState.Create(FSXStateUIDFlapsBetween, FSXStateDisplayNameFlapsBetween, lcAmber));
- RegisterState(TLEDState.Create(FSXStateUIDFlapsExtended, FSXStateDisplayNameFlapsExtended, lcRed));
+ Result := FSXCategoryEngines;
end;
-function TFSXFlapsFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+procedure TFSXEngineAntiIceFunction.RegisterStates;
+begin
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAntiIceNoEngines, FSXStateDisplayNameEngineAntiIceNoEngines, lcOff));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAntiIceAll, FSXStateDisplayNameEngineAntiIceAll, lcRed));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAntiIcePartial, FSXStateDisplayNameEngineAntiIcePartial, lcAmber));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAntiIceNone, FSXStateDisplayNameEngineAntiIceNone, lcGreen));
+end;
+
+
+function TFSXEngineAntiIceFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXEngineAntiIceFunctionWorker;
+end;
+
+
+{ TFSXEngineFunction }
+function TFSXEngineFunction.GetCategoryName: string;
+begin
+ Result := FSXCategoryEngines;
+end;
+
+
+procedure TFSXEngineFunction.RegisterStates;
+begin
+ RegisterState(TLEDState.Create(FSXStateUIDEngineNoEngines, FSXStateDisplayNameEngineNoEngines, lcOff));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAllRunning, FSXStateDisplayNameEngineAllRunning, lcGreen));
+ RegisterState(TLEDState.Create(FSXStateUIDEnginePartiallyRunning, FSXStateDisplayNameEnginePartiallyRunning, lcAmber));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineAllOff, FSXStateDisplayNameEngineAllOff, lcRed));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineFailed, FSXStateDisplayNameEngineFailed, lcFlashingRedNormal));
+ RegisterState(TLEDState.Create(FSXStateUIDEngineOnFire, FSXStateDisplayNameEngineOnFire, lcFlashingRedFast));
+end;
+
+
+function TFSXEngineFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXEngineFunctionWorker;
+end;
+
+
+{ TFSXFlapsFunction }
+function TFSXFlapsFunction.GetCategoryName: string;
+begin
+ Result := FSXCategoryControlSurfaces;
+end;
+
+
+procedure TFSXFlapsFunction.RegisterStates;
+begin
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsNotAvailable, FSXStateDisplayNameFlapsNotAvailable, lcOff));
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsRetracted, FSXStateDisplayNameFlapsRetracted, lcGreen));
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsBetween, FSXStateDisplayNameFlapsBetween, lcAmber));
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsExtended, FSXStateDisplayNameFlapsExtended, lcRed));
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsSpeedExceeded, FSXStateDisplayNameFlapsSpeedExceeded, lcFlashingAmberNormal));
+ RegisterState(TLEDState.Create(FSXStateUIDFlapsDamageBySpeed, FSXStateDisplayNameFlapsDamageBySpeed, lcFlashingRedFast));
+end;
+
+
+function TFSXFlapsFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXFlapsFunctionWorker;
end;
{ TFSXSpoilersFunction }
+function TFSXSpoilersFunction.GetCategoryName: string;
+begin
+ Result := FSXCategoryControlSurfaces;
+end;
+
+
procedure TFSXSpoilersFunction.RegisterStates;
begin
RegisterState(TLEDState.Create(FSXStateUIDSpoilersNotAvailable, FSXStateDisplayNameSpoilersNotAvailable, lcOff));
@@ -299,90 +408,12 @@ begin
end;
-function TFSXSpoilersFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXSpoilersFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXSpoilersFunctionWorker;
end;
-{ TFSXBatteryMasterFunction }
-procedure TFSXBatteryMasterFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXBatteryMasterFunction.RegisterStates
-end;
-
-
-function TFSXBatteryMasterFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXBatteryMasterFunctionWorker;
-end;
-
-
-{ TFSXAvionicsMasterFunction }
-procedure TFSXAvionicsMasterFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAvionicsMasterFunction.RegisterStates
-end;
-
-
-function TFSXAvionicsMasterFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXAvionicsMasterFunctionWorker;
-end;
-
-
-{ TFSXPressDumpSwitchFunction }
-procedure TFSXPressDumpSwitchFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXPressDumpSwitchFunction.RegisterStates
-end;
-
-
-function TFSXPressDumpSwitchFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXPressDumpSwitchFunctionWorker;
-end;
-
-
-{ TFSXEngineAntiIceFunction }
-procedure TFSXEngineAntiIceFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXEngineAntiIceFunction.RegisterStates
-end;
-
-
-function TFSXEngineAntiIceFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXEngineAntiIceFunctionWorker;
-end;
-
-
-{ TFSXFuelPumpFunction }
-procedure TFSXFuelPumpFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXFuelPumpFunction.RegisterStates
-end;
-
-
-function TFSXFuelPumpFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXFuelPumpFunctionWorker;
-end;
-
-
-{ TFSXDeIceFunction }
-procedure TFSXDeIceFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXDeIceFunction.RegisterStates
-end;
-
-
-function TFSXDeIceFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
-begin
- Result := TFSXDeIceFunctionWorker;
-end;
-
-
{ TFSXLightFunction }
function TCustomFSXLightFunction.GetCategoryName: string;
begin
@@ -390,15 +421,15 @@ begin
end;
-function TCustomFSXLightFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TCustomFSXLightFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXLightStatesFunctionWorker;
end;
-function TCustomFSXLightFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker;
+function TCustomFSXLightFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string): TCustomLEDFunctionWorker;
begin
- Result := inherited DoCreateWorker(ASettings);
+ Result := inherited DoCreateWorker(ASettings, APreviousState);
(Result as TFSXLightStatesFunctionWorker).StateMask := GetLightMask;
end;
@@ -459,81 +490,66 @@ begin
end;
-{ TFSXAutoPilotFunction }
-procedure TFSXAutoPilotFunction.RegisterStates;
+procedure TCustomFSXAutoPilotFunction.RegisterStates;
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotFunction.RegisterStates
+ RegisterState(TLEDState.Create(FSXStateUIDAutoPilotNotAvailable, FSXStateDisplayNameAutoPilotNotAvailable, lcOff));
+ RegisterState(TLEDState.Create(FSXStateUIDOn, FSXStateDisplayNameOn, lcGreen));
+ RegisterState(TLEDState.Create(FSXStateUIDOff, FSXStateDisplayNameOff, lcOff));
end;
-function TFSXAutoPilotFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+{ TFSXAutoPilotFunction }
+function TFSXAutoPilotFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotFunctionWorker;
end;
{ TFSXAutoPilotHeadingFunction }
-procedure TFSXAutoPilotHeadingFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotHeadingFunction.RegisterState
-end;
-
-
-function TFSXAutoPilotHeadingFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXAutoPilotHeadingFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotHeadingFunctionWorker;
end;
{ TFSXAutoPilotApproachFunction }
-procedure TFSXAutoPilotApproachFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotApproachFunction.RegisterStates
-end;
-
-
-function TFSXAutoPilotApproachFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXAutoPilotApproachFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotApproachFunctionWorker;
end;
{ TFSXAutoPilotBackcourseFunction }
-procedure TFSXAutoPilotBackcourseFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotBackcourseFunction.RegisterStates
-end;
-
-
-function TFSXAutoPilotBackcourseFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXAutoPilotBackcourseFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotBackcourseFunctionWorker;
end;
{ TFSXAutoPilotAltitudeFunction }
-procedure TFSXAutoPilotAltitudeFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotAltitudeFunction.RegisterStates
-end;
-
-
-function TFSXAutoPilotAltitudeFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXAutoPilotAltitudeFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotAltitudeFunctionWorker;
end;
{ TFSXAutoPilotNavFunction }
-procedure TFSXAutoPilotNavFunction.RegisterStates;
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotNavFunction.RegisterStates
-end;
-
-
-function TFSXAutoPilotNavFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
+function TFSXAutoPilotNavFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
begin
Result := TFSXAutoPilotNavFunctionWorker;
end;
+
+{ TFSXAvionicsMasterFunction }
+function TFSXAvionicsMasterFunction.GetCategoryName: string;
+begin
+ Result := FSXCategoryRadios;
+end;
+
+
+function TFSXAvionicsMasterFunction.GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass;
+begin
+ Result := TFSXAvionicsMasterFunctionWorker;
+end;
+
end.
diff --git a/G940LEDControl/Units/FSXLEDFunctionProvider.pas b/G940LEDControl/Units/FSXLEDFunctionProvider.pas
index e02864f..84ea46a 100644
--- a/G940LEDControl/Units/FSXLEDFunctionProvider.pas
+++ b/G940LEDControl/Units/FSXLEDFunctionProvider.pas
@@ -41,7 +41,7 @@ type
FDisplayName: string;
FUID: string;
protected
- function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; override;
+ function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): TCustomLEDFunctionWorker; override;
property Provider: TFSXLEDFunctionProvider read FProvider;
protected
@@ -56,30 +56,23 @@ type
TCustomFSXFunctionClass = class of TCustomFSXFunction;
- TCustomFSXFunctionWorker = class(TCustomLEDFunctionWorker)
+ TCustomFSXFunctionWorker = class(TCustomLEDMultiStateFunctionWorker)
private
FDataHandler: IFSXSimConnectDataHandler;
FDefinitionID: Cardinal;
FSimConnect: IFSXSimConnect;
- FCurrentStateLock: TCriticalSection;
- FCurrentState: ILEDStateWorker;
protected
- procedure RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings); override;
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); virtual; abstract;
- procedure SetCurrentState(const AUID: string; ANotifyObservers: Boolean = True); overload; virtual;
- procedure SetCurrentState(AState: ILEDStateWorker; ANotifyObservers: Boolean = True); overload; virtual;
procedure SetSimConnect(const Value: IFSXSimConnect); virtual;
property DataHandler: IFSXSimConnectDataHandler read FDataHandler;
property DefinitionID: Cardinal read FDefinitionID;
property SimConnect: IFSXSimConnect read FSimConnect write SetSimConnect;
protected
- function GetCurrentState: ILEDStateWorker; override;
-
procedure HandleData(AData: Pointer); virtual; abstract;
public
- constructor Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings); override;
+ constructor Create(const AProviderUID, AFunctionUID: string; AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''); override;
destructor Destroy; override;
end;
@@ -129,21 +122,23 @@ end;
procedure TFSXLEDFunctionProvider.RegisterFunctions;
begin
- { Misc }
- RegisterFunction(TFSXAvionicsMasterFunction.Create( Self, FSXFunctionDisplayNameAvionicsMaster, FSXFunctionUIDAvionicsMaster));
+ { Systems }
RegisterFunction(TFSXBatteryMasterFunction.Create( Self, FSXFunctionDisplayNameBatteryMaster, FSXFunctionUIDBatteryMaster));
RegisterFunction(TFSXDeIceFunction.Create( Self, FSXFunctionDisplayNameDeIce, FSXFunctionUIDDeIce));
- RegisterFunction(TFSXEngineAntiIceFunction.Create( Self, FSXFunctionDisplayNameEngineAntiIce, FSXFunctionUIDEngineAntiIce));
- RegisterFunction(TFSXEngineFunction.Create( Self, FSXFunctionDisplayNameEngine, FSXFunctionUIDEngine));
RegisterFunction(TFSXExitDoorFunction.Create( Self, FSXFunctionDisplayNameExitDoor, FSXFunctionUIDExitDoor));
- RegisterFunction(TFSXFlapsFunction.Create( Self, FSXFunctionDisplayNameFlaps, FSXFunctionUIDFlaps));
- RegisterFunction(TFSXFuelPumpFunction.Create( Self, FSXFunctionDisplayNameFuelPump, FSXFunctionUIDFuelPump));
RegisterFunction(TFSXGearFunction.Create( Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear));
RegisterFunction(TFSXParkingBrakeFunction.Create( Self, FSXFunctionDisplayNameParkingBrake, FSXFunctionUIDParkingBrake));
RegisterFunction(TFSXPressDumpSwitchFunction.Create( Self, FSXFunctionDisplayNamePressDumpSwitch, FSXFunctionUIDPressDumpSwitch));
- RegisterFunction(TFSXSpoilersFunction.Create( Self, FSXFunctionDisplayNameSpoilers, FSXFunctionUIDSpoilers));
RegisterFunction(TFSXTailHookFunction.Create( Self, FSXFunctionDisplayNameTailHook, FSXFunctionUIDTailHook));
+ { Engines }
+ RegisterFunction(TFSXEngineAntiIceFunction.Create( Self, FSXFunctionDisplayNameEngineAntiIce, FSXFunctionUIDEngineAntiIce));
+ RegisterFunction(TFSXEngineFunction.Create( Self, FSXFunctionDisplayNameEngine, FSXFunctionUIDEngine));
+
+ { Control surfaces }
+ RegisterFunction(TFSXFlapsFunction.Create( Self, FSXFunctionDisplayNameFlaps, FSXFunctionUIDFlaps));
+ RegisterFunction(TFSXSpoilersFunction.Create( Self, FSXFunctionDisplayNameSpoilers, FSXFunctionUIDSpoilers));
+
{ Lights }
RegisterFunction(TFSXBeaconLightsFunction.Create( Self, FSXFunctionDisplayNameBeaconLights, FSXFunctionUIDBeaconLights));
RegisterFunction(TFSXInstrumentLightsFunction.Create( Self, FSXFunctionDisplayNameInstrumentLights, FSXFunctionUIDInstrumentLights));
@@ -160,6 +155,9 @@ begin
RegisterFunction(TFSXAutoPilotBackcourseFunction.Create(Self, FSXFunctionDisplayNameAutoPilotBackcourse, FSXFunctionUIDAutoPilotBackcourse));
RegisterFunction(TFSXAutoPilotHeadingFunction.Create( Self, FSXFunctionDisplayNameAutoPilotHeading, FSXFunctionUIDAutoPilotHeading));
RegisterFunction(TFSXAutoPilotNavFunction.Create( Self, FSXFunctionDisplayNameAutoPilotNav, FSXFunctionUIDAutoPilotNav));
+
+ { Radios }
+ RegisterFunction(TFSXAvionicsMasterFunction.Create( Self, FSXFunctionDisplayNameAvionicsMaster, FSXFunctionUIDAvionicsMaster));
end;
@@ -202,7 +200,7 @@ end;
{ TCustomFSXFunction }
constructor TCustomFSXFunction.Create(AProvider: TFSXLEDFunctionProvider; const ADisplayName, AUID: string);
begin
- inherited Create;
+ inherited Create(AProvider.GetUID);
FProvider := AProvider;
FDisplayName := ADisplayName;
@@ -210,9 +208,9 @@ begin
end;
-function TCustomFSXFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker;
+function TCustomFSXFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string): TCustomLEDFunctionWorker;
begin
- Result := inherited DoCreateWorker(ASettings);
+ Result := inherited DoCreateWorker(ASettings, APreviousState);
(Result as TCustomFSXFunctionWorker).SimConnect := Provider.GetSimConnect;
end;
@@ -237,23 +235,19 @@ end;
{ TCustomFSXFunctionWorker }
-constructor TCustomFSXFunctionWorker.Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings);
+constructor TCustomFSXFunctionWorker.Create(const AProviderUID, AFunctionUID: string; AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; const APreviousState: string);
begin
- FCurrentStateLock := TCriticalSection.Create;
-
{ We can't pass ourselves as the Data Handler, as it would keep a reference to
this worker from the SimConnect interface. That'd mean the worker never
gets destroyed, and SimConnect never shuts down. Hence this proxy class. }
FDataHandler := TCustomFSXFunctionWorkerDataHandler.Create(Self);
- inherited Create(AStates, ASettings);
+ inherited Create(AProviderUID, AFunctionUID, AStates, ASettings, APreviousState);
end;
destructor TCustomFSXFunctionWorker.Destroy;
begin
- FreeAndNil(FCurrentStateLock);
-
if DefinitionID <> 0 then
SimConnect.RemoveDefinition(DefinitionID, DataHandler);
@@ -261,50 +255,6 @@ begin
end;
-procedure TCustomFSXFunctionWorker.RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings);
-begin
- inherited RegisterStates(AStates, ASettings);
-
- { Make sure we have a default state }
- if States.Count > 0 then
- SetCurrentState((States[0] as ILEDStateWorker), False);
-end;
-
-
-function TCustomFSXFunctionWorker.GetCurrentState: ILEDStateWorker;
-begin
- FCurrentStateLock.Acquire;
- try
- Result := FCurrentState;
- finally
- FCurrentStateLock.Release;
- end;
-end;
-
-
-procedure TCustomFSXFunctionWorker.SetCurrentState(const AUID: string; ANotifyObservers: Boolean);
-begin
- SetCurrentState(FindState(AUID), ANotifyObservers);
-end;
-
-
-procedure TCustomFSXFunctionWorker.SetCurrentState(AState: ILEDStateWorker; ANotifyObservers: Boolean);
-begin
- FCurrentStateLock.Acquire;
- try
- if AState <> FCurrentState then
- begin
- FCurrentState := AState;
-
- if ANotifyObservers then
- NotifyObservers;
- end;
- finally
- FCurrentStateLock.Release;
- end;
-end;
-
-
procedure TCustomFSXFunctionWorker.SetSimConnect(const Value: IFSXSimConnect);
var
definition: IFSXSimConnectDefinition;
diff --git a/G940LEDControl/Units/FSXLEDFunctionWorker.pas b/G940LEDControl/Units/FSXLEDFunctionWorker.pas
index 711a298..634145a 100644
--- a/G940LEDControl/Units/FSXLEDFunctionWorker.pas
+++ b/G940LEDControl/Units/FSXLEDFunctionWorker.pas
@@ -7,8 +7,20 @@ uses
type
- { Misc }
- TFSXEngineFunctionWorker = class(TCustomFSXFunctionWorker)
+ { Systems }
+ TFSXBatteryMasterFunctionWorker = class(TCustomFSXFunctionWorker)
+ protected
+ procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
+ procedure HandleData(AData: Pointer); override;
+ end;
+
+ TFSXDeIceFunctionWorker = class(TCustomFSXFunctionWorker)
+ protected
+ procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
+ procedure HandleData(AData: Pointer); override;
+ end;
+
+ TFSXExitDoorFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
procedure HandleData(AData: Pointer); override;
@@ -26,7 +38,7 @@ type
procedure HandleData(AData: Pointer); override;
end;
- TFSXExitDoorFunctionWorker = class(TCustomFSXFunctionWorker)
+ TFSXPressDumpSwitchFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
procedure HandleData(AData: Pointer); override;
@@ -39,12 +51,26 @@ type
end;
- TFSXFlapsFunctionWorker = class(TCustomFSXFunctionWorker)
+ { Engines }
+ TFSXEngineAntiIceFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
procedure HandleData(AData: Pointer); override;
end;
+ TFSXEngineFunctionWorker = class(TCustomFSXFunctionWorker)
+ protected
+ procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
+ procedure HandleData(AData: Pointer); override;
+ end;
+
+
+ { Control surfaces }
+ TFSXFlapsFunctionWorker = class(TCustomFSXFunctionWorker)
+ protected
+ procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
+ procedure HandleData(AData: Pointer); override;
+ end;
TFSXSpoilersFunctionWorker = class(TCustomFSXFunctionWorker)
protected
@@ -53,48 +79,7 @@ type
end;
- TFSXBatteryMasterFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
- TFSXAvionicsMasterFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
- TFSXPressDumpSwitchFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
- TFSXEngineAntiIceFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
- TFSXFuelPumpFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
- TFSXDeIceFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
- end;
-
-
+ { Lights }
TFSXLightStatesFunctionWorker = class(TCustomFSXFunctionWorker)
private
FStateMask: Integer;
@@ -106,42 +91,67 @@ type
end;
- TFSXAutoPilotFunctionWorker = class(TCustomFSXFunctionWorker)
- protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
+ { Autopilot }
+ PAutoPilotData = ^TAutoPilotData;
+ TAutoPilotData = packed record
+ AutoPilotAvailable: Cardinal;
+ AutoPilotMaster: Cardinal;
+ AutoPilotHeading: Cardinal;
+ AutoPilotApproach: Cardinal;
+ AutoPilotBackcourse: Cardinal;
+ AutoPilotAltitude: Cardinal;
+ AutoPilotNav: Cardinal;
end;
- TFSXAutoPilotHeadingFunctionWorker = class(TCustomFSXFunctionWorker)
+ TCustomFSXAutoPilotFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
procedure HandleData(AData: Pointer); override;
+
+ procedure SetOnOffState(AState: Cardinal); virtual;
+ procedure HandleAutoPilotData(AData: PAutoPilotData); virtual; abstract;
end;
- TFSXAutoPilotApproachFunctionWorker = class(TCustomFSXFunctionWorker)
+ TFSXAutoPilotFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
end;
- TFSXAutoPilotBackcourseFunctionWorker = class(TCustomFSXFunctionWorker)
+ TFSXAutoPilotHeadingFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
end;
- TFSXAutoPilotAltitudeFunctionWorker = class(TCustomFSXFunctionWorker)
+ TFSXAutoPilotApproachFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
protected
- procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
- procedure HandleData(AData: Pointer); override;
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
end;
- TFSXAutoPilotNavFunctionWorker = class(TCustomFSXFunctionWorker)
+ TFSXAutoPilotBackcourseFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
+ protected
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
+ end;
+
+
+ TFSXAutoPilotAltitudeFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
+ protected
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
+ end;
+
+
+ TFSXAutoPilotNavFunctionWorker = class(TCustomFSXAutoPilotFunctionWorker)
+ protected
+ procedure HandleAutoPilotData(AData: PAutoPilotData); override;
+ end;
+
+
+ { Radios }
+ TFSXAvionicsMasterFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables(ADefinition: IFSXSimConnectDefinition); override;
procedure HandleData(AData: Pointer); override;
@@ -158,6 +168,200 @@ uses
SimConnect;
+{ TFSXBatteryMasterFunctionWorker }
+procedure TFSXBatteryMasterFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('ELECTRICAL MASTER BATTERY', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXBatteryMasterFunctionWorker.HandleData(AData: Pointer);
+begin
+ if PCardinal(AData)^ <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+{ TFSXDeIceFunctionWorker }
+procedure TFSXDeIceFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('STRUCTURAL DEICE SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXDeIceFunctionWorker.HandleData(AData: Pointer);
+begin
+ if PCardinal(AData)^ <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+{ TFSXExitDoorFunctionWorker }
+procedure TFSXExitDoorFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('CANOPY OPEN', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
+end;
+
+
+procedure TFSXExitDoorFunctionWorker.HandleData(AData: Pointer);
+begin
+ case Trunc(PDouble(AData)^) of
+ 0..5: SetCurrentState(FSXStateUIDExitDoorClosed);
+ 95..100: SetCurrentState(FSXStateUIDExitDoorOpen);
+ else SetCurrentState(FSXStateUIDExitDoorBetween);
+ end;
+end;
+
+
+{ TFSXGearFunctionWorker }
+procedure TFSXGearFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('IS GEAR RETRACTABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('GEAR TOTAL PCT EXTENDED', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
+ ADefinition.AddVariable('GEAR DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('GEAR SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXGearFunctionWorker.HandleData(AData: Pointer);
+type
+ PGearData = ^TGearData;
+ TGearData = packed record
+ IsGearRetractable: Cardinal;
+ TotalPctExtended: Double;
+ DamageBySpeed: Integer;
+ SpeedExceeded: Integer;
+ end;
+
+var
+ gearData: PGearData;
+
+begin
+ gearData := AData;
+
+ if gearData^.DamageBySpeed <> 0 then
+ SetCurrentState(FSXStateUIDGearDamageBySpeed)
+
+ else if gearData^.SpeedExceeded <> 0 then
+ SetCurrentState(FSXStateUIDGearSpeedExceeded)
+
+ else if gearData^.IsGearRetractable <> 0 then
+ begin
+ case Trunc(gearData ^.TotalPctExtended * 100) of
+ 0: SetCurrentState(FSXStateUIDGearRetracted);
+ 95..100: SetCurrentState(FSXStateUIDGearExtended);
+ else SetCurrentState(FSXStateUIDGearBetween);
+ end;
+ end else
+ SetCurrentState(FSXStateUIDGearNotRetractable);
+end;
+
+
+{ TFSXParkingBrakeFunctionWorker }
+procedure TFSXParkingBrakeFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('BRAKE PARKING INDICATOR', FSX_UNIT_BOOL, SIMCONNECT_DATATYPE_INT32);
+end;
+
+
+procedure TFSXParkingBrakeFunctionWorker.HandleData(AData: Pointer);
+begin
+ if PCardinal(AData)^ <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+{ TFSXPressDumpSwitchFunctionWorker }
+procedure TFSXPressDumpSwitchFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('PRESSURIZATION DUMP SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXPressDumpSwitchFunctionWorker.HandleData(AData: Pointer);
+begin
+ if PCardinal(AData)^ <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+{ TFSXTailHookFunctionWorker }
+procedure TFSXTailHookFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+begin
+ ADefinition.AddVariable('TAILHOOK POSITION', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
+end;
+
+
+procedure TFSXTailHookFunctionWorker.HandleData(AData: Pointer);
+begin
+ case Trunc(PDouble(AData)^) of
+ 0..5: SetCurrentState(FSXStateUIDTailHookRetracted);
+ 95..100: SetCurrentState(FSXStateUIDTailHookBetween);
+ else SetCurrentState(FSXStateUIDTailHookExtended);
+ end;
+end;
+
+
+{ TFSXEngineAntiIceFunctionWorker }
+procedure TFSXEngineAntiIceFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+var
+ engineIndex: Integer;
+
+begin
+ ADefinition.AddVariable('NUMBER OF ENGINES', FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32);
+
+ for engineIndex := 1 to FSX_MAX_ENGINES do
+ ADefinition.AddVariable(Format('ENG ANTI ICE:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXEngineAntiIceFunctionWorker.HandleData(AData: Pointer);
+type
+ PAntiIceData = ^TAntiIceData;
+ TAntiIceData = packed record
+ NumberOfEngines: Integer;
+ EngineAntiIce: array[1..FSX_MAX_ENGINES] of Integer;
+ end;
+
+var
+ antiIceData: PAntiIceData;
+ engineCount: Integer;
+ antiIceCount: Integer;
+ engineIndex: Integer;
+
+begin
+ antiIceData := AData;
+ engineCount := Min(antiIceData^.NumberOfEngines, FSX_MAX_ENGINES);
+ antiIceCount := 0;
+
+ for engineIndex := 1 to engineCount do
+ begin
+ if antiIceData^.EngineAntiIce[engineIndex] <> 0 then
+ Inc(antiIceCount);
+ end;
+
+ if engineCount > 0 then
+ begin
+ if antiIceCount = 0 then
+ SetCurrentState(FSXStateUIDEngineAntiIceNone)
+ else if antiIceCount = engineCount then
+ SetCurrentState(FSXStateUIDEngineAntiIceAll)
+ else
+ SetCurrentState(FSXStateUIDEngineAntiIcePartial);
+ end else
+ SetCurrentState(FSXStateUIDEngineAntiIceNoEngines);
+end;
+
+
+
{ TFSXEngineFunctionWorker }
procedure TFSXEngineFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
var
@@ -236,105 +440,13 @@ begin
end;
-{ TFSXGearFunctionWorker }
-procedure TFSXGearFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- ADefinition.AddVariable('IS GEAR RETRACTABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
- ADefinition.AddVariable('GEAR TOTAL PCT EXTENDED', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
- ADefinition.AddVariable('GEAR DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
- ADefinition.AddVariable('GEAR SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
-end;
-
-
-procedure TFSXGearFunctionWorker.HandleData(AData: Pointer);
-type
- PGearData = ^TGearData;
- TGearData = packed record
- IsGearRetractable: Cardinal;
- TotalPctExtended: Double;
- DamageBySpeed: Integer;
- SpeedExceeded: Integer;
- end;
-
-var
- gearData: PGearData;
-
-begin
- gearData := AData;
-
- if gearData^.DamageBySpeed <> 0 then
- SetCurrentState(FSXStateUIDGearDamageBySpeed)
-
- else if gearData^.SpeedExceeded <> 0 then
- SetCurrentState(FSXStateUIDGearSpeedExceeded)
-
- else if gearData^.IsGearRetractable <> 0 then
- begin
- case Trunc(gearData ^.TotalPctExtended * 100) of
- 0: SetCurrentState(FSXStateUIDGearRetracted);
- 95..100: SetCurrentState(FSXStateUIDGearExtended);
- else SetCurrentState(FSXStateUIDGearBetween);
- end;
- end else
- SetCurrentState(FSXStateUIDGearNotRetractable);
-end;
-
-
-{ TFSXParkingBrakeFunctionWorker }
-procedure TFSXParkingBrakeFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- ADefinition.AddVariable('BRAKE PARKING INDICATOR', FSX_UNIT_BOOL, SIMCONNECT_DATATYPE_INT32);
-end;
-
-
-procedure TFSXParkingBrakeFunctionWorker.HandleData(AData: Pointer);
-begin
- if PCardinal(AData)^ <> 0 then
- SetCurrentState(FSXStateUIDOn)
- else
- SetCurrentState(FSXStateUIDOff);
-end;
-
-
-{ TFSXExitDoorFunctionWorker }
-procedure TFSXExitDoorFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- ADefinition.AddVariable('CANOPY OPEN', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
-end;
-
-
-procedure TFSXExitDoorFunctionWorker.HandleData(AData: Pointer);
-begin
- case Trunc(PDouble(AData)^) of
- 0..5: SetCurrentState(FSXStateUIDExitDoorClosed);
- 95..100: SetCurrentState(FSXStateUIDExitDoorOpen);
- else SetCurrentState(FSXStateUIDExitDoorBetween);
- end;
-end;
-
-
-{ TFSXTailHookFunctionWorker }
-procedure TFSXTailHookFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- ADefinition.AddVariable('TAILHOOK POSITION', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
-end;
-
-
-procedure TFSXTailHookFunctionWorker.HandleData(AData: Pointer);
-begin
- case Trunc(PDouble(AData)^) of
- 0..5: SetCurrentState(FSXStateUIDTailHookRetracted);
- 95..100: SetCurrentState(FSXStateUIDTailHookBetween);
- else SetCurrentState(FSXStateUIDTailHookExtended);
- end;
-end;
-
-
{ TFSXFlapsFunctionWorker }
procedure TFSXFlapsFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
begin
ADefinition.AddVariable('FLAPS AVAILABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
ADefinition.AddVariable('FLAPS HANDLE PERCENT', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
+ ADefinition.AddVariable('FLAP DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('FLAP SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
end;
@@ -344,6 +456,8 @@ type
TFlapsData = packed record
FlapsAvailable: Cardinal;
FlapsHandlePercent: Double;
+ DamageBySpeed: Integer;
+ SpeedExceeded: Integer;
end;
var
@@ -354,11 +468,16 @@ begin
if flapsData^.FlapsAvailable <> 0 then
begin
- case Trunc(flapsData^.FlapsHandlePercent) of
- 0..5: SetCurrentState(FSXStateUIDFlapsRetracted);
- 95..100: SetCurrentState(FSXStateUIDFlapsExtended);
- else SetCurrentState(FSXStateUIDFlapsBetween);
- end;
+ if flapsData^.DamageBySpeed <> 0 then
+ SetCurrentState(FSXStateUIDFlapsDamageBySpeed)
+ else if flapsData^.SpeedExceeded <> 0 then
+ SetCurrentState(FSXStateUIDFlapsSpeedExceeded)
+ else
+ case Trunc(flapsData^.FlapsHandlePercent) of
+ 0..5: SetCurrentState(FSXStateUIDFlapsRetracted);
+ 95..100: SetCurrentState(FSXStateUIDFlapsExtended);
+ else SetCurrentState(FSXStateUIDFlapsBetween);
+ end;
end else
SetCurrentState(FSXStateUIDFlapsNotAvailable);
end;
@@ -398,84 +517,6 @@ begin
end;
-{ TFSXBatteryMasterFunctionWorker }
-procedure TFSXBatteryMasterFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXBatteryMasterFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXBatteryMasterFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXBatteryMasterFunctionWorker.HandleData
-end;
-
-
-{ TFSXAvionicsMasterFunctionWorker }
-procedure TFSXAvionicsMasterFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAvionicsMasterFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXAvionicsMasterFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAvionicsMasterFunctionWorker.HandleData
-end;
-
-
-{ TFSXPressDumpSwitchFunctionWorker }
-procedure TFSXPressDumpSwitchFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXPressDumpSwitchFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXPressDumpSwitchFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXPressDumpSwitchFunctionWorker.HandleData
-end;
-
-
-{ TFSXEngineAntiIceFunctionWorker }
-procedure TFSXEngineAntiIceFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXEngineAntiIceFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXEngineAntiIceFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXEngineAntiIceFunctionWorker.HandleData
-end;
-
-
-{ TFSXFuelPumpFunctionWorker }
-procedure TFSXFuelPumpFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXFuelPumpFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXFuelPumpFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXFuelPumpFunctionWorker.HandleData
-end;
-
-
-{ TFSXDeIceFunctionWorker }
-procedure TFSXDeIceFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXDeIceFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXDeIceFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXDeIceFunctionWorker.HandleData
-end;
-
-
{ TFSXLightStatesFunctionWorker }
procedure TFSXLightStatesFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
begin
@@ -492,81 +533,97 @@ begin
end;
-{ TFSXAutoPilotFunctionWorker }
-procedure TFSXAutoPilotFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+{ TCustomFSXAutoPilotFunctionWorker }
+procedure TCustomFSXAutoPilotFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotFunctionWorker.RegisterVariables
+ ADefinition.AddVariable('AUTOPILOT AVAILABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT MASTER', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT HEADING LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT APPROACH HOLD', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT BACKCOURSE HOLD', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT ALTITUDE LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+ ADefinition.AddVariable('AUTOPILOT NAV1 LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
end;
-procedure TFSXAutoPilotFunctionWorker.HandleData(AData: Pointer);
+procedure TCustomFSXAutoPilotFunctionWorker.HandleData(AData: Pointer);
+var
+ autoPilotData: PAutoPilotData;
+
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotFunctionWorker.HandleData
+ autoPilotData := AData;
+
+ if autoPilotData^.AutoPilotAvailable <> 0 then
+ HandleAutoPilotData(autoPilotData)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+procedure TCustomFSXAutoPilotFunctionWorker.SetOnOffState(AState: Cardinal);
+begin
+ if AState <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
+end;
+
+
+{ TFSXAutoPilotFunctionWorker }
+procedure TFSXAutoPilotFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
+begin
+ SetOnOffState(AData^.AutoPilotMaster);
end;
{ TFSXAutoPilotHeadingFunctionWorker }
-procedure TFSXAutoPilotHeadingFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+procedure TFSXAutoPilotHeadingFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotHeadingFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXAutoPilotHeadingFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotHeadingFunctionWorker.HandleData
+ SetOnOffState(AData^.AutoPilotHeading);
end;
{ TFSXAutoPilotApproachFunctionWorker }
-procedure TFSXAutoPilotApproachFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+procedure TFSXAutoPilotApproachFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotApproachFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXAutoPilotApproachFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotApproachFunctionWorker.HandleData
+ SetOnOffState(AData^.AutoPilotApproach);
end;
{ TFSXAutoPilotBackcourseFunctionWorker }
-procedure TFSXAutoPilotBackcourseFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+procedure TFSXAutoPilotBackcourseFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotBackcourseFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXAutoPilotBackcourseFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotBackcourseFunctionWorker.HandleData
+ SetOnOffState(AData^.AutoPilotBackcourse);
end;
{ TFSXAutoPilotAltitudeFunctionWorker }
-procedure TFSXAutoPilotAltitudeFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+procedure TFSXAutoPilotAltitudeFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotAltitudeFunctionWorker.RegisterVariables
-end;
-
-
-procedure TFSXAutoPilotAltitudeFunctionWorker.HandleData(AData: Pointer);
-begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotAltitudeFunctionWorker.HandleData
+ SetOnOffState(AData^.AutoPilotAltitude);
end;
{ TFSXAutoPilotNavFunctionWorker }
-procedure TFSXAutoPilotNavFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
+procedure TFSXAutoPilotNavFunctionWorker.HandleAutoPilotData(AData: PAutoPilotData);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotNavFunctionWorker.RegisterVariables
+ SetOnOffState(AData^.AutoPilotNav);
end;
-procedure TFSXAutoPilotNavFunctionWorker.HandleData(AData: Pointer);
+{ TFSXAvionicsMasterFunctionWorker }
+procedure TFSXAvionicsMasterFunctionWorker.RegisterVariables(ADefinition: IFSXSimConnectDefinition);
begin
- // #ToDo1 -cEmpty -oMvR: 22-2-2013: TFSXAutoPilotNavFunctionWorker.HandleData
+ ADefinition.AddVariable('AVIONICS MASTER SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
+end;
+
+
+procedure TFSXAvionicsMasterFunctionWorker.HandleData(AData: Pointer);
+begin
+ if PCardinal(AData)^ <> 0 then
+ SetCurrentState(FSXStateUIDOn)
+ else
+ SetCurrentState(FSXStateUIDOff);
end;
end.
diff --git a/G940LEDControl/Units/FSXResources.pas b/G940LEDControl/Units/FSXResources.pas
index 1e9a7c7..04eed5d 100644
--- a/G940LEDControl/Units/FSXResources.pas
+++ b/G940LEDControl/Units/FSXResources.pas
@@ -6,8 +6,12 @@ const
FSXProviderUID = 'fsx';
FSXCategory = 'Flight Simulator X';
+ FSXCategorySystems = FSXCategory + ' - Systems';
+ FSXCategoryEngines = FSXCategory + ' - Engines';
+ FSXCategoryControlSurfaces = FSXCategory + ' - Control surfaces';
FSXCategoryLights = FSXCategory + ' - Lights';
FSXCategoryAutoPilot = FSXCategory + ' - Autopilot';
+ FSXCategoryRadios = FSXCategory + ' - Radios';
FSXStateUIDOn = 'on';
FSXStateUIDOff = 'off';
@@ -73,9 +77,11 @@ const
FSXFunctionUIDRecognitionLights = 'recognitionLights';
FSXFunctionDisplayNameRecognitionLights = 'Recognition lights';
+
FSXFunctionUIDParkingBrake = 'parkingBrake';
FSXFunctionDisplayNameParkingBrake = 'Parking brake';
+
FSXFunctionUIDExitDoor = 'exitDoor';
FSXFunctionDisplayNameExitDoor = 'Exit door';
@@ -87,6 +93,7 @@ const
FSXStateDisplayNameExitDoorBetween = 'Opening / closing';
FSXStateDisplayNameExitDoorOpen = 'Open';
+
FSXFunctionUIDTailHook = 'tailHook';
FSXFunctionDisplayNameTailHook = 'Tail hook';
@@ -106,11 +113,15 @@ const
FSXStateUIDFlapsRetracted = 'retracted';
FSXStateUIDFlapsBetween = 'between';
FSXStateUIDFlapsExtended = 'extended';
+ FSXStateUIDFlapsSpeedExceeded = 'speedExceeded';
+ FSXStateUIDFlapsDamageBySpeed = 'damageBySpeed';
FSXStateDisplayNameFlapsNotAvailable = 'No flaps';
FSXStateDisplayNameFlapsRetracted = 'Retracted';
FSXStateDisplayNameFlapsBetween = 'Extending / retracting';
FSXStateDisplayNameFlapsExtended = 'Extended';
+ FSXStateDisplayNameFlapsSpeedExceeded = 'Speed exceeded';
+ FSXStateDisplayNameFlapsDamageBySpeed = 'Damage by speed';
FSXFunctionUIDSpoilers = 'spoilers';
@@ -130,21 +141,35 @@ const
FSXFunctionUIDBatteryMaster = 'batteryMaster';
FSXFunctionDisplayNameBatteryMaster = 'Battery master';
+
FSXFunctionUIDAvionicsMaster = 'avionicsMaster';
FSXFunctionDisplayNameAvionicsMaster = 'Avionics master';
+
FSXFunctionUIDPressDumpSwitch = 'pressurizationDumpSwitch';
FSXFunctionDisplayNamePressDumpSwitch = 'Pressurization dump switch';
FSXFunctionUIDEngineAntiIce = 'engineAntiIce';
FSXFunctionDisplayNameEngineAntiIce = 'Engine anti-ice';
- FSXFunctionUIDFuelPump = 'fuelPump';
- FSXFunctionDisplayNameFuelPump = 'Fuel pump';
+ FSXStateUIDEngineAntiIceNoEngines = 'noEngines';
+ FSXStateUIDEngineAntiIceAll = 'all';
+ FSXStateUIDEngineAntiIcePartial = 'partial';
+ FSXStateUIDEngineAntiIceNone = 'none';
+
+ FSXStateDisplayNameEngineAntiIceNoEngines = 'No engines';
+ FSXStateDisplayNameEngineAntiIceAll = 'All';
+ FSXStateDisplayNameEngineAntiIcePartial = 'Partial';
+ FSXStateDisplayNameEngineAntiIceNone = 'None';
+
FSXFunctionUIDDeIce = 'structuralDeIce';
FSXFunctionDisplayNameDeIce = 'De-ice';
+
+ FSXStateUIDAutoPilotNotAvailable = 'notAvailable';
+ FSXStateDisplayNameAutoPilotNotAvailable = 'Not available';
+
FSXFunctionUIDAutoPilot = 'autoPilotMaster';
FSXFunctionDisplayNameAutoPilot = 'Autopilot master';
diff --git a/G940LEDControl/Units/FSXSimConnectClient.pas b/G940LEDControl/Units/FSXSimConnectClient.pas
index bfd34e7..25043a0 100644
--- a/G940LEDControl/Units/FSXSimConnectClient.pas
+++ b/G940LEDControl/Units/FSXSimConnectClient.pas
@@ -43,7 +43,8 @@ uses
OtlCommon,
SimConnect,
- FSXResources;
+ FSXResources,
+ FSXSimConnectStateMonitor;
const
@@ -68,7 +69,7 @@ type
destructor Destroy; override;
procedure Attach(ADataHandler: IFSXSimConnectDataHandler);
- procedure Detach(ADataHandler: IFSXSimConnectDataHandler);
+ function Detach(ADataHandler: IFSXSimConnectDataHandler): Integer;
procedure HandleData(AData: Pointer);
@@ -76,7 +77,10 @@ type
end;
- TFSXSimConnectDefinitionMap = TDictionary;
+ TFSXSimConnectDefinitionMap = class(TObjectDictionary)
+ public
+ constructor Create(ACapacity: Integer = 0); reintroduce;
+ end;
TFSXSimConnectClient = class(TOmniWorker)
private
@@ -98,6 +102,8 @@ type
procedure RegisterDefinitions;
procedure RegisterDefinition(ADefinitionID: Cardinal; ADefinition: IFSXSimConnectDefinitionAccess);
+ procedure UpdateDefinition(ADefinitionID: Cardinal);
+ procedure UnregisterDefinition(ADefinitionID: Cardinal);
function SameDefinition(ADefinition1, ADefinition2: IFSXSimConnectDefinitionAccess): Boolean;
@@ -306,13 +312,13 @@ end;
procedure TFSXSimConnectClient.Cleanup;
begin
- // #ToDo1 -oMvR: 22-2-2013: unregister definitions
+ FreeAndNil(FSimConnectDataEvent);
+ FreeAndNil(FDefinitions);
if SimConnectHandle <> 0 then
SimConnect_Close(SimConnectHandle);
- FreeAndNil(FSimConnectDataEvent);
- FreeAndNil(FDefinitions);
+ TFSXSimConnectStateMonitor.SetCurrentState(scsDisconnected);
inherited Cleanup;
end;
@@ -327,13 +333,19 @@ begin
begin
if SimConnect_Open(FSimConnectHandle, FSXSimConnectAppName, 0, 0, SimConnectDataEvent.Handle, 0) = S_OK then
begin
+ TFSXSimConnectStateMonitor.SetCurrentState(scsConnected);
+
Task.ClearTimer(TIMER_TRYSIMCONNECT);
RegisterDefinitions;
end;
end;
if SimConnectHandle = 0 then
+ begin
+ TFSXSimConnectStateMonitor.SetCurrentState(scsFailed);
+
Task.SetTimer(TIMER_TRYSIMCONNECT, INTERVAL_TRYSIMCONNECT, TM_TRYSIMCONNECT);
+ end;
end;
@@ -364,6 +376,8 @@ begin
begin
FSimConnectHandle := 0;
Task.SetTimer(TIMER_TRYSIMCONNECT, INTERVAL_TRYSIMCONNECT, TM_TRYSIMCONNECT);
+
+ TFSXSimConnectStateMonitor.SetCurrentState(scsDisconnected);
end;
end;
end;
@@ -409,6 +423,25 @@ begin
end;
+procedure TFSXSimConnectClient.UpdateDefinition(ADefinitionID: Cardinal);
+begin
+ if SimConnectHandle <> 0 then
+ { One-time data update; the RequestID is counted backwards to avoid conflicts with
+ the FLAG_CHANGED request which is still active }
+ SimConnect_RequestDataOnSimObject(SimConnectHandle, High(Cardinal) - ADefinitionID, ADefinitionID,
+ SIMCONNECT_OBJECT_ID_USER,
+ SIMCONNECT_PERIOD_SIM_FRAME,
+ 0, 0, 0, 1);
+end;
+
+
+procedure TFSXSimConnectClient.UnregisterDefinition(ADefinitionID: Cardinal);
+begin
+ if SimConnectHandle <> 0 then
+ SimConnect_ClearDataDefinition(SimConnectHandle, ADefinitionID);
+end;
+
+
function TFSXSimConnectClient.SameDefinition(ADefinition1, ADefinition2: IFSXSimConnectDefinitionAccess): Boolean;
var
variableIndex: Integer;
@@ -463,6 +496,10 @@ begin
begin
definitionRef.Attach(addDefinition.DataHandler);
addDefinition.DefinitionID := definitionID;
+
+ { Request an update on the definition to update the new worker }
+ UpdateDefinition(definitionID);
+
hasDefinition := True;
break;
end;
@@ -488,11 +525,22 @@ end;
procedure TFSXSimConnectClient.TMRemoveDefinition(var Msg: TOmniMessage);
var
removeDefinition: TRemoveDefinitionValue;
+ definitionRef: TFSXSimConnectDefinitionRef;
begin
removeDefinition := Msg.MsgData;
- // #ToDo1 -oMvR: 22-2-2013: actually remove the definition
+ if Definitions.ContainsKey(removeDefinition.DefinitionID) then
+ begin
+ definitionRef := Definitions[removeDefinition.DefinitionID];
+ if definitionRef.Detach(removeDefinition.DataHandler) = 0 then
+ begin
+ { Unregister with SimConnect }
+ UnregisterDefinition(removeDefinition.DefinitionID);
+
+ Definitions.Remove(removeDefinition.DefinitionID);
+ end;
+ end;
removeDefinition.Signal;
end;
@@ -538,9 +586,17 @@ begin
end;
-procedure TFSXSimConnectDefinitionRef.Detach(ADataHandler: IFSXSimConnectDataHandler);
+function TFSXSimConnectDefinitionRef.Detach(ADataHandler: IFSXSimConnectDataHandler): Integer;
begin
DataHandlers.Remove(ADataHandler as IFSXSimConnectDataHandler);
+ Result := DataHandlers.Count;
+end;
+
+
+{ TFSXSimConnectDefinitionMap }
+constructor TFSXSimConnectDefinitionMap.Create(ACapacity: Integer);
+begin
+ inherited Create([doOwnsValues], ACapacity);
end;
diff --git a/G940LEDControl/Units/FSXSimConnectIntf.pas b/G940LEDControl/Units/FSXSimConnectIntf.pas
index 8b9bae5..5f235a9 100644
--- a/G940LEDControl/Units/FSXSimConnectIntf.pas
+++ b/G940LEDControl/Units/FSXSimConnectIntf.pas
@@ -55,6 +55,14 @@ type
end;
+ TFSXSimConnectState = (scsDisconnected, scsConnected, scsFailed);
+
+ IFSXSimConnectStateObserver = interface
+ ['{0508904F-8189-479D-AF70-E98B00C9D9B2}']
+ procedure ObserverStateUpdate(ANewState: TFSXSimConnectState);
+ end;
+
+
const
FSX_UNIT_PERCENT = 'percent';
FSX_UNIT_MASK = 'mask';
diff --git a/G940LEDControl/Units/FSXSimConnectStateMonitor.pas b/G940LEDControl/Units/FSXSimConnectStateMonitor.pas
new file mode 100644
index 0000000..60e9aa4
--- /dev/null
+++ b/G940LEDControl/Units/FSXSimConnectStateMonitor.pas
@@ -0,0 +1,114 @@
+unit FSXSimConnectStateMonitor;
+
+interface
+uses
+ System.Classes,
+ System.SyncObjs,
+
+ FSXSimConnectIntf;
+
+
+type
+ TFSXSimConnectStateMonitor = class(TObject)
+ private
+ FObservers: TInterfaceList;
+ FCurrentStateLock: TCriticalSection;
+ FCurrentState: TFSXSimConnectState;
+
+ procedure DoSetCurrentState(const Value: TFSXSimConnectState);
+ protected
+ property CurrentStateLock: TCriticalSection read FCurrentStateLock;
+ property Observers: TInterfaceList read FObservers;
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ class function Instance: TFSXSimConnectStateMonitor;
+ class procedure SetCurrentState(AState: TFSXSimConnectState);
+
+ procedure Attach(AObserver: IFSXSimConnectStateObserver);
+ procedure Detach(AObserver: IFSXSimConnectStateObserver);
+
+ property CurrentState: TFSXSimConnectState read FCurrentState write DoSetCurrentState;
+ end;
+
+
+implementation
+uses
+ System.SysUtils;
+
+
+var
+ FSXSimConnectStateInstance: TFSXSimConnectStateMonitor;
+
+
+{ TFSXSimConnectState }
+class function TFSXSimConnectStateMonitor.Instance: TFSXSimConnectStateMonitor;
+begin
+ Result := FSXSimConnectStateInstance;
+end;
+
+
+class procedure TFSXSimConnectStateMonitor.SetCurrentState(AState: TFSXSimConnectState);
+begin
+ Instance.DoSetCurrentState(AState);
+end;
+
+
+constructor TFSXSimConnectStateMonitor.Create;
+begin
+ inherited Create;
+
+ FCurrentStateLock := TCriticalSection.Create;
+ FObservers := TInterfaceList.Create;
+end;
+
+
+destructor TFSXSimConnectStateMonitor.Destroy;
+begin
+ FreeAndNil(FObservers);
+ FreeAndNil(FCurrentStateLock);
+
+ inherited Destroy;
+end;
+
+
+procedure TFSXSimConnectStateMonitor.Attach(AObserver: IFSXSimConnectStateObserver);
+begin
+ Observers.Add(AObserver as IFSXSimConnectStateObserver);
+end;
+
+
+procedure TFSXSimConnectStateMonitor.Detach(AObserver: IFSXSimConnectStateObserver);
+begin
+ Observers.Remove(AObserver as IFSXSimConnectStateObserver);
+end;
+
+
+procedure TFSXSimConnectStateMonitor.DoSetCurrentState(const Value: TFSXSimConnectState);
+var
+ observer: IInterface;
+
+begin
+ CurrentStateLock.Acquire;
+ try
+ if Value <> FCurrentState then
+ begin
+ FCurrentState := Value;
+
+ for observer in Observers do
+ (observer as IFSXSimConnectStateObserver).ObserverStateUpdate(CurrentState);
+ end;
+ finally
+ CurrentStateLock.Release;
+ end;
+end;
+
+
+initialization
+ FSXSimConnectStateInstance := TFSXSimConnectStateMonitor.Create;
+
+finalization
+ FreeAndNil(FSXSimConnectStateInstance);
+
+end.
diff --git a/G940LEDControl/Units/G940LEDStateConsumer.pas b/G940LEDControl/Units/G940LEDStateConsumer.pas
index 9df311e..f668616 100644
--- a/G940LEDControl/Units/G940LEDStateConsumer.pas
+++ b/G940LEDControl/Units/G940LEDStateConsumer.pas
@@ -179,8 +179,8 @@ begin
for buttonIndex := 0 to Pred(G940_BUTTONCOUNT) do
begin
- if buttonIndex >= ButtonColors.Count then
- buttonColor := lcOff
+ if (buttonIndex >= ButtonColors.Count) or (not Assigned(ButtonColors[buttonIndex])) then
+ buttonColor := lcGreen
else
buttonColor := (ButtonColors[buttonIndex] as ILEDStateColor).GetCurrentColor;
diff --git a/G940LEDControl/Units/LEDFunction.pas b/G940LEDControl/Units/LEDFunction.pas
index 98448ad..07ed8d3 100644
--- a/G940LEDControl/Units/LEDFunction.pas
+++ b/G940LEDControl/Units/LEDFunction.pas
@@ -2,7 +2,8 @@ unit LEDFunction;
interface
uses
- Classes,
+ System.Classes,
+ System.SyncObjs,
LEDFunctionIntf,
LEDStateIntf;
@@ -10,7 +11,7 @@ uses
type
TCustomLEDFunctionWorker = class;
- TCustomLEDFunctionWorkerClass = class of TCustomLEDFunctionWorker;
+ TCustomLEDMultiStateFunctionWorkerClass = class of TCustomLEDMultiStateFunctionWorker;
TCustomLEDFunctionProvider = class(TInterfacedObject, ILEDFunctionProvider)
@@ -38,26 +39,27 @@ type
function GetDisplayName: string; virtual; abstract;
function GetUID: string; virtual; abstract;
- function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; virtual; abstract;
+ function CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): ILEDFunctionWorker; virtual; abstract;
end;
TCustomMultiStateLEDFunction = class(TCustomLEDFunction, ILEDMultiStateFunction)
private
FStates: TInterfaceList;
+ FProviderUID: string;
protected
procedure RegisterStates; virtual; abstract;
function RegisterState(AState: ILEDState): ILEDState; virtual;
- function GetWorkerClass: TCustomLEDFunctionWorkerClass; virtual; abstract;
- function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; virtual;
+ function GetWorkerClass: TCustomLEDMultiStateFunctionWorkerClass; virtual; abstract;
+ function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): TCustomLEDFunctionWorker; virtual;
protected
- function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; override;
+ function CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): ILEDFunctionWorker; override;
{ ILEDMultiStateFunction }
function GetEnumerator: ILEDStateEnumerator; virtual;
public
- constructor Create;
+ constructor Create(const AProviderUID: string);
destructor Destroy; override;
end;
@@ -65,25 +67,44 @@ type
TCustomLEDFunctionWorker = class(TInterfacedObject, ILEDFunctionWorker)
private
FObservers: TInterfaceList;
- FStates: TInterfaceList;
+ FProviderUID: string;
+ FFunctionUID: string;
protected
- procedure RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings); virtual;
- function FindState(const AUID: string): ILEDStateWorker; virtual;
-
procedure NotifyObservers; virtual;
property Observers: TInterfaceList read FObservers;
- property States: TInterfaceList read FStates;
protected
{ ILEDFunctionWorker }
procedure Attach(AObserver: ILEDFunctionObserver); virtual;
procedure Detach(AObserver: ILEDFunctionObserver); virtual;
+ function GetProviderUID: string; virtual;
+ function GetFunctionUID: string; virtual;
+
function GetCurrentState: ILEDStateWorker; virtual; abstract;
public
- constructor Create; overload; virtual;
- constructor Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings); overload; virtual;
+ constructor Create(const AProviderUID, AFunctionUID: string);
+ destructor Destroy; override;
+ end;
+
+ TCustomLEDMultiStateFunctionWorker = class(TCustomLEDFunctionWorker)
+ private
+ FStates: TInterfaceList;
+ FCurrentStateLock: TCriticalSection;
+ FCurrentState: ILEDStateWorker;
+ protected
+ procedure RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings); virtual;
+ function FindState(const AUID: string): ILEDStateWorker; virtual;
+
+ procedure SetCurrentState(const AUID: string; ANotifyObservers: Boolean = True); overload; virtual;
+ procedure SetCurrentState(AState: ILEDStateWorker; ANotifyObservers: Boolean = True); overload; virtual;
+
+ property States: TInterfaceList read FStates;
+ protected
+ function GetCurrentState: ILEDStateWorker; override;
+ public
+ constructor Create(const AProviderUID, AFunctionUID: string; AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''); virtual;
destructor Destroy; override;
end;
@@ -125,11 +146,13 @@ uses
{ TCustomMultiStateLEDFunction }
-constructor TCustomMultiStateLEDFunction.Create;
+constructor TCustomMultiStateLEDFunction.Create(const AProviderUID: string);
begin
inherited Create;
FStates := TInterfaceList.Create;
+ FProviderUID := AProviderUID;
+
RegisterStates;
end;
@@ -155,39 +178,31 @@ begin
end;
-function TCustomMultiStateLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker;
+function TCustomMultiStateLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string): ILEDFunctionWorker;
begin
- Result := DoCreateWorker(ASettings);
+ Result := DoCreateWorker(ASettings, APreviousState);
end;
-function TCustomMultiStateLEDFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker;
+function TCustomMultiStateLEDFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string): TCustomLEDFunctionWorker;
begin
- Result := GetWorkerClass.Create(Self, ASettings);
+ Result := GetWorkerClass.Create(FProviderUID, GetUID, Self, ASettings, APreviousState);
end;
{ TCustomLEDFunctionWorker }
-constructor TCustomLEDFunctionWorker.Create;
+constructor TCustomLEDFunctionWorker.Create(const AProviderUID, AFunctionUID: string);
begin
inherited Create;
FObservers := TInterfaceList.Create;
-end;
-
-
-constructor TCustomLEDFunctionWorker.Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings);
-begin
- Create;
-
- FStates := TInterfaceList.Create;
- RegisterStates(AStates, ASettings);
+ FProviderUID := AProviderUID;
+ FFunctionUID := AFunctionUID;
end;
destructor TCustomLEDFunctionWorker.Destroy;
begin
- FreeAndNil(FStates);
FreeAndNil(FObservers);
inherited Destroy;
@@ -207,7 +222,57 @@ begin
end;
-procedure TCustomLEDFunctionWorker.RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings);
+function TCustomLEDFunctionWorker.GetProviderUID: string;
+begin
+ Result := FProviderUID;
+end;
+
+
+function TCustomLEDFunctionWorker.GetFunctionUID: string;
+begin
+ Result := FFunctionUID;
+end;
+
+
+procedure TCustomLEDFunctionWorker.NotifyObservers;
+var
+ observer: IInterface;
+
+begin
+ for observer in Observers do
+ (observer as ILEDFunctionObserver).ObserveUpdate(Self);
+end;
+
+
+{ TCustomLEDMultiStateFunctionWorker }
+constructor TCustomLEDMultiStateFunctionWorker.Create(const AProviderUID, AFunctionUID: string; AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; const APreviousState: string);
+begin
+ inherited Create(AProviderUID, AFunctionUID);
+
+ FCurrentStateLock := TCriticalSection.Create;
+
+ FStates := TInterfaceList.Create;
+ RegisterStates(AStates, ASettings);
+
+ if Length(APreviousState) > 0 then
+ FCurrentState := FindState(APreviousState);
+
+ { Make sure we have a default state }
+ if (not Assigned(FCurrentState)) and (States.Count > 0) then
+ SetCurrentState((States[0] as ILEDStateWorker), False);
+end;
+
+
+destructor TCustomLEDMultiStateFunctionWorker.Destroy;
+begin
+ FreeAndNil(FCurrentStateLock);
+ FreeAndNil(FStates);
+
+ inherited Destroy;
+end;
+
+
+procedure TCustomLEDMultiStateFunctionWorker.RegisterStates(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings);
var
state: ILEDState;
color: TLEDColor;
@@ -223,7 +288,7 @@ begin
end;
-function TCustomLEDFunctionWorker.FindState(const AUID: string): ILEDStateWorker;
+function TCustomLEDMultiStateFunctionWorker.FindState(const AUID: string): ILEDStateWorker;
var
state: IInterface;
@@ -241,13 +306,37 @@ begin
end;
-procedure TCustomLEDFunctionWorker.NotifyObservers;
-var
- observer: IInterface;
-
+procedure TCustomLEDMultiStateFunctionWorker.SetCurrentState(const AUID: string; ANotifyObservers: Boolean);
begin
- for observer in Observers do
- (observer as ILEDFunctionObserver).ObserveUpdate(Self);
+ SetCurrentState(FindState(AUID), ANotifyObservers);
+end;
+
+
+procedure TCustomLEDMultiStateFunctionWorker.SetCurrentState(AState: ILEDStateWorker; ANotifyObservers: Boolean);
+begin
+ FCurrentStateLock.Acquire;
+ try
+ if AState <> FCurrentState then
+ begin
+ FCurrentState := AState;
+
+ if ANotifyObservers then
+ NotifyObservers;
+ end;
+ finally
+ FCurrentStateLock.Release;
+ end;
+end;
+
+
+function TCustomLEDMultiStateFunctionWorker.GetCurrentState: ILEDStateWorker;
+begin
+ FCurrentStateLock.Acquire;
+ try
+ Result := FCurrentState;
+ finally
+ FCurrentStateLock.Release;
+ end;
end;
diff --git a/G940LEDControl/Units/LEDFunctionIntf.pas b/G940LEDControl/Units/LEDFunctionIntf.pas
index 81bba41..b4ce881 100644
--- a/G940LEDControl/Units/LEDFunctionIntf.pas
+++ b/G940LEDControl/Units/LEDFunctionIntf.pas
@@ -29,7 +29,7 @@ type
function GetDisplayName: string;
function GetUID: string;
- function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker;
+ function CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): ILEDFunctionWorker;
end;
@@ -50,6 +50,9 @@ type
procedure Attach(AObserver: ILEDFunctionObserver);
procedure Detach(AObserver: ILEDFunctionObserver);
+ function GetProviderUID: string;
+ function GetFunctionUID: string;
+
function GetCurrentState: ILEDStateWorker;
end;
diff --git a/G940LEDControl/Units/LEDStateConsumer.pas b/G940LEDControl/Units/LEDStateConsumer.pas
index f7c1912..d20f05b 100644
--- a/G940LEDControl/Units/LEDStateConsumer.pas
+++ b/G940LEDControl/Units/LEDStateConsumer.pas
@@ -30,7 +30,7 @@ type
function Initialize: Boolean; override;
procedure Cleanup; override;
- function CreateWorker(AProfileButton: TProfileButton): ILEDFunctionWorker;
+ function CreateWorker(AProfileButton: TProfileButton; const APreviousState: string): ILEDFunctionWorker;
property ButtonWorkers: TInterfaceList read FButtonWorkers;
property ButtonColors: TInterfaceList read FButtonColors;
@@ -49,6 +49,7 @@ type
implementation
uses
+ Generics.Collections,
System.SysUtils,
Winapi.Windows,
@@ -95,7 +96,7 @@ begin
end;
-function TLEDStateConsumer.CreateWorker(AProfileButton: TProfileButton): ILEDFunctionWorker;
+function TLEDStateConsumer.CreateWorker(AProfileButton: TProfileButton; const APreviousState: string): ILEDFunctionWorker;
var
provider: ILEDFunctionProvider;
ledFunction: ILEDFunction;
@@ -108,7 +109,7 @@ begin
begin
ledFunction := provider.Find(AProfileButton.FunctionUID);
if Assigned(ledFunction) then
- Result := ledFunction.CreateWorker(TProfileButtonWorkerSettings.Create(AProfileButton));
+ Result := ledFunction.CreateWorker(TProfileButtonWorkerSettings.Create(AProfileButton), APreviousState);
end;
end;
@@ -175,26 +176,55 @@ end;
procedure TLEDStateConsumer.TMLoadProfile(var Msg: TOmniMessage);
+
+ function GetFunctionKey(const AProviderUID, AFunctionUID: string): string; inline;
+ begin
+ Result := AProviderUID + '|' + AFunctionUID;
+ end;
+
+
var
oldWorkers: TInterfaceList;
+ oldStates: TDictionary;
oldWorker: IInterface;
profile: TProfile;
buttonIndex: Integer;
worker: ILEDFunctionWorker;
+ state: ILEDStateWorker;
+ previousState: string;
+ button: TProfileButton;
+ functionKey: string;
begin
profile := Msg.MsgData;
- { Keep a copy of the old workers until all the new ones are initialized,
- so we don't get unneccessary SimConnect reconnects. }
- oldWorkers := TInterfaceList.Create;
+ oldStates := nil;
+ oldWorkers := nil;
try
+ oldStates := TDictionary.Create;
+ oldWorkers := TInterfaceList.Create;
+
+ { Keep a copy of the old workers until all the new ones are initialized,
+ so we don't get unneccessary SimConnect reconnects. }
for oldWorker in ButtonWorkers do
begin
if Assigned(oldWorker) then
begin
- (oldWorker as ILEDFunctionWorker).Detach(Self);
- oldWorkers.Add(oldWorker);
+ worker := (oldWorker as ILEDFunctionWorker);
+ try
+ worker.Detach(Self);
+ oldWorkers.Add(worker);
+
+ { Keep the current state as well, to prevent the LEDs from flickering }
+ state := worker.GetCurrentState;
+ try
+ oldStates.AddOrSetValue(GetFunctionKey(worker.GetProviderUID, worker.GetFunctionUID), state.GetUID);
+ finally
+ state := nil;
+ end;
+ finally
+ worker := nil;
+ end;
end;
end;
@@ -204,7 +234,14 @@ begin
begin
if profile.HasButton(buttonIndex) then
begin
- worker := CreateWorker(profile.Buttons[buttonIndex]) as ILEDFunctionWorker;
+ button := profile.Buttons[buttonIndex];
+
+ previousState := '';
+ functionKey := GetFunctionKey(button.ProviderUID, button.FunctionUID);
+ if oldStates.ContainsKey(functionKey) then
+ previousState := oldStates[functionKey];
+
+ worker := CreateWorker(button, previousState) as ILEDFunctionWorker;
ButtonWorkers.Add(worker);
if Assigned(worker) then
@@ -214,6 +251,7 @@ begin
end;
finally
FreeAndNil(oldWorkers);
+ FreeAndNil(oldStates);
end;
Changed;
diff --git a/G940LEDControl/Units/Profile.pas b/G940LEDControl/Units/Profile.pas
index a4a1c6a..1389b6a 100644
--- a/G940LEDControl/Units/Profile.pas
+++ b/G940LEDControl/Units/Profile.pas
@@ -28,6 +28,8 @@ type
constructor Create;
destructor Destroy; override;
+ procedure Assign(Source: TPersistent); override;
+
procedure ClearStateColors;
function GetStateColor(const AStateUID: string; out AValue: TLEDColor): Boolean;
procedure SetStateColor(const AStateUID: string; const AValue: TLEDColor);
@@ -43,20 +45,24 @@ type
TProfile = class(TPersistent)
private
FName: string;
+ FIsTemporary: Boolean;
FButtons: TProfileButtonList;
function GetButton(Index: Integer): TProfileButton;
function GetButtonCount: Integer;
protected
- function Load(AReader: IX2PersistReader): Boolean;
+ procedure Load(AReader: IX2PersistReader);
procedure Save(AWriter: IX2PersistWriter);
public
constructor Create;
destructor Destroy; override;
+ procedure Assign(Source: TPersistent); override;
+
function HasButton(AIndex: Integer): Boolean;
property Name: string read FName write FName;
+ property IsTemporary: Boolean read FIsTemporary write FIsTemporary;
property ButtonCount: Integer read GetButtonCount;
property Buttons[Index: Integer]: TProfileButton read GetButton;
@@ -65,6 +71,8 @@ type
TProfileList = class(TObjectList)
public
+ function Find(const AName: string): TProfile;
+
procedure Load(AReader: IX2PersistReader);
procedure Save(AWriter: IX2PersistWriter);
end;
@@ -84,6 +92,7 @@ const
KeyProviderUID = 'ProviderUID';
KeyFunctionUID = 'FunctionUID';
+ KeyIsTemporary = 'IsTemporary';
{ TProfileButton }
@@ -103,6 +112,27 @@ begin
end;
+procedure TProfileButton.Assign(Source: TPersistent);
+var
+ sourceButton: TProfileButton;
+ stateUID: string;
+
+begin
+ if Source is TProfileButton then
+ begin
+ sourceButton := TProfileButton(Source);
+
+ FProviderUID := sourceButton.ProviderUID;
+ FFunctionUID := sourceButton.FunctionUID;
+
+ FStateColors.Clear;
+ for stateUID in sourceButton.StateColors.Keys do
+ SetStateColor(stateUID, sourceButton.StateColors[stateUID]);
+ end else
+ inherited Assign(Source);
+end;
+
+
procedure TProfileButton.ClearStateColors;
begin
FStateColors.Clear;
@@ -192,22 +222,44 @@ begin
end;
-function TProfile.Load(AReader: IX2PersistReader): Boolean;
+procedure TProfile.Assign(Source: TPersistent);
+var
+ sourceProfile: TProfile;
+ buttonIndex: Integer;
+
+begin
+ if Source is TProfile then
+ begin
+ sourceProfile := TProfile(Source);
+
+ FName := sourceProfile.Name;
+ FIsTemporary := sourceProfile.IsTemporary;
+
+ FButtons.Clear;
+ for buttonIndex := 0 to Pred(sourceProfile.ButtonCount) do
+ Buttons[buttonIndex].Assign(sourceProfile.Buttons[buttonIndex]);
+ end else
+ inherited Assign(Source);
+end;
+
+
+procedure TProfile.Load(AReader: IX2PersistReader);
var
buttonIndex: Integer;
button: TProfileButton;
begin
- Result := False;
buttonIndex := 0;
+ if not AReader.ReadBoolean(KeyIsTemporary, FIsTemporary) then
+ FIsTemporary := False;
+
while AReader.BeginSection(SectionButton + IntToStr(buttonIndex)) do
try
button := TProfileButton.Create;
if button.Load(AReader) then
begin
FButtons.Add(button);
- Result := True;
end else
FreeAndNil(button);
finally
@@ -222,6 +274,8 @@ var
buttonIndex: Integer;
begin
+ AWriter.WriteBoolean(KeyIsTemporary, IsTemporary);
+
for buttonIndex := 0 to Pred(FButtons.Count) do
begin
if AWriter.BeginSection(SectionButton + IntToStr(buttonIndex)) then
@@ -272,6 +326,22 @@ end;
{ TProfileList }
+function TProfileList.Find(const AName: string): TProfile;
+var
+ profile: TProfile;
+
+begin
+ Result := nil;
+
+ for profile in Self do
+ if SameText(profile.Name, AName) then
+ begin
+ Result := profile;
+ break;
+ end;
+end;
+
+
procedure TProfileList.Load(AReader: IX2PersistReader);
var
profiles: TStringList;
@@ -291,11 +361,9 @@ begin
try
profile := TProfile.Create;
profile.Name := profileName;
+ profile.Load(AReader);
- if profile.Load(AReader) then
- Add(profile)
- else
- FreeAndNil(profile);
+ Add(profile);
finally
AReader.EndSection;
end;
diff --git a/G940LEDControl/Units/Settings.pas b/G940LEDControl/Units/Settings.pas
index 14c9d4a..c1fd303 100644
--- a/G940LEDControl/Units/Settings.pas
+++ b/G940LEDControl/Units/Settings.pas
@@ -9,6 +9,7 @@ type
private
FCheckUpdates: Boolean;
FHasCheckUpdates: Boolean;
+ FActiveProfile: string;
procedure SetCheckUpdates(const Value: Boolean);
public
@@ -17,6 +18,8 @@ type
property CheckUpdates: Boolean read FCheckUpdates write SetCheckUpdates;
property HasCheckUpdates: Boolean read FHasCheckUpdates;
+
+ property ActiveProfile: string read FActiveProfile write FActiveProfile;
end;
@@ -25,6 +28,7 @@ const
SectionSettings = 'Settings';
KeyCheckUpdates = 'CheckUpdates';
+ KeyActiveProfile = 'ActiveProfile';
{ TSettings }
@@ -37,6 +41,9 @@ begin
try
if AReader.ReadBoolean(KeyCheckUpdates, value) then
CheckUpdates := value;
+
+ if not AReader.ReadString(KeyActiveProfile, FActiveProfile) then
+ FActiveProfile := '';
finally
AReader.EndSection;
end;
@@ -48,6 +55,7 @@ begin
if AWriter.BeginSection(SectionSettings) then
try
AWriter.WriteBoolean(KeyCheckUpdates, CheckUpdates);
+ AWriter.WriteString(KeyActiveProfile, ActiveProfile);
finally
AWriter.EndSection;
end;
diff --git a/G940LEDControl/Units/StaticLEDFunction.pas b/G940LEDControl/Units/StaticLEDFunction.pas
index 1bdced1..c3cb7df 100644
--- a/G940LEDControl/Units/StaticLEDFunction.pas
+++ b/G940LEDControl/Units/StaticLEDFunction.pas
@@ -25,7 +25,7 @@ type
function GetDisplayName: string; override;
function GetUID: string; override;
- function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; override;
+ function CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string = ''): ILEDFunctionWorker; override;
public
constructor Create(AColor: TLEDColor);
end;
@@ -46,7 +46,7 @@ type
protected
function GetCurrentState: ILEDStateWorker; override;
public
- constructor Create(AColor: TLEDColor);
+ constructor Create(const AProviderUID, AFunctionUID: string; AColor: TLEDColor);
end;
@@ -94,16 +94,16 @@ begin
end;
-function TStaticLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker;
+function TStaticLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings; const APreviousState: string): ILEDFunctionWorker;
begin
- Result := TStaticLEDFunctionWorker.Create(FColor);
+ Result := TStaticLEDFunctionWorker.Create(StaticProviderUID, GetUID, FColor);
end;
{ TStaticLEDFunctionWorker }
-constructor TStaticLEDFunctionWorker.Create(AColor: TLEDColor);
+constructor TStaticLEDFunctionWorker.Create(const AProviderUID, AFunctionUID: string; AColor: TLEDColor);
begin
- inherited Create;
+ inherited Create(AProviderUID, AFunctionUID);
FState := TLEDStateWorker.Create('', TLEDColorPool.GetColor(AColor));
end;