diff --git a/Client/UfrmLargeScaleCommand.lfm b/Client/UfrmLargeScaleCommand.lfm index 3b3dce2..374cf46 100644 --- a/Client/UfrmLargeScaleCommand.lfm +++ b/Client/UfrmLargeScaleCommand.lfm @@ -1084,7 +1084,7 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = btnDeleteArea Left = 4 - Height = 118 + Height = 122 Top = 154 Width = 144 Anchors = [akTop, akLeft, akRight, akBottom] @@ -1209,10 +1209,8 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand Top = 280 Width = 22 Anchors = [akLeft, akBottom] - BorderSpacing.Left = 4 - BorderSpacing.Top = 8 - BorderSpacing.Right = 4 - BorderSpacing.Bottom = 8 + BorderSpacing.Bottom = 4 + BorderSpacing.Around = 4 Color = clBtnFace Glyph.Data = { 36040000424D3604000000000000360000002800000010000000100000000100 @@ -1394,6 +1392,7 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand AnchorSideBottom.Side = asrBottom Left = 34 Height = 22 + Hint = 'Grab coordinates from the main window.' Top = 360 Width = 22 Anchors = [akLeft, akBottom] @@ -1438,6 +1437,8 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand } NumGlyphs = 0 OnClick = btnGrab1Click + ShowHint = True + ParentShowHint = False end object btnGrab2: TSpeedButton AnchorSideLeft.Control = seY2 @@ -1446,6 +1447,7 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand AnchorSideBottom.Side = asrBottom Left = 92 Height = 22 + Hint = 'Grab coordinates from the main window.' Top = 360 Width = 22 Anchors = [akLeft, akBottom] @@ -1489,5 +1491,7 @@ object frmLargeScaleCommand: TfrmLargeScaleCommand } NumGlyphs = 0 OnClick = btnGrab1Click + ShowHint = True + ParentShowHint = False end end diff --git a/Client/UfrmRegionControl.lfm b/Client/UfrmRegionControl.lfm index 5364521..ed0bc98 100644 --- a/Client/UfrmRegionControl.lfm +++ b/Client/UfrmRegionControl.lfm @@ -3,7 +3,7 @@ object frmRegionControl: TfrmRegionControl Height = 413 Top = 139 Width = 620 - ActiveControl = Panel1 + ActiveControl = vstRegions Caption = 'Region Control' ClientHeight = 413 ClientWidth = 620 @@ -14,486 +14,611 @@ object frmRegionControl: TfrmRegionControl OnShow = FormShow Position = poOwnerFormCenter ShowInTaskBar = stAlways - LCLVersion = '0.9.27' - object Panel1: TPanel - Left = 0 - Height = 380 - Top = 0 - Width = 160 - Align = alLeft - ClientHeight = 380 - ClientWidth = 160 - TabOrder = 0 - object Label1: TLabel - Left = 5 - Height = 14 - Top = 176 - Width = 150 - Align = alTop - BorderSpacing.Left = 4 - BorderSpacing.Right = 4 - Caption = 'Area:' - ParentColor = False - end - object pnlAreaControls: TPanel - Left = 5 - Height = 82 - Top = 293 - Width = 150 - Align = alBottom - BorderSpacing.Around = 4 - BevelOuter = bvNone - ClientHeight = 82 - ClientWidth = 150 - TabOrder = 0 - object lblX: TLabel - Left = 4 - Height = 14 - Top = 32 - Width = 8 - Caption = 'X' - Enabled = False - ParentColor = False - end - object lblY: TLabel - Left = 4 - Height = 14 - Top = 60 - Width = 8 - Caption = 'Y' - Enabled = False - ParentColor = False - end - object btnAddArea: TSpeedButton - Left = 30 - Height = 22 - Hint = 'Add area' - Top = 0 - Width = 23 - Color = clBtnFace - Enabled = False - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 - 37FF000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE - 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 - 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB - 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 - 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 - 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 - 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 - 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC - 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 - 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF - 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 - 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 - 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC - 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 - 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD - 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 - 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 - 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 - 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF - AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 - 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD - B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 - 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE - 77FF000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000 - } - NumGlyphs = 0 - OnClick = btnAddAreaClick - ShowHint = True - ParentShowHint = False - end - object btnDeleteArea: TSpeedButton - Left = 59 - Height = 22 - Hint = 'Delete area' - Top = 0 - Width = 23 - Color = clBtnFace - Enabled = False - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E - B8FF000000000000000000000000000000000000000000000000000000000000 - 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 - E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 - 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 - EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 - 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 - E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 - 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 - E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 - D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 - E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 - DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 - DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A - DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F - ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 - 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 - F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 - 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 - F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 - 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 - FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 - 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 - F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 - 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 - D9FF000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000 - } - NumGlyphs = 0 - OnClick = btnDeleteAreaClick - ShowHint = True - ParentShowHint = False - end - object btnClearArea: TSpeedButton - Left = 87 - Height = 22 - Hint = 'Delete all areas' - Top = 0 - Width = 23 - Color = clBtnFace - Enabled = False - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000F1FF0000F1FF0000F1FF0000F1FF0000EFFF0000 - EFFF0000EDFF0000EDFF00000000000000000000000000000000000000000000 - 0000000000000000F5FF1A20F5FF3C4CF9FF3A49F8FF3847F8FF3545F8FF3443 - F7FF3242F7FF141BF1FF0000EDFF000000000000000000000000000000000000 - 00000000F7FF1D23F9FF4453FAFF2429F9FF1212F7FF0F0FF6FF0C0CF5FF0909 - F5FF161BF5FF3343F7FF141BF1FF0000EDFF0000000000000000000000000000 - F9FF1F25FAFF4A58FBFF4247FBFFC9C9FDFF3B3BF9FF1313F7FF1010F6FF3333 - F7FFC5C5FDFF3035F7FF3444F7FF141BF2FF0000EDFF00000000000000000000 - FBFF4F5DFDFF3237FBFFCBCBFEFFF2F2FFFFEBEBFEFF3B3BF9FF3939F8FFEAEA - FEFFF1F1FEFFC5C5FDFF181DF6FF3343F7FF0000EFFF00000000000000000000 - FDFF525FFDFF2828FCFF4747FCFFECECFFFFF2F2FFFFECECFFFFECECFEFFF1F1 - FFFFEAEAFEFF3434F7FF0B0BF5FF3545F8FF0000EFFF00000000000000000000 - FDFF5562FEFF2C2CFDFF2929FCFF4848FCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC - FEFF3A3AF9FF1212F7FF0F0FF6FF3848F8FF0000F1FF00000000000000000000 - FDFF5764FEFF3030FDFF2D2DFDFF4B4BFCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC - FFFF3D3DF9FF1616F8FF1313F7FF3C4BF8FF0000F1FF00000000000000000000 - FFFF5A67FEFF3333FEFF5050FDFFEDEDFFFFF3F3FFFFEDEDFFFFEDEDFFFFF2F2 - FFFFECECFEFF3E3EFAFF1717F8FF3F4EF9FF0000F1FF00000000000000000000 - FFFF5B68FFFF4347FEFFCFCFFFFFF3F3FFFFEDEDFFFF4C4CFCFF4A4AFCFFECEC - FFFFF2F2FFFFCACAFEFF2A2FFAFF4251FAFF0000F3FF00000000000000000000 - FFFF262BFFFF5D6AFFFF585BFFFFCFCFFFFF5252FEFF2F2FFDFF2C2CFDFF4B4B - FCFFCCCCFEFF484CFBFF4957FBFF1D23F9FF0000F5FF00000000000000000000 - 00000000FFFF262BFFFF5D6AFFFF4347FFFF3434FEFF3232FEFF3030FDFF2D2D - FDFF383CFCFF4F5DFCFF1F25FAFF0000F7FF0000000000000000000000000000 - 0000000000000000FFFF262BFFFF5C69FFFF5B68FFFF5A67FEFF5865FEFF5663 - FEFF5461FEFF2227FCFF0000FBFF000000000000000000000000000000000000 - 000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0000FDFF0000 - FDFF0000FDFF0000FDFF00000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000 - } - NumGlyphs = 0 - OnClick = btnClearAreaClick - ShowHint = True - ParentShowHint = False - end - object seX1: TSpinEdit - Left = 20 - Height = 19 - Top = 29 - Width = 50 - Enabled = False - OnChange = seX1Change - TabOrder = 0 - end - object seX2: TSpinEdit - Left = 84 - Height = 19 - Top = 29 - Width = 50 - Enabled = False - OnChange = seX1Change - TabOrder = 1 - end - object seY1: TSpinEdit - Left = 20 - Height = 19 - Top = 56 - Width = 50 - Enabled = False - OnChange = seX1Change - TabOrder = 2 - end - object seY2: TSpinEdit - Left = 84 - Height = 19 - Top = 56 - Width = 50 - Enabled = False - OnChange = seX1Change - TabOrder = 3 - end - end - object vstArea: TVirtualStringTree - Left = 5 - Height = 99 - Top = 190 - Width = 150 - Align = alClient - BorderSpacing.Left = 4 - BorderSpacing.Right = 4 - BorderSpacing.Bottom = 4 - BorderStyle = bsSingle - DefaultText = 'Node' - Header.AutoSizeIndex = 0 - Header.Columns = <> - Header.DefaultHeight = 17 - Header.MainColumn = -1 - Header.Options = [hoColumnResize, hoDrag] - TabOrder = 1 - TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages] - TreeOptions.SelectionOptions = [toFullRowSelect] - OnChange = vstAreaChange - OnGetText = vstAreaGetText - end - object spRegionsArea: TSplitter - Cursor = crVSplit - Left = 1 - Height = 5 - Top = 171 - Width = 158 - Align = alTop - AutoSnap = False - ResizeAnchor = akTop - end - object Panel4: TPanel - Left = 1 - Height = 170 - Top = 1 - Width = 158 - Align = alTop - Anchors = [akLeft, akRight] - BevelOuter = bvNone - ClientHeight = 170 - ClientWidth = 158 - TabOrder = 3 - object vstRegions: TVirtualStringTree - Left = 0 - Height = 144 - Top = 0 - Width = 158 - Align = alClient - DefaultText = 'Node' - Header.AutoSizeIndex = 0 - Header.Columns = < - item - Position = 0 - Text = 'Regions' - Width = 158 - end> - Header.DefaultHeight = 17 - Header.Options = [hoAutoResize, hoVisible] - Header.ParentFont = True - Header.Style = hsFlatButtons - PopupMenu = pmRegions - TabOrder = 0 - TreeOptions.MiscOptions = [toCheckSupport, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning] - TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages] - TreeOptions.SelectionOptions = [toFullRowSelect] - OnChange = vstRegionsChange - OnFreeNode = vstRegionsFreeNode - OnGetText = vstRegionsGetText - end - object Panel5: TPanel - Left = 0 - Height = 26 - Top = 144 - Width = 158 - Align = alBottom - BevelOuter = bvNone - ClientHeight = 26 - ClientWidth = 158 - TabOrder = 1 - object btnAddRegion: TSpeedButton - Left = 54 - Height = 22 - Hint = 'Add region' - Top = 3 - Width = 23 - Color = clBtnFace - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 - 37FF000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE - 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 - 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB - 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 - 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 - 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 - 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 - 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC - 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 - 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF - 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 - 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 - 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC - 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 - 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD - 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 - 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 - 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 - 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF - AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 - 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD - B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 - 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE - 77FF000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000 - } - NumGlyphs = 0 - OnClick = mnuAddRegionClick - ShowHint = True - ParentShowHint = False - end - object btnDeleteRegion: TSpeedButton - Left = 82 - Height = 22 - Hint = 'Delete region' - Top = 3 - Width = 23 - Color = clBtnFace - Enabled = False - Glyph.Data = { - 36040000424D3604000000000000360000002800000010000000100000000100 - 2000000000000004000064000000640000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E - B8FF000000000000000000000000000000000000000000000000000000000000 - 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 - E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 - 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 - EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 - 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 - E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 - 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 - E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 - D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 - E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 - DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 - DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A - DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F - ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 - 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 - F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 - 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 - F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 - 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 - FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 - 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 - F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 - 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 - D9FF000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000 - } - NumGlyphs = 0 - OnClick = mnuDeleteRegionClick - ShowHint = True - ParentShowHint = False - end - end - end - end - object Panel2: TPanel + LCLVersion = '0.9.29' + object sbArea: TScrollBox + AnchorSideLeft.Control = vstRegions + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = btnClose Left = 160 - Height = 380 + Height = 372 Top = 0 Width = 460 - Align = alClient - Caption = 'Panel2' - ClientHeight = 380 - ClientWidth = 460 - TabOrder = 1 - object sbArea: TScrollBox - Left = 1 - Height = 378 - Top = 1 - Width = 458 - Align = alClient - ClientHeight = 374 - ClientWidth = 454 - TabOrder = 0 - object pbArea: TPaintBox - Left = 0 - Height = 105 - Top = 0 - Width = 105 - OnMouseDown = pbAreaMouseDown - OnMouseMove = pbAreaMouseMove - OnPaint = pbAreaPaint - end + Anchors = [akTop, akLeft, akRight, akBottom] + ClientHeight = 368 + ClientWidth = 456 + TabOrder = 0 + object pbArea: TPaintBox + Left = 0 + Height = 105 + Top = 0 + Width = 105 + OnMouseDown = pbAreaMouseDown + OnMouseMove = pbAreaMouseMove + OnPaint = pbAreaPaint end end - object Panel3: TPanel - Left = 4 + object btnClose: TButton + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Owner + AnchorSideBottom.Side = asrBottom + Left = 548 Height = 25 - Top = 384 - Width = 612 - Align = alBottom - BorderSpacing.Around = 4 - BevelOuter = bvNone - ClientHeight = 25 - ClientWidth = 612 + Top = 380 + Width = 64 + Anchors = [akRight, akBottom] + BorderSpacing.Around = 8 + Caption = 'Close' + OnClick = btnCloseClick + TabOrder = 1 + end + object btnSave: TButton + AnchorSideRight.Control = btnClose + AnchorSideBottom.Control = btnClose + AnchorSideBottom.Side = asrBottom + Left = 476 + Height = 25 + Top = 380 + Width = 64 + Anchors = [akRight, akBottom] + BorderSpacing.Right = 4 + Caption = 'Save' + Enabled = False + OnClick = btnSaveClick TabOrder = 2 - object btnClose: TButton - Left = 548 - Height = 25 - Top = 0 - Width = 64 - Align = alRight - Anchors = [akTop, akRight] - BorderSpacing.Left = 4 - Caption = 'Close' - OnClick = btnCloseClick - TabOrder = 0 - end - object btnSave: TButton - Left = 480 - Height = 25 - Top = 0 - Width = 64 - Align = alRight - Anchors = [akTop, akRight] - BorderSpacing.Right = 4 - Caption = 'Save' - Enabled = False - OnClick = btnSaveClick - TabOrder = 1 - end + end + object vstRegions: TVirtualStringTree + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + AnchorSideBottom.Control = btnAddRegion + Left = 0 + Height = 130 + Top = 0 + Width = 160 + Anchors = [akTop, akLeft, akBottom] + DefaultText = 'Node' + Header.AutoSizeIndex = 0 + Header.Columns = < + item + Position = 0 + Text = 'Regions' + Width = 160 + end> + Header.DefaultHeight = 17 + Header.Options = [hoAutoResize, hoVisible] + Header.ParentFont = True + Header.Style = hsFlatButtons + PopupMenu = pmRegions + TabOrder = 3 + TreeOptions.MiscOptions = [toCheckSupport, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning] + TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages] + TreeOptions.SelectionOptions = [toFullRowSelect] + OnChange = vstRegionsChange + OnFreeNode = vstRegionsFreeNode + OnGetText = vstRegionsGetText + end + object btnAddRegion: TSpeedButton + AnchorSideLeft.Control = vstRegions + AnchorSideBottom.Control = spRegionsArea + Left = 4 + Height = 22 + Hint = 'Add region' + Top = 134 + Width = 22 + Anchors = [akLeft, akBottom] + BorderSpacing.Around = 4 + Color = clBtnFace + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 + 37FF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 + 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 + 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 + 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC + 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF + 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 + 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 + 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 + 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 + 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 + 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 + 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE + 77FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + NumGlyphs = 0 + OnClick = mnuAddRegionClick + ShowHint = True + ParentShowHint = False + end + object btnDeleteRegion: TSpeedButton + AnchorSideLeft.Control = btnAddRegion + AnchorSideLeft.Side = asrBottom + AnchorSideBottom.Control = btnAddRegion + AnchorSideBottom.Side = asrBottom + Left = 30 + Height = 22 + Hint = 'Delete region' + Top = 134 + Width = 22 + Anchors = [akLeft, akBottom] + BorderSpacing.Left = 4 + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E + B8FF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 + 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 + 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 + 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 + D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 + DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 + DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A + DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 + 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 + 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 + 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 + 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 + 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 + D9FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + NumGlyphs = 0 + OnClick = mnuDeleteRegionClick + ShowHint = True + ParentShowHint = False + end + object vstArea: TVirtualStringTree + AnchorSideLeft.Control = spRegionsArea + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = spRegionsArea + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = btnDeleteArea + Left = 4 + Height = 124 + Top = 179 + Width = 152 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 4 + BorderSpacing.Right = 4 + BorderSpacing.Bottom = 4 + BorderStyle = bsSingle + DefaultText = 'Node' + Header.AutoSizeIndex = 0 + Header.Columns = <> + Header.DefaultHeight = 17 + Header.MainColumn = -1 + Header.Options = [hoColumnResize, hoDrag] + TabOrder = 4 + TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages] + TreeOptions.SelectionOptions = [toFullRowSelect] + OnChange = vstAreaChange + OnGetText = vstAreaGetText + end + object Label1: TLabel + AnchorSideLeft.Control = spRegionsArea + AnchorSideTop.Control = spRegionsArea + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = spRegionsArea + AnchorSideRight.Side = asrBottom + Left = 4 + Height = 14 + Top = 165 + Width = 152 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 4 + BorderSpacing.Right = 4 + Caption = 'Area:' + ParentColor = False + end + object spRegionsArea: TSplitter + AnchorSideLeft.Control = vstRegions + AnchorSideRight.Control = vstRegions + AnchorSideRight.Side = asrBottom + Cursor = crVSplit + Left = 0 + Height = 5 + Top = 160 + Width = 160 + Align = alNone + Anchors = [akTop, akLeft, akRight] + AutoSnap = False + ResizeAnchor = akTop + end + object btnAddArea: TSpeedButton + AnchorSideTop.Control = btnDeleteArea + AnchorSideRight.Control = btnDeleteArea + Left = 43 + Height = 22 + Hint = 'Add area' + Top = 307 + Width = 22 + Anchors = [akTop, akRight] + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 + 37FF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 + 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 + 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 + 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC + 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF + 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 + 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 + 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 + 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 + 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 + 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 + 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE + 77FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + NumGlyphs = 0 + OnClick = btnAddAreaClick + ShowHint = True + ParentShowHint = False + end + object btnDeleteArea: TSpeedButton + AnchorSideLeft.Control = vstArea + AnchorSideLeft.Side = asrCenter + AnchorSideBottom.Control = seX1 + Left = 69 + Height = 22 + Hint = 'Delete area' + Top = 307 + Width = 22 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 4 + BorderSpacing.Around = 4 + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E + B8FF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 + 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 + 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 + 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 + D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 + DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 + DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A + DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 + 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 + 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 + 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 + 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 + 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 + D9FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + NumGlyphs = 0 + OnClick = btnDeleteAreaClick + ShowHint = True + ParentShowHint = False + end + object btnClearArea: TSpeedButton + AnchorSideLeft.Control = btnDeleteArea + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = btnDeleteArea + Left = 95 + Height = 22 + Hint = 'Delete all areas' + Top = 307 + Width = 22 + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000F1FF0000F1FF0000F1FF0000F1FF0000EFFF0000 + EFFF0000EDFF0000EDFF00000000000000000000000000000000000000000000 + 0000000000000000F5FF1A20F5FF3C4CF9FF3A49F8FF3847F8FF3545F8FF3443 + F7FF3242F7FF141BF1FF0000EDFF000000000000000000000000000000000000 + 00000000F7FF1D23F9FF4453FAFF2429F9FF1212F7FF0F0FF6FF0C0CF5FF0909 + F5FF161BF5FF3343F7FF141BF1FF0000EDFF0000000000000000000000000000 + F9FF1F25FAFF4A58FBFF4247FBFFC9C9FDFF3B3BF9FF1313F7FF1010F6FF3333 + F7FFC5C5FDFF3035F7FF3444F7FF141BF2FF0000EDFF00000000000000000000 + FBFF4F5DFDFF3237FBFFCBCBFEFFF2F2FFFFEBEBFEFF3B3BF9FF3939F8FFEAEA + FEFFF1F1FEFFC5C5FDFF181DF6FF3343F7FF0000EFFF00000000000000000000 + FDFF525FFDFF2828FCFF4747FCFFECECFFFFF2F2FFFFECECFFFFECECFEFFF1F1 + FFFFEAEAFEFF3434F7FF0B0BF5FF3545F8FF0000EFFF00000000000000000000 + FDFF5562FEFF2C2CFDFF2929FCFF4848FCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FEFF3A3AF9FF1212F7FF0F0FF6FF3848F8FF0000F1FF00000000000000000000 + FDFF5764FEFF3030FDFF2D2DFDFF4B4BFCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FFFF3D3DF9FF1616F8FF1313F7FF3C4BF8FF0000F1FF00000000000000000000 + FFFF5A67FEFF3333FEFF5050FDFFEDEDFFFFF3F3FFFFEDEDFFFFEDEDFFFFF2F2 + FFFFECECFEFF3E3EFAFF1717F8FF3F4EF9FF0000F1FF00000000000000000000 + FFFF5B68FFFF4347FEFFCFCFFFFFF3F3FFFFEDEDFFFF4C4CFCFF4A4AFCFFECEC + FFFFF2F2FFFFCACAFEFF2A2FFAFF4251FAFF0000F3FF00000000000000000000 + FFFF262BFFFF5D6AFFFF585BFFFFCFCFFFFF5252FEFF2F2FFDFF2C2CFDFF4B4B + FCFFCCCCFEFF484CFBFF4957FBFF1D23F9FF0000F5FF00000000000000000000 + 00000000FFFF262BFFFF5D6AFFFF4347FFFF3434FEFF3232FEFF3030FDFF2D2D + FDFF383CFCFF4F5DFCFF1F25FAFF0000F7FF0000000000000000000000000000 + 0000000000000000FFFF262BFFFF5C69FFFF5B68FFFF5A67FEFF5865FEFF5663 + FEFF5461FEFF2227FCFF0000FBFF000000000000000000000000000000000000 + 000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0000FDFF0000 + FDFF0000FDFF0000FDFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } + NumGlyphs = 0 + OnClick = btnClearAreaClick + ShowHint = True + ParentShowHint = False + end + object lblX: TLabel + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = seX1 + AnchorSideTop.Side = asrCenter + Left = 4 + Height = 14 + Top = 339 + Width = 8 + BorderSpacing.Left = 4 + Caption = 'X' + Enabled = False + ParentColor = False + end + object seX1: TSpinEdit + AnchorSideLeft.Control = seY1 + AnchorSideBottom.Control = seY1 + Left = 20 + Height = 19 + Top = 337 + Width = 50 + Anchors = [akLeft, akBottom] + BorderSpacing.Bottom = 8 + Enabled = False + OnChange = seX1Change + TabOrder = 6 + Value = 1 + end + object seX2: TSpinEdit + AnchorSideLeft.Control = seX1 + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = seX1 + Left = 78 + Height = 19 + Top = 337 + Width = 50 + BorderSpacing.Left = 8 + Enabled = False + OnChange = seX1Change + TabOrder = 7 + Value = 1 + end + object lblY: TLabel + AnchorSideLeft.Control = lblX + AnchorSideTop.Control = seY1 + AnchorSideTop.Side = asrCenter + Left = 4 + Height = 14 + Top = 366 + Width = 8 + Caption = 'Y' + Enabled = False + ParentColor = False + end + object seY1: TSpinEdit + AnchorSideLeft.Control = lblY + AnchorSideLeft.Side = asrBottom + AnchorSideRight.Control = seX1 + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = btnGrab1 + Left = 20 + Height = 19 + Top = 364 + Width = 50 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 8 + Enabled = False + OnChange = seX1Change + TabOrder = 8 + Value = 1 + end + object seY2: TSpinEdit + AnchorSideLeft.Control = seX2 + AnchorSideTop.Control = seX2 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = seX2 + AnchorSideRight.Side = asrBottom + Left = 78 + Height = 19 + Top = 364 + Width = 50 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Top = 8 + Enabled = False + OnChange = seX1Change + TabOrder = 9 + Value = 1 + end + object btnGrab1: TSpeedButton + AnchorSideLeft.Control = seY1 + AnchorSideLeft.Side = asrCenter + AnchorSideBottom.Control = Owner + AnchorSideBottom.Side = asrBottom + Left = 34 + Height = 22 + Hint = 'Grab coordinates from the main window.' + Top = 387 + Width = 22 + Anchors = [akLeft, akBottom] + BorderSpacing.Around = 4 + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007F7F7F067C7C + 7CE6787878CC75757581FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008383835DAAAA + AAFFDBDBDBFF797979F275757506FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0097979709FFFFFF00FFFFFF00FFFFFF00888888E7DBDB + DBFFB7B7B7FF7D7D7D80FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF009C9C9CC99898981EFFFFFF0090909050ADADADFFF2F2 + F2FF848484FD8181810FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A0A0A0FF9C9C9CE798989836949494DFD9D9D9FFC1C1 + C1FF898989A0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A4A4A4FFD7D7D7FF9D9D9DF8D0D0D0FFEEEEEEFF9191 + 91FE8D8D8D18FFFFFF00FFFFFF00818181097E7E7E09FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A9A9A9FFF2F2F2FFE5E5E5FFE2E2E2FFE3E3E3FF9595 + 95F4919191CC8D8D8DF9898989FF86868693FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00ADADADFFEEEEEEFFE1E1E1FFDFDFDFFFE0E0E0FFE7E7 + E7FFE4E4E4FFBBBBBBFF8E8E8E93FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B1B1B1FFF0F0F0FFE4E4E4FFE2E2E2FFE2E2E2FFE7E7 + E7FFC1C1C1FF96969690FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B5B5B5FFF2F2F2FFE8E8E8FFE7E7E7FFEAEAEAFFC6C6 + C6FF9E9E9E8DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B9B9B9FFF4F4F4FFECECECFFEDEDEDFFCBCBCBFFA7A7 + A78AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00BDBDBDFFF7F7F7FFEFEFEFFFD0D0D0FFAFAFAF8AFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C1C1C1FFF7F7F7FFD5D5D5FFB6B6B687FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C4C4C4FFD9D9D9FFBEBEBE84FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C8C8C8FFC5C5C581FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00CBCBCB7EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + NumGlyphs = 0 + OnClick = btnGrab1Click + ShowHint = True + ParentShowHint = False + end + object btnGrab2: TSpeedButton + AnchorSideLeft.Control = seY2 + AnchorSideLeft.Side = asrCenter + AnchorSideBottom.Control = btnGrab1 + AnchorSideBottom.Side = asrBottom + Left = 92 + Height = 22 + Hint = 'Grab coordinates from the main window.' + Top = 387 + Width = 22 + Anchors = [akLeft, akBottom] + Color = clBtnFace + Enabled = False + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF007F7F7F067C7C + 7CE6787878CC75757581FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008383835DAAAA + AAFFDBDBDBFF797979F275757506FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0097979709FFFFFF00FFFFFF00FFFFFF00888888E7DBDB + DBFFB7B7B7FF7D7D7D80FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF009C9C9CC99898981EFFFFFF0090909050ADADADFFF2F2 + F2FF848484FD8181810FFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A0A0A0FF9C9C9CE798989836949494DFD9D9D9FFC1C1 + C1FF898989A0FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A4A4A4FFD7D7D7FF9D9D9DF8D0D0D0FFEEEEEEFF9191 + 91FE8D8D8D18FFFFFF00FFFFFF00818181097E7E7E09FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00A9A9A9FFF2F2F2FFE5E5E5FFE2E2E2FFE3E3E3FF9595 + 95F4919191CC8D8D8DF9898989FF86868693FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00ADADADFFEEEEEEFFE1E1E1FFDFDFDFFFE0E0E0FFE7E7 + E7FFE4E4E4FFBBBBBBFF8E8E8E93FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B1B1B1FFF0F0F0FFE4E4E4FFE2E2E2FFE2E2E2FFE7E7 + E7FFC1C1C1FF96969690FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B5B5B5FFF2F2F2FFE8E8E8FFE7E7E7FFEAEAEAFFC6C6 + C6FF9E9E9E8DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00B9B9B9FFF4F4F4FFECECECFFEDEDEDFFCBCBCBFFA7A7 + A78AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00BDBDBDFFF7F7F7FFEFEFEFFFD0D0D0FFAFAFAF8AFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C1C1C1FFF7F7F7FFD5D5D5FFB6B6B687FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C4C4C4FFD9D9D9FFBEBEBE84FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00C8C8C8FFC5C5C581FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00CBCBCB7EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + NumGlyphs = 0 + OnClick = btnGrab1Click + ShowHint = True + ParentShowHint = False end object pmRegions: TPopupMenu left = 48 diff --git a/Client/UfrmRegionControl.pas b/Client/UfrmRegionControl.pas index eee970e..0bf464a 100644 --- a/Client/UfrmRegionControl.pas +++ b/Client/UfrmRegionControl.pas @@ -1,714 +1,740 @@ -(* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at - * http://www.opensource.org/licenses/cddl1.php. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at - * http://www.opensource.org/licenses/cddl1.php. If applicable, - * add the following below this CDDL HEADER, with the fields enclosed - * by brackets "[]" replaced with your own identifying * information: - * Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - * - * - * Portions Copyright 2008 Andreas Schneider - *) -unit UfrmRegionControl; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, math, LResources, Forms, Controls, Graphics, Dialogs, - VirtualTrees, ExtCtrls, ImagingComponents, StdCtrls, Buttons, Spin, LCLIntf, - UEnhancedMemoryStream, Menus, URectList, UEnums; - -type - TAreaMoveType = (amLeft, amTop, amRight, amBottom); - TAreaMove = set of TAreaMoveType; - - PRegionInfo = ^TRegionInfo; - TRegionInfo = record - Name: string; - Areas: TRectList; - end; - - TRegionModifiedEvent = procedure(ARegionInfo: TRegionInfo) of object; - TRegionDeletedEvent = procedure(ARegionName: string) of object; - TRegionListEvent = procedure of object; - - { TfrmRegionControl } - - TfrmRegionControl = class(TForm) - btnAddArea: TSpeedButton; - btnAddRegion: TSpeedButton; - btnClearArea: TSpeedButton; - btnDeleteArea: TSpeedButton; - btnClose: TButton; - btnDeleteRegion: TSpeedButton; - - btnSave: TButton; - Label1: TLabel; - lblX: TLabel; - lblY: TLabel; - mnuAddRegion: TMenuItem; - mnuDeleteRegion: TMenuItem; - Panel1: TPanel; - Panel2: TPanel; - Panel3: TPanel; - Panel4: TPanel; - Panel5: TPanel; - pbArea: TPaintBox; - pnlAreaControls: TPanel; - pmRegions: TPopupMenu; - sbArea: TScrollBox; - seX1: TSpinEdit; - seX2: TSpinEdit; - seY1: TSpinEdit; - seY2: TSpinEdit; - spRegionsArea: TSplitter; - vstArea: TVirtualStringTree; - vstRegions: TVirtualStringTree; - procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); - procedure mnuAddRegionClick(Sender: TObject); - procedure mnuDeleteRegionClick(Sender: TObject); - procedure btnAddAreaClick(Sender: TObject); - procedure btnClearAreaClick(Sender: TObject); - procedure btnCloseClick(Sender: TObject); - procedure btnDeleteAreaClick(Sender: TObject); - procedure btnSaveClick(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormDestroy(Sender: TObject); - procedure FormShow(Sender: TObject); - procedure pbAreaMouseDown(Sender: TObject; Button: TMouseButton; - Shift: TShiftState; X, Y: Integer); - procedure pbAreaMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer - ); - procedure pbAreaPaint(Sender: TObject); - procedure seX1Change(Sender: TObject); - procedure vstAreaChange(Sender: TBaseVirtualTree; Node: PVirtualNode); - procedure vstAreaGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; - Column: TColumnIndex; TextType: TVSTTextType; var CellText: UTF8String); - procedure vstRegionsChange(Sender: TBaseVirtualTree; Node: PVirtualNode); - procedure vstRegionsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); - procedure vstRegionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; - Column: TColumnIndex; TextType: TVSTTextType; var CellText: UTF8String); - protected - FLastX: Integer; - FLastY: Integer; - FAreaMove: TAreaMove; - FTempRegionNode: PVirtualNode; - FOnRegionModified: TRegionModifiedEvent; - FOnRegionDeleted: TRegionDeletedEvent; - FOnRegionList: TRegionListEvent; - function FindRegion(AName: string): PVirtualNode; - procedure CheckUnsaved; - procedure OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream); - procedure OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream); - procedure OnListRegionsPacket(ABuffer: TEnhancedMemoryStream); - procedure OnAccessChanged(AAccessLevel: TAccessLevel); - public - property OnRegionModified: TRegionModifiedEvent read FOnRegionModified write FOnRegionModified; - property OnRegionDeleted: TRegionDeletedEvent read FOnRegionDeleted write FOnRegionDeleted; - property OnRegionList: TRegionListEvent read FOnRegionList write FOnRegionList; - end; - -var - frmRegionControl: TfrmRegionControl; - -implementation - -uses - UGameResources, UfrmRadar, UfrmMain, UdmNetwork, UPacket, UGUIPlatformUtils, - UAdminHandling, UPacketHandlers; - -type - { TModifyRegionPacket } - - TModifyRegionPacket = class(TPacket) - constructor Create(ARegionInfo: TRegionInfo); - end; - - { TDeleteRegionPacket } - - TDeleteRegionPacket = class(TPacket) - constructor Create(AName: string); - end; - - { TRequestRegionListPacket } - - TRequestRegionListPacket = class(TPacket) - constructor Create; - end; - -{ TModifyRegionPacket } - -constructor TModifyRegionPacket.Create(ARegionInfo: TRegionInfo); -var - i: Integer; - count: Byte; - area: TRect; -begin - inherited Create($03, 0); //Admin Packet - FStream.WriteByte($08); //Admin PacketID - FStream.WriteStringNull(ARegionInfo.Name); - count := Min(ARegionInfo.Areas.Count, 256); - FStream.WriteByte(count); - for i := 0 to count - 1 do - begin - area := ARegionInfo.Areas.Rects[i]; - FStream.WriteWord(area.Left); - FStream.WriteWord(area.Top); - FStream.WriteWord(area.Right); - FStream.WriteWord(area.Bottom); - end; -end; - -{ TDeleteRegionPacket } - -constructor TDeleteRegionPacket.Create(AName: string); -begin - inherited Create($03, 0); //Admin Packet - FStream.WriteByte($09); //Admin PacketID - FStream.WriteStringNull(AName); -end; - -{ TRequestRegionListPacket } - -constructor TRequestRegionListPacket.Create; -begin - inherited Create($03, 0); //Admin Packet - FStream.WriteByte($0A); //Admin PacketID -end; - -{ TfrmRegionControl } - -procedure TfrmRegionControl.FormCreate(Sender: TObject); -begin - pbArea.Width := frmRadarMap.Radar.Width; - pbArea.Height := frmRadarMap.Radar.Height; - seX1.MaxValue := ResMan.Landscape.CellWidth; - seX2.MaxValue := ResMan.Landscape.CellWidth; - seY1.MaxValue := ResMan.Landscape.CellHeight; - seY2.MaxValue := ResMan.Landscape.CellHeight; - - vstArea.NodeDataSize := SizeOf(TRect); - vstRegions.NodeDataSize := SizeOf(TRegionInfo); - - FTempRegionNode := nil; - - frmRadarMap.Dependencies.Add(pbArea); - frmMain.RegisterAccessChangedListener(@OnAccessChanged); - - AssignAdminPacketHandler($08, TPacketHandler.Create(0, @OnModifyRegionPacket)); - AssignAdminPacketHandler($09, TPacketHandler.Create(0, @OnDeleteRegionPacket)); - AssignAdminPacketHandler($0A, TPacketHandler.Create(0, @OnListRegionsPacket)); - - dmNetwork.Send(TRequestRegionListPacket.Create); -end; - -procedure TfrmRegionControl.FormDestroy(Sender: TObject); -begin - frmRadarMap.Dependencies.Remove(pbArea); - if AdminPacketHandlers[$08] <> nil then FreeAndNil(AdminPacketHandlers[$08]); - if AdminPacketHandlers[$09] <> nil then FreeAndNil(AdminPacketHandlers[$09]); - if AdminPacketHandlers[$0A] <> nil then FreeAndNil(AdminPacketHandlers[$0A]); -end; - -procedure TfrmRegionControl.FormShow(Sender: TObject); -begin - SetWindowParent(Handle, frmMain.Handle); - btnSave.Enabled := False; //no changes yet -end; - -procedure TfrmRegionControl.btnSaveClick(Sender: TObject); -var - regionNode: PVirtualNode; - regionInfo: PRegionInfo; - areaNode: PVirtualNode; - areaInfo: PRect; -begin - btnSave.Enabled := False; - - //Refresh the current region - if FTempRegionNode <> nil then - regionNode := FTempRegionNode - else - regionNode := vstRegions.GetFirstSelected; - if regionNode <> nil then - begin - regionInfo := vstRegions.GetNodeData(regionNode); - regionInfo^.Areas.Clear; - areaNode := vstArea.GetFirst; - while areaNode <> nil do - begin - areaInfo := vstArea.GetNodeData(areaNode); - regionInfo^.Areas.Add(areaInfo^.Left, areaInfo^.Top, areaInfo^.Right, - areaInfo^.Bottom); - areaNode := vstArea.GetNext(areaNode); - end; - - //Send the modified values - dmNetwork.Send(TModifyRegionPacket.Create(regionInfo^)); - end; - - //Clear the selection - vstRegions.ClearSelection; - - FTempRegionNode := nil; -end; - -procedure TfrmRegionControl.mnuAddRegionClick(Sender: TObject); -var - regionName: string; - regionInfo: PRegionInfo; -begin - regionName := ''; - if InputQuery('New Region', 'Enter the name for the new region:', regionName) then - begin - CheckUnsaved; - - if FindRegion(regionName) = nil then - begin - FTempRegionNode := vstRegions.AddChild(nil); - regionInfo := vstRegions.GetNodeData(FTempRegionNode); - regionInfo^.Name := regionName; - regionInfo^.Areas := TRectList.Create; - vstRegions.ClearSelection; - vstRegions.Selected[FTempRegionNode] := True; - btnSave.Enabled := True; - end else - begin - MessageDlg('New Region', 'The region could not be added. A region with ' + - 'that name already exists.', mtError, [mbOK], 0); - end; - end; -end; - -procedure TfrmRegionControl.FormClose(Sender: TObject; - var CloseAction: TCloseAction); -begin - CheckUnsaved; -end; - -procedure TfrmRegionControl.mnuDeleteRegionClick(Sender: TObject); -var - regionNode: PVirtualNode; - regionInfo: PRegionInfo; -begin - regionNode := vstRegions.GetFirstSelected; - if (regionNode <> nil) and (MessageDlg('Delete Region', 'Are you sure, you ' + - 'want to delete the selected region?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) then - begin - regionInfo := vstRegions.GetNodeData(regionNode); - dmNetwork.Send(TDeleteRegionPacket.Create(regionInfo^.Name)); - vstRegions.Selected[regionNode] := False; - end; -end; - -procedure TfrmRegionControl.btnAddAreaClick(Sender: TObject); -var - node: PVirtualNode; - areaInfo: PRect; -begin - node := vstArea.AddChild(nil); - areaInfo := vstArea.GetNodeData(node); - areaInfo^.Left := 0; - areaInfo^.Top := 0; - areaInfo^.Right := 0; - areaInfo^.Bottom := 0; - vstArea.ClearSelection; - vstArea.Selected[node] := True; - vstArea.FocusedNode := node; - - btnSave.Enabled := True; //possible change to be saved -end; - -procedure TfrmRegionControl.btnClearAreaClick(Sender: TObject); -begin - vstArea.Clear; - vstAreaChange(vstArea, nil); -end; - -procedure TfrmRegionControl.btnCloseClick(Sender: TObject); -begin - Close; -end; - -procedure TfrmRegionControl.btnDeleteAreaClick(Sender: TObject); -begin - vstArea.DeleteSelectedNodes; - vstAreaChange(vstArea, nil); - - btnSave.Enabled := True; //possible change to be saved -end; - -procedure TfrmRegionControl.pbAreaMouseDown(Sender: TObject; - Button: TMouseButton; Shift: TShiftState; X, Y: Integer); -var - areaNode, match: PVirtualNode; - areaInfo: PRect; - p: TPoint; -begin - if vstRegions.GetFirstSelected = nil then Exit; - - FAreaMove := []; - p := Point(X * 8, Y * 8); - match := nil; - areaNode := vstArea.GetFirst; - while areaNode <> nil do //find the last matching area - begin - areaInfo := vstArea.GetNodeData(areaNode); - if PtInRect(areaInfo^, p) then - match := areaNode; - areaNode := vstArea.GetNext(areaNode); - end; - if match <> nil then - begin - areaInfo := vstArea.GetNodeData(match); - if p.x - areaInfo^.Left <= 64 then Include(FAreaMove, amLeft); - if p.y - areaInfo^.Top <= 64 then Include(FAreaMove, amTop); - if areaInfo^.Right - p.x <= 64 then Include(FAreaMove, amRight); - if areaInfo^.Bottom - p.y <= 64 then Include(FAreaMove, amBottom); - if FAreaMove = [] then - FAreaMove := [amLeft, amTop, amRight, amBottom]; - end else - begin - match := vstArea.AddChild(nil); - areaInfo := vstArea.GetNodeData(match); - areaInfo^.Left := p.x; - areaInfo^.Top := p.y; - areaInfo^.Right := p.x; - areaInfo^.Bottom := p.y; - pbArea.Repaint; - FAreaMove := [amRight, amBottom]; - end; - vstArea.ClearSelection; - vstArea.Selected[match] := True; - FLastX := X; - FLastY := Y; -end; - -procedure TfrmRegionControl.pbAreaMouseMove(Sender: TObject; - Shift: TShiftState; X, Y: Integer); -var - offsetX, offsetY: Integer; -begin - if (ssLeft in Shift) and (vstArea.GetFirstSelected <> nil) then - begin - offsetX := (X - FLastX) * 8; - offsetY := (Y - FLastY) * 8; - if amLeft in FAreaMove then seX1.Value := seX1.Value + offsetX; - if amRight in FAreaMove then seX2.Value := seX2.Value + offsetX; - if amTop in FAreaMove then seY1.Value := seY1.Value + offsetY; - if amBottom in FAreaMove then seY2.Value := seY2.Value + offsetY; - FLastX := X; - FLastY := Y; - seX1Change(nil); - end; -end; - -procedure TfrmRegionControl.pbAreaPaint(Sender: TObject); -var - node: PVirtualNode; - areaInfo: PRect; -begin - DisplayImage(pbArea.Canvas, 0, 0, frmRadarMap.Radar); - pbArea.Canvas.Pen.Color := clRed; - pbArea.Canvas.Brush.Color := clMaroon; - pbArea.Canvas.Brush.Style := bsFDiagonal; - node := vstArea.GetFirst; - while node <> nil do - begin - if vstArea.Selected[node] then - begin - pbArea.Canvas.Pen.Width := 2; - pbArea.Canvas.Pen.Style := psSolid; - end else - begin - pbArea.Canvas.Pen.Width := 1; - pbArea.Canvas.Pen.Style := psDot; - end; - areaInfo := vstArea.GetNodeData(node); - pbArea.Canvas.Rectangle(areaInfo^.Left div 8, areaInfo^.Top div 8, - areaInfo^.Right div 8 + 1, areaInfo^.Bottom div 8 + 1); - node := vstArea.GetNext(node); - end; -end; - -procedure TfrmRegionControl.seX1Change(Sender: TObject); -var - node: PVirtualNode; - areaInfo: PRect; -begin - node := vstArea.GetFirstSelected; - if node <> nil then - begin - areaInfo := vstArea.GetNodeData(node); - areaInfo^.Left := seX1.Value; - areaInfo^.Right := seX2.Value; - areaInfo^.Top := seY1.Value; - areaInfo^.Bottom := seY2.Value; - vstArea.InvalidateNode(node); - pbArea.Repaint; - - btnSave.Enabled := True; //possible change to be saved - end; -end; - -procedure TfrmRegionControl.vstAreaChange(Sender: TBaseVirtualTree; - Node: PVirtualNode); -var - areaInfo: PRect; - selected: Boolean; -begin - selected := (Node <> nil) and Sender.Selected[Node]; - btnDeleteArea.Enabled := selected; - lblX.Enabled := selected; - lblY.Enabled := selected; - seX1.Enabled := selected; - seX2.Enabled := selected; - seY1.Enabled := selected; - seY2.Enabled := selected; - if selected then - begin - areaInfo := Sender.GetNodeData(Node); - seX1.Value := areaInfo^.Left; - seX2.Value := areaInfo^.Right; - seY1.Value := areaInfo^.Top; - seY2.Value := areaInfo^.Bottom; - end; - pbArea.Repaint; -end; - -procedure TfrmRegionControl.vstAreaGetText(Sender: TBaseVirtualTree; - Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; - var CellText: UTF8String); -var - areaInfo: PRect; -begin - areaInfo := Sender.GetNodeData(Node); - CellText := Format('(%d, %d), (%d, %d)', [areaInfo^.Left, areaInfo^.Top, - areaInfo^.Right, areaInfo^.Bottom]); -end; - -procedure TfrmRegionControl.vstRegionsChange(Sender: TBaseVirtualTree; - Node: PVirtualNode); -var - i: Integer; - selected, areaNode: PVirtualNode; - regionInfo: PRegionInfo; - areaInfo: PRect; -begin - CheckUnsaved; - - vstArea.BeginUpdate; - vstArea.Clear; - selected := Sender.GetFirstSelected; - if selected <> nil then - begin - btnAddArea.Enabled := True; - btnClearArea.Enabled := True; - mnuDeleteRegion.Enabled := (selected <> FTempRegionNode); - btnDeleteRegion.Enabled := (selected <> FTempRegionNode); - - regionInfo := Sender.GetNodeData(selected); - for i := 0 to regionInfo^.Areas.Count - 1 do - begin - areaNode := vstArea.AddChild(nil); - areaInfo := vstArea.GetNodeData(areaNode); - with regionInfo^.Areas.Rects[i] do - begin - areaInfo^.Left := Left; - areaInfo^.Top := Top; - areaInfo^.Right := Right; - areaInfo^.Bottom := Bottom; - end; - end; - end else - begin - btnAddArea.Enabled := False; - btnDeleteArea.Enabled := False; - btnClearArea.Enabled := False; - mnuDeleteRegion.Enabled := False; - btnDeleteRegion.Enabled := False; - end; - vstArea.EndUpdate; - pbArea.Repaint; - - btnSave.Enabled := False; //no changes to be saved -end; - -procedure TfrmRegionControl.vstRegionsFreeNode(Sender: TBaseVirtualTree; - Node: PVirtualNode); -var - regionInfo: PRegionInfo; -begin - regionInfo := Sender.GetNodeData(Node); - regionInfo^.Name := ''; - if regionInfo^.Areas <> nil then FreeAndNil(regionInfo^.Areas); -end; - -procedure TfrmRegionControl.vstRegionsGetText(Sender: TBaseVirtualTree; - Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; - var CellText: UTF8String); -var - regionInfo: PRegionInfo; -begin - regionInfo := Sender.GetNodeData(Node); - CellText := UTF8Encode(regionInfo^.Name); -end; - -function TfrmRegionControl.FindRegion(AName: string): PVirtualNode; -var - regionInfo: PRegionInfo; - found: Boolean; -begin - found := False; - Result := vstRegions.GetFirst; - while (Result <> nil) and (not found) do - begin - regionInfo := vstRegions.GetNodeData(Result); - if regionInfo^.Name = AName then - found := True - else - Result := vstRegions.GetNext(Result); - end; -end; - -procedure TfrmRegionControl.CheckUnsaved; -begin - if btnSave.Enabled then - begin - if MessageDlg('Unsaved changes', 'There are unsaved ' + - 'changes.' + #13#10+#13#10+ 'Do you want to save them now?', - mtConfirmation, [mbYes, mbNo], 0) = mrYes then - begin - btnSaveClick(nil); - end else if FTempRegionNode <> nil then - begin - btnSave.Enabled := False; - vstRegions.DeleteNode(FTempRegionNode); - FTempRegionNode := nil; - end; - end; -end; - -procedure TfrmRegionControl.OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream); -var - regionName: string; - regionNode: PVirtualNode; - regionInfo: PRegionInfo; - areaCount: Byte; - i: Integer; - x1, y1, x2, y2: Word; -begin - ABuffer.ReadByte; //status, not used yet - - //TODO : Ask user how to proceed, if the added/modified packet conflicts with the currently edited region - - regionName := ABuffer.ReadStringNull; - regionNode := FindRegion(regionName); - if regionNode = nil then - begin - regionNode := vstRegions.AddChild(nil); - regionInfo := vstRegions.GetNodeData(regionNode); - regionInfo^.Name := regionName; - regionInfo^.Areas := TRectList.Create; - end else - begin - regionInfo := vstRegions.GetNodeData(regionNode); - regionInfo^.Areas.Clear; - end; - - areaCount := ABuffer.ReadByte; - for i := 0 to areaCount - 1 do - begin - x1 := ABuffer.ReadWord; - y1 := ABuffer.ReadWord; - x2 := ABuffer.ReadWord; - y2 := ABuffer.ReadWord; - regionInfo^.Areas.Add(x1, y1, x2, y2); - end; - - if vstRegions.Selected[regionNode] then - begin - btnSave.Enabled := False; - vstRegionsChange(vstRegions, regionNode); - end; - - if Assigned(FOnRegionModified) then - FOnRegionModified(regionInfo^); -end; - -procedure TfrmRegionControl.OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream); -var - regionName: string; - regionNode: PVirtualNode; -begin - ABuffer.ReadByte; //status, not used yet - regionName := ABuffer.ReadStringNull; - regionNode := FindRegion(regionName); - - //TODO : Ask user how to proceed, if the deleted packet conflicts with the currently edited region - - if regionNode <> nil then - vstRegions.DeleteNode(regionNode); - - if Assigned(FOnRegionDeleted) then - FOnRegionDeleted(regionName); -end; - -procedure TfrmRegionControl.OnListRegionsPacket(ABuffer: TEnhancedMemoryStream); -var - regionCount, areaCount: Byte; - i, j, x1, x2, y1, y2: Integer; - node: PVirtualNode; - regionInfo: PRegionInfo; -begin - vstRegions.BeginUpdate; - vstRegions.Clear; - regionCount := ABuffer.ReadByte; - for i := 0 to regionCount - 1 do - begin - node := vstRegions.AddChild(nil); - regionInfo := vstRegions.GetNodeData(node); - regionInfo^.Name := ABuffer.ReadStringNull; - regionInfo^.Areas := TRectList.Create; - areaCount := ABuffer.ReadByte; - for j := 0 to areaCount - 1 do - begin - x1 := ABuffer.ReadWord; - y1 := ABuffer.ReadWord; - x2 := ABuffer.ReadWord; - y2 := ABuffer.ReadWord; - regionInfo^.Areas.Add(x1, y1, x2, y2); - end; - end; - vstRegions.EndUpdate; - - if Assigned(FOnRegionList) then - FOnRegionList; -end; - -procedure TfrmRegionControl.OnAccessChanged(AAccessLevel: TAccessLevel); -begin - if AAccessLevel >= alAdministrator then - dmNetwork.Send(TRequestRegionListPacket.Create); -end; - -initialization - {$I UfrmRegionControl.lrs} - -end. +(* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at + * http://www.opensource.org/licenses/cddl1.php. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at + * http://www.opensource.org/licenses/cddl1.php. If applicable, + * add the following below this CDDL HEADER, with the fields enclosed + * by brackets "[]" replaced with your own identifying * information: + * Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * + * Portions Copyright 2009 Andreas Schneider + *) +unit UfrmRegionControl; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, math, LResources, Forms, Controls, Graphics, Dialogs, + VirtualTrees, ExtCtrls, ImagingComponents, StdCtrls, Buttons, Spin, LCLIntf, + UEnhancedMemoryStream, Menus, URectList, UEnums, UWorldItem; + +type + TAreaMoveType = (amLeft, amTop, amRight, amBottom); + TAreaMove = set of TAreaMoveType; + + PRegionInfo = ^TRegionInfo; + TRegionInfo = record + Name: string; + Areas: TRectList; + end; + + TRegionModifiedEvent = procedure(ARegionInfo: TRegionInfo) of object; + TRegionDeletedEvent = procedure(ARegionName: string) of object; + TRegionListEvent = procedure of object; + + { TfrmRegionControl } + + TfrmRegionControl = class(TForm) + btnAddArea: TSpeedButton; + btnAddRegion: TSpeedButton; + btnClearArea: TSpeedButton; + btnClose: TButton; + btnDeleteArea: TSpeedButton; + btnDeleteRegion: TSpeedButton; + btnSave: TButton; + Label1: TLabel; + lblX: TLabel; + lblY: TLabel; + mnuAddRegion: TMenuItem; + mnuDeleteRegion: TMenuItem; + pbArea: TPaintBox; + pmRegions: TPopupMenu; + sbArea: TScrollBox; + seX1: TSpinEdit; + seX2: TSpinEdit; + seY1: TSpinEdit; + seY2: TSpinEdit; + btnGrab1: TSpeedButton; + btnGrab2: TSpeedButton; + spRegionsArea: TSplitter; + vstArea: TVirtualStringTree; + vstRegions: TVirtualStringTree; + procedure btnGrab1Click(Sender: TObject); + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); + procedure mnuAddRegionClick(Sender: TObject); + procedure mnuDeleteRegionClick(Sender: TObject); + procedure btnAddAreaClick(Sender: TObject); + procedure btnClearAreaClick(Sender: TObject); + procedure btnCloseClick(Sender: TObject); + procedure btnDeleteAreaClick(Sender: TObject); + procedure btnSaveClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure pbAreaMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); + procedure pbAreaMouseMove(Sender: TObject; Shift: TShiftState; X, + Y: Integer); + procedure pbAreaPaint(Sender: TObject); + procedure seX1Change(Sender: TObject); + procedure vstAreaChange(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure vstAreaGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex; TextType: TVSTTextType; var CellText: UTF8String); + procedure vstRegionsChange(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure vstRegionsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); + procedure vstRegionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; + Column: TColumnIndex; TextType: TVSTTextType; var CellText: UTF8String); + protected + FLastX: Integer; + FLastY: Integer; + FAreaMove: TAreaMove; + FTempRegionNode: PVirtualNode; + FOnRegionModified: TRegionModifiedEvent; + FOnRegionDeleted: TRegionDeletedEvent; + FOnRegionList: TRegionListEvent; + FSelectFirst: Boolean; + FOldWindowState: TWindowState; + function FindRegion(AName: string): PVirtualNode; + procedure CheckUnsaved; + procedure OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream); + procedure OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream); + procedure OnListRegionsPacket(ABuffer: TEnhancedMemoryStream); + procedure OnAccessChanged(AAccessLevel: TAccessLevel); + procedure TileSelected(AWorldItem: TWorldItem); + public + property OnRegionModified: TRegionModifiedEvent read FOnRegionModified write FOnRegionModified; + property OnRegionDeleted: TRegionDeletedEvent read FOnRegionDeleted write FOnRegionDeleted; + property OnRegionList: TRegionListEvent read FOnRegionList write FOnRegionList; + end; + +var + frmRegionControl: TfrmRegionControl; + +implementation + +uses + UGameResources, UfrmRadar, UfrmMain, UdmNetwork, UPacket, UGUIPlatformUtils, + UAdminHandling, UPacketHandlers; + +type + { TModifyRegionPacket } + + TModifyRegionPacket = class(TPacket) + constructor Create(ARegionInfo: TRegionInfo); + end; + + { TDeleteRegionPacket } + + TDeleteRegionPacket = class(TPacket) + constructor Create(AName: string); + end; + + { TRequestRegionListPacket } + + TRequestRegionListPacket = class(TPacket) + constructor Create; + end; + +{ TModifyRegionPacket } + +constructor TModifyRegionPacket.Create(ARegionInfo: TRegionInfo); +var + i: Integer; + count: Byte; + area: TRect; +begin + inherited Create($03, 0); //Admin Packet + FStream.WriteByte($08); //Admin PacketID + FStream.WriteStringNull(ARegionInfo.Name); + count := Min(ARegionInfo.Areas.Count, 256); + FStream.WriteByte(count); + for i := 0 to count - 1 do + begin + area := ARegionInfo.Areas.Rects[i]; + FStream.WriteWord(area.Left); + FStream.WriteWord(area.Top); + FStream.WriteWord(area.Right); + FStream.WriteWord(area.Bottom); + end; +end; + +{ TDeleteRegionPacket } + +constructor TDeleteRegionPacket.Create(AName: string); +begin + inherited Create($03, 0); //Admin Packet + FStream.WriteByte($09); //Admin PacketID + FStream.WriteStringNull(AName); +end; + +{ TRequestRegionListPacket } + +constructor TRequestRegionListPacket.Create; +begin + inherited Create($03, 0); //Admin Packet + FStream.WriteByte($0A); //Admin PacketID +end; + +{ TfrmRegionControl } + +procedure TfrmRegionControl.FormCreate(Sender: TObject); +begin + pbArea.Width := frmRadarMap.Radar.Width; + pbArea.Height := frmRadarMap.Radar.Height; + seX1.MaxValue := ResMan.Landscape.CellWidth; + seX2.MaxValue := ResMan.Landscape.CellWidth; + seY1.MaxValue := ResMan.Landscape.CellHeight; + seY2.MaxValue := ResMan.Landscape.CellHeight; + + vstArea.NodeDataSize := SizeOf(TRect); + vstRegions.NodeDataSize := SizeOf(TRegionInfo); + + FTempRegionNode := nil; + + frmRadarMap.Dependencies.Add(pbArea); + frmMain.RegisterAccessChangedListener(@OnAccessChanged); + + AssignAdminPacketHandler($08, TPacketHandler.Create(0, @OnModifyRegionPacket)); + AssignAdminPacketHandler($09, TPacketHandler.Create(0, @OnDeleteRegionPacket)); + AssignAdminPacketHandler($0A, TPacketHandler.Create(0, @OnListRegionsPacket)); + + dmNetwork.Send(TRequestRegionListPacket.Create); +end; + +procedure TfrmRegionControl.FormDestroy(Sender: TObject); +begin + frmRadarMap.Dependencies.Remove(pbArea); + FreeAndNil(AdminPacketHandlers[$08]); + FreeAndNil(AdminPacketHandlers[$09]); + FreeAndNil(AdminPacketHandlers[$0A]); +end; + +procedure TfrmRegionControl.FormShow(Sender: TObject); +begin + SetWindowParent(Handle, frmMain.Handle); + btnSave.Enabled := False; //no changes yet +end; + +procedure TfrmRegionControl.btnSaveClick(Sender: TObject); +var + regionNode: PVirtualNode; + regionInfo: PRegionInfo; + areaNode: PVirtualNode; + areaInfo: PRect; +begin + btnSave.Enabled := False; + + //Refresh the current region + if FTempRegionNode <> nil then + regionNode := FTempRegionNode + else + regionNode := vstRegions.GetFirstSelected; + if regionNode <> nil then + begin + regionInfo := vstRegions.GetNodeData(regionNode); + regionInfo^.Areas.Clear; + areaNode := vstArea.GetFirst; + while areaNode <> nil do + begin + areaInfo := vstArea.GetNodeData(areaNode); + regionInfo^.Areas.Add(areaInfo^.Left, areaInfo^.Top, areaInfo^.Right, + areaInfo^.Bottom); + areaNode := vstArea.GetNext(areaNode); + end; + + //Send the modified values + dmNetwork.Send(TModifyRegionPacket.Create(regionInfo^)); + end; + + //Clear the selection + vstRegions.ClearSelection; + + FTempRegionNode := nil; +end; + +procedure TfrmRegionControl.mnuAddRegionClick(Sender: TObject); +var + regionName: string; + regionInfo: PRegionInfo; +begin + regionName := ''; + if InputQuery('New Region', 'Enter the name for the new region:', regionName) then + begin + CheckUnsaved; + + if FindRegion(regionName) = nil then + begin + FTempRegionNode := vstRegions.AddChild(nil); + regionInfo := vstRegions.GetNodeData(FTempRegionNode); + regionInfo^.Name := regionName; + regionInfo^.Areas := TRectList.Create; + vstRegions.ClearSelection; + vstRegions.Selected[FTempRegionNode] := True; + btnSave.Enabled := True; + end else + begin + MessageDlg('New Region', 'The region could not be added. A region with ' + + 'that name already exists.', mtError, [mbOK], 0); + end; + end; +end; + +procedure TfrmRegionControl.FormClose(Sender: TObject; + var CloseAction: TCloseAction); +begin + CheckUnsaved; +end; + +procedure TfrmRegionControl.btnGrab1Click(Sender: TObject); +begin + FSelectFirst := (Sender = btnGrab1); + frmMain.RegisterSelectionListener(@TileSelected); + FOldWindowState := WindowState; + WindowState := wsMinimized; + frmMain.SwitchToSelection; +end; + +procedure TfrmRegionControl.mnuDeleteRegionClick(Sender: TObject); +var + regionNode: PVirtualNode; + regionInfo: PRegionInfo; +begin + regionNode := vstRegions.GetFirstSelected; + if (regionNode <> nil) and (MessageDlg('Delete Region', 'Are you sure, you ' + + 'want to delete the selected region?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) then + begin + regionInfo := vstRegions.GetNodeData(regionNode); + dmNetwork.Send(TDeleteRegionPacket.Create(regionInfo^.Name)); + vstRegions.Selected[regionNode] := False; + end; +end; + +procedure TfrmRegionControl.btnAddAreaClick(Sender: TObject); +var + node: PVirtualNode; + areaInfo: PRect; +begin + node := vstArea.AddChild(nil); + areaInfo := vstArea.GetNodeData(node); + areaInfo^.Left := 0; + areaInfo^.Top := 0; + areaInfo^.Right := 0; + areaInfo^.Bottom := 0; + vstArea.ClearSelection; + vstArea.Selected[node] := True; + vstArea.FocusedNode := node; + + btnSave.Enabled := True; //possible change to be saved +end; + +procedure TfrmRegionControl.btnClearAreaClick(Sender: TObject); +begin + vstArea.Clear; + vstAreaChange(vstArea, nil); +end; + +procedure TfrmRegionControl.btnCloseClick(Sender: TObject); +begin + Close; +end; + +procedure TfrmRegionControl.btnDeleteAreaClick(Sender: TObject); +begin + vstArea.DeleteSelectedNodes; + vstAreaChange(vstArea, nil); + + btnSave.Enabled := True; //possible change to be saved +end; + +procedure TfrmRegionControl.pbAreaMouseDown(Sender: TObject; + Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + areaNode, match: PVirtualNode; + areaInfo: PRect; + p: TPoint; +begin + if vstRegions.GetFirstSelected = nil then Exit; + + FAreaMove := []; + p := Point(X * 8, Y * 8); + match := nil; + areaNode := vstArea.GetFirst; + while areaNode <> nil do //find the last matching area + begin + areaInfo := vstArea.GetNodeData(areaNode); + if PtInRect(areaInfo^, p) then + match := areaNode; + areaNode := vstArea.GetNext(areaNode); + end; + if match <> nil then + begin + areaInfo := vstArea.GetNodeData(match); + if p.x - areaInfo^.Left <= 64 then Include(FAreaMove, amLeft); + if p.y - areaInfo^.Top <= 64 then Include(FAreaMove, amTop); + if areaInfo^.Right - p.x <= 64 then Include(FAreaMove, amRight); + if areaInfo^.Bottom - p.y <= 64 then Include(FAreaMove, amBottom); + if FAreaMove = [] then + FAreaMove := [amLeft, amTop, amRight, amBottom]; + end else + begin + match := vstArea.AddChild(nil); + areaInfo := vstArea.GetNodeData(match); + areaInfo^.Left := p.x; + areaInfo^.Top := p.y; + areaInfo^.Right := p.x; + areaInfo^.Bottom := p.y; + pbArea.Repaint; + FAreaMove := [amRight, amBottom]; + end; + vstArea.ClearSelection; + vstArea.Selected[match] := True; + FLastX := X; + FLastY := Y; +end; + +procedure TfrmRegionControl.pbAreaMouseMove(Sender: TObject; + Shift: TShiftState; X, Y: Integer); +var + offsetX, offsetY: Integer; +begin + if (ssLeft in Shift) and (vstArea.GetFirstSelected <> nil) then + begin + offsetX := (X - FLastX) * 8; + offsetY := (Y - FLastY) * 8; + if amLeft in FAreaMove then seX1.Value := seX1.Value + offsetX; + if amRight in FAreaMove then seX2.Value := seX2.Value + offsetX; + if amTop in FAreaMove then seY1.Value := seY1.Value + offsetY; + if amBottom in FAreaMove then seY2.Value := seY2.Value + offsetY; + FLastX := X; + FLastY := Y; + seX1Change(nil); + end; +end; + +procedure TfrmRegionControl.pbAreaPaint(Sender: TObject); +var + node: PVirtualNode; + areaInfo: PRect; +begin + DisplayImage(pbArea.Canvas, 0, 0, frmRadarMap.Radar); + pbArea.Canvas.Pen.Color := clRed; + pbArea.Canvas.Brush.Color := clMaroon; + pbArea.Canvas.Brush.Style := bsFDiagonal; + node := vstArea.GetFirst; + while node <> nil do + begin + if vstArea.Selected[node] then + begin + pbArea.Canvas.Pen.Width := 2; + pbArea.Canvas.Pen.Style := psSolid; + end else + begin + pbArea.Canvas.Pen.Width := 1; + pbArea.Canvas.Pen.Style := psDot; + end; + areaInfo := vstArea.GetNodeData(node); + pbArea.Canvas.Rectangle(areaInfo^.Left div 8, areaInfo^.Top div 8, + areaInfo^.Right div 8 + 1, areaInfo^.Bottom div 8 + 1); + node := vstArea.GetNext(node); + end; +end; + +procedure TfrmRegionControl.seX1Change(Sender: TObject); +var + node: PVirtualNode; + areaInfo: PRect; +begin + node := vstArea.GetFirstSelected; + if node <> nil then + begin + areaInfo := vstArea.GetNodeData(node); + areaInfo^.Left := seX1.Value; + areaInfo^.Right := seX2.Value; + areaInfo^.Top := seY1.Value; + areaInfo^.Bottom := seY2.Value; + vstArea.InvalidateNode(node); + pbArea.Repaint; + + btnSave.Enabled := True; //possible change to be saved + end; +end; + +procedure TfrmRegionControl.vstAreaChange(Sender: TBaseVirtualTree; + Node: PVirtualNode); +var + areaInfo: PRect; + selected: Boolean; +begin + selected := (Node <> nil) and Sender.Selected[Node]; + btnDeleteArea.Enabled := selected; + lblX.Enabled := selected; + lblY.Enabled := selected; + seX1.Enabled := selected; + seX2.Enabled := selected; + seY1.Enabled := selected; + seY2.Enabled := selected; + btnGrab1.Enabled := selected; + btnGrab2.Enabled := selected; + if selected then + begin + areaInfo := Sender.GetNodeData(Node); + seX1.Value := areaInfo^.Left; + seX2.Value := areaInfo^.Right; + seY1.Value := areaInfo^.Top; + seY2.Value := areaInfo^.Bottom; + end; + pbArea.Repaint; +end; + +procedure TfrmRegionControl.vstAreaGetText(Sender: TBaseVirtualTree; + Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; + var CellText: UTF8String); +var + areaInfo: PRect; +begin + areaInfo := Sender.GetNodeData(Node); + CellText := Format('(%d, %d), (%d, %d)', [areaInfo^.Left, areaInfo^.Top, + areaInfo^.Right, areaInfo^.Bottom]); +end; + +procedure TfrmRegionControl.vstRegionsChange(Sender: TBaseVirtualTree; + Node: PVirtualNode); +var + i: Integer; + selected, areaNode: PVirtualNode; + regionInfo: PRegionInfo; + areaInfo: PRect; +begin + CheckUnsaved; + + vstArea.BeginUpdate; + vstArea.Clear; + selected := Sender.GetFirstSelected; + if selected <> nil then + begin + btnAddArea.Enabled := True; + btnClearArea.Enabled := True; + mnuDeleteRegion.Enabled := (selected <> FTempRegionNode); + btnDeleteRegion.Enabled := (selected <> FTempRegionNode); + + regionInfo := Sender.GetNodeData(selected); + for i := 0 to regionInfo^.Areas.Count - 1 do + begin + areaNode := vstArea.AddChild(nil); + areaInfo := vstArea.GetNodeData(areaNode); + with regionInfo^.Areas.Rects[i] do + begin + areaInfo^.Left := Left; + areaInfo^.Top := Top; + areaInfo^.Right := Right; + areaInfo^.Bottom := Bottom; + end; + end; + end else + begin + btnAddArea.Enabled := False; + btnDeleteArea.Enabled := False; + btnClearArea.Enabled := False; + mnuDeleteRegion.Enabled := False; + btnDeleteRegion.Enabled := False; + end; + vstArea.EndUpdate; + pbArea.Repaint; + + btnSave.Enabled := False; //no changes to be saved +end; + +procedure TfrmRegionControl.vstRegionsFreeNode(Sender: TBaseVirtualTree; + Node: PVirtualNode); +var + regionInfo: PRegionInfo; +begin + regionInfo := Sender.GetNodeData(Node); + regionInfo^.Name := ''; + if regionInfo^.Areas <> nil then FreeAndNil(regionInfo^.Areas); +end; + +procedure TfrmRegionControl.vstRegionsGetText(Sender: TBaseVirtualTree; + Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; + var CellText: UTF8String); +var + regionInfo: PRegionInfo; +begin + regionInfo := Sender.GetNodeData(Node); + CellText := UTF8Encode(regionInfo^.Name); +end; + +function TfrmRegionControl.FindRegion(AName: string): PVirtualNode; +var + regionInfo: PRegionInfo; + found: Boolean; +begin + found := False; + Result := vstRegions.GetFirst; + while (Result <> nil) and (not found) do + begin + regionInfo := vstRegions.GetNodeData(Result); + if regionInfo^.Name = AName then + found := True + else + Result := vstRegions.GetNext(Result); + end; +end; + +procedure TfrmRegionControl.CheckUnsaved; +begin + if btnSave.Enabled then + begin + if MessageDlg('Unsaved changes', 'There are unsaved ' + + 'changes.' + #13#10+#13#10+ 'Do you want to save them now?', + mtConfirmation, [mbYes, mbNo], 0) = mrYes then + begin + btnSaveClick(nil); + end else if FTempRegionNode <> nil then + begin + btnSave.Enabled := False; + vstRegions.DeleteNode(FTempRegionNode); + FTempRegionNode := nil; + end; + end; +end; + +procedure TfrmRegionControl.OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream); +var + regionName: string; + regionNode: PVirtualNode; + regionInfo: PRegionInfo; + areaCount: Byte; + i: Integer; + x1, y1, x2, y2: Word; +begin + ABuffer.ReadByte; //status, not used yet + + //TODO : Ask user how to proceed, if the added/modified packet conflicts with the currently edited region + + regionName := ABuffer.ReadStringNull; + regionNode := FindRegion(regionName); + if regionNode = nil then + begin + regionNode := vstRegions.AddChild(nil); + regionInfo := vstRegions.GetNodeData(regionNode); + regionInfo^.Name := regionName; + regionInfo^.Areas := TRectList.Create; + end else + begin + regionInfo := vstRegions.GetNodeData(regionNode); + regionInfo^.Areas.Clear; + end; + + areaCount := ABuffer.ReadByte; + for i := 0 to areaCount - 1 do + begin + x1 := ABuffer.ReadWord; + y1 := ABuffer.ReadWord; + x2 := ABuffer.ReadWord; + y2 := ABuffer.ReadWord; + regionInfo^.Areas.Add(x1, y1, x2, y2); + end; + + if vstRegions.Selected[regionNode] then + begin + btnSave.Enabled := False; + vstRegionsChange(vstRegions, regionNode); + end; + + if Assigned(FOnRegionModified) then + FOnRegionModified(regionInfo^); +end; + +procedure TfrmRegionControl.OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream); +var + regionName: string; + regionNode: PVirtualNode; +begin + ABuffer.ReadByte; //status, not used yet + regionName := ABuffer.ReadStringNull; + regionNode := FindRegion(regionName); + + //TODO : Ask user how to proceed, if the deleted packet conflicts with the currently edited region + + if regionNode <> nil then + vstRegions.DeleteNode(regionNode); + + if Assigned(FOnRegionDeleted) then + FOnRegionDeleted(regionName); +end; + +procedure TfrmRegionControl.OnListRegionsPacket(ABuffer: TEnhancedMemoryStream); +var + regionCount, areaCount: Byte; + i, j, x1, x2, y1, y2: Integer; + node: PVirtualNode; + regionInfo: PRegionInfo; +begin + vstRegions.BeginUpdate; + vstRegions.Clear; + regionCount := ABuffer.ReadByte; + for i := 0 to regionCount - 1 do + begin + node := vstRegions.AddChild(nil); + regionInfo := vstRegions.GetNodeData(node); + regionInfo^.Name := ABuffer.ReadStringNull; + regionInfo^.Areas := TRectList.Create; + areaCount := ABuffer.ReadByte; + for j := 0 to areaCount - 1 do + begin + x1 := ABuffer.ReadWord; + y1 := ABuffer.ReadWord; + x2 := ABuffer.ReadWord; + y2 := ABuffer.ReadWord; + regionInfo^.Areas.Add(x1, y1, x2, y2); + end; + end; + vstRegions.EndUpdate; + + if Assigned(FOnRegionList) then + FOnRegionList; +end; + +procedure TfrmRegionControl.OnAccessChanged(AAccessLevel: TAccessLevel); +begin + if AAccessLevel >= alAdministrator then + dmNetwork.Send(TRequestRegionListPacket.Create); +end; + +procedure TfrmRegionControl.TileSelected(AWorldItem: TWorldItem); +begin + if FSelectFirst then + begin + seX1.Value := AWorldItem.X; + seY1.Value := AWorldItem.Y; + end else + begin + seX2.Value := AWorldItem.X; + seY2.Value := AWorldItem.Y; + end; + frmMain.UnregisterSelectionListener(@TileSelected); + WindowState := FOldWindowState; + seX1Change(nil); +end; + +initialization + {$I UfrmRegionControl.lrs} + +end.