diff --git a/Editor.xib b/Editor.xib
deleted file mode 100644
index 724fcb6..0000000
--- a/Editor.xib
+++ /dev/null
@@ -1,515 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- FilesCountTransformer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- name
-
-
- address
-
-
- sign
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- NSNegateBoolean
-
-
-
-
-
-
-
-
-
-
-
-
-
- NSNegateBoolean
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- title
- contents
- saved
- active
- name
- editable
- exists
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- name
-
-
- address
-
-
- sign
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Gas Mask.xcodeproj/project.pbxproj b/Gas Mask.xcodeproj/project.pbxproj
index 0e9c3ec..61f07fc 100644
--- a/Gas Mask.xcodeproj/project.pbxproj
+++ b/Gas Mask.xcodeproj/project.pbxproj
@@ -13,18 +13,13 @@
350920C51226EDD600ACA0F4 /* AbstractHostsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 350920C41226EDD600ACA0F4 /* AbstractHostsManager.m */; };
350C7F391A3C55B000B46B09 /* Create@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 350C7F381A3C55B000B46B09 /* Create@2x.png */; };
350C7F3B1A3C56BB00B46B09 /* Read Only@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 350C7F3A1A3C56BB00B46B09 /* Read Only@2x.png */; };
- 350E7D3E121093E400D2F5F5 /* AlertBadge.m in Sources */ = {isa = PBXBuildFile; fileRef = 350E7D3D121093E400D2F5F5 /* AlertBadge.m */; };
- 350E7D7E12111B2300D2F5F5 /* Badge.m in Sources */ = {isa = PBXBuildFile; fileRef = 350E7D7D12111B2300D2F5F5 /* Badge.m */; };
- 350E7D941211A7AE00D2F5F5 /* BadgeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 350E7D931211A7AE00D2F5F5 /* BadgeManager.m */; };
351167C010D6346000A5FAA1 /* HostsGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 351167BF10D6346000A5FAA1 /* HostsGroup.m */; };
- 3511697810D68B1000A5FAA1 /* FilesCountTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3511697710D68B1000A5FAA1 /* FilesCountTransformer.m */; };
35116A7010D6AAD200A5FAA1 /* Menulet.m in Sources */ = {isa = PBXBuildFile; fileRef = 35116A6F10D6AAD200A5FAA1 /* Menulet.m */; };
35116AC010D6AF0500A5FAA1 /* LoginItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 35116ABF10D6AF0500A5FAA1 /* LoginItem.m */; };
3513A600113908A900AD789D /* Read Only.png in Resources */ = {isa = PBXBuildFile; fileRef = 3513A5FF113908A900AD789D /* Read Only.png */; };
3513A61C11390B7900AD789D /* Error.m in Sources */ = {isa = PBXBuildFile; fileRef = 3513A61B11390B7900AD789D /* Error.m */; };
351416CF28C3A7B80093A452 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 351416CE28C3A7B80093A452 /* Sparkle */; };
AA1B2C3D4E5F000100000001 /* MASShortcut in Frameworks */ = {isa = PBXBuildFile; productRef = AA1B2C3D4E5F000200000001 /* MASShortcut */; };
- 3516864B11187EDE00314609 /* HostsTextController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3516864A11187EDE00314609 /* HostsTextController.m */; };
351D904510E76F7100CA6B5E /* Help in Resources */ = {isa = PBXBuildFile; fileRef = 351D904110E76F7100CA6B5E /* Help */; };
3522BEE0153316AA00035B90 /* ExtendedNSArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 3522BEDF153316AA00035B90 /* ExtendedNSArray.m */; };
3522BEE31533552200035B90 /* ExtendedNSPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3522BEE21533552200035B90 /* ExtendedNSPredicate.m */; };
@@ -34,14 +29,10 @@
3528ECEC10E3F87E003C8CB9 /* Syncing_arrows4.png in Resources */ = {isa = PBXBuildFile; fileRef = 3528ECE610E3F87E003C8CB9 /* Syncing_arrows4.png */; };
3528ECED10E3F87E003C8CB9 /* Syncing_arrows5.png in Resources */ = {isa = PBXBuildFile; fileRef = 3528ECE710E3F87E003C8CB9 /* Syncing_arrows5.png */; };
3528ECEE10E3F87E003C8CB9 /* Syncing_arrows6.png in Resources */ = {isa = PBXBuildFile; fileRef = 3528ECE810E3F87E003C8CB9 /* Syncing_arrows6.png */; };
- 352E048D106279F50071E25B /* ListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 352E048C106279F50071E25B /* ListController.m */; };
- 352E049F10627A830071E25B /* Editor.xib in Resources */ = {isa = PBXBuildFile; fileRef = 352E049E10627A830071E25B /* Editor.xib */; };
352E04BA10627C1D0071E25B /* ApplicationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 352E04B910627C1D0071E25B /* ApplicationController.m */; };
352E04FD106281940071E25B /* Create.png in Resources */ = {isa = PBXBuildFile; fileRef = 352E04F9106281940071E25B /* Create.png */; };
352E04FF106281940071E25B /* Save.png in Resources */ = {isa = PBXBuildFile; fileRef = 352E04FB106281940071E25B /* Save.png */; };
- 352E050E106283630071E25B /* EditorController.m in Sources */ = {isa = PBXBuildFile; fileRef = 352E050D106283630071E25B /* EditorController.m */; };
352E0556106288400071E25B /* Node.m in Sources */ = {isa = PBXBuildFile; fileRef = 352E0555106288400071E25B /* Node.m */; };
- 352E059310628A2F0071E25B /* Cell.m in Sources */ = {isa = PBXBuildFile; fileRef = 352E059210628A2F0071E25B /* Cell.m */; };
352E05B610628D790071E25B /* Activated.png in Resources */ = {isa = PBXBuildFile; fileRef = 352E05B310628D790071E25B /* Activated.png */; };
352E05B710628D790071E25B /* Blue Dot.png in Resources */ = {isa = PBXBuildFile; fileRef = 352E05B410628D790071E25B /* Blue Dot.png */; };
352E05DA10628E400071E25B /* Local File.png in Resources */ = {isa = PBXBuildFile; fileRef = 352E05D910628E400071E25B /* Local File.png */; };
@@ -54,16 +45,12 @@
353A80BB10B01C050005CAD1 /* Preferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 353A80BA10B01C050005CAD1 /* Preferences.m */; };
353A80CA10B01F320005CAD1 /* ExtendedNSString.m in Sources */ = {isa = PBXBuildFile; fileRef = 353A80C910B01F320005CAD1 /* ExtendedNSString.m */; };
353A80FC10B020B10005CAD1 /* UserDefaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 353A80FB10B020B10005CAD1 /* UserDefaults.plist */; };
- 3541CE0510E4AF9B00FA00CB /* SyncingArrowsBadge.m in Sources */ = {isa = PBXBuildFile; fileRef = 3541CE0410E4AF9B00FA00CB /* SyncingArrowsBadge.m */; };
3544E2D310E4CCB1009AC525 /* Map.m in Sources */ = {isa = PBXBuildFile; fileRef = 3544E2D210E4CCB1009AC525 /* Map.m */; };
3545DC7310E38DDE00EBA66D /* Offline.png in Resources */ = {isa = PBXBuildFile; fileRef = 3545DC7210E38DDE00EBA66D /* Offline.png */; };
3545DCA910E396CF00EBA66D /* Network.m in Sources */ = {isa = PBXBuildFile; fileRef = 3545DCA810E396CF00EBA66D /* Network.m */; };
3545DCE410E3997200EBA66D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3545DCE310E3997200EBA66D /* SystemConfiguration.framework */; };
- 3546AF7815318F48006B293B /* CombinedHostsPredicateController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3546AF7715318F48006B293B /* CombinedHostsPredicateController.m */; };
- 3546AF7F1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3546AF7E1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.m */; };
35498EDB12187F5D00E46952 /* Offline_rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 35498EDA12187F5D00E46952 /* Offline_rollover.png */; };
354C0BC510E782A5005B9A33 /* hosts.icns in Resources */ = {isa = PBXBuildFile; fileRef = 354C0BC410E782A5005B9A33 /* hosts.icns */; };
- 354CCF811117285300EB6948 /* HostsListViewMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 354CCF801117285300EB6948 /* HostsListViewMenu.m */; };
354E7E4010AEB09D00FC4757 /* HostsMainController.m in Sources */ = {isa = PBXBuildFile; fileRef = 354E7E3F10AEB09D00FC4757 /* HostsMainController.m */; };
354E7E7410AEB25100FC4757 /* Hosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 354E7E7310AEB25100FC4757 /* Hosts.m */; };
354E7EB110AEEF3D00FC4757 /* StructureConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 354E7EB010AEEF3D00FC4757 /* StructureConverter.m */; };
@@ -76,11 +63,9 @@
356218B510E52CD600772473 /* Growl Registration Ticket.growlRegDict in Resources */ = {isa = PBXBuildFile; fileRef = 356218B410E52CD600772473 /* Growl Registration Ticket.growlRegDict */; };
356712201132E2A700DF30E0 /* NetworkStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 3567121F1132E2A700DF30E0 /* NetworkStatus.m */; };
3569AEBF12303479007DF95F /* Preferences+Remote.m in Sources */ = {isa = PBXBuildFile; fileRef = 3569AEBE12303479007DF95F /* Preferences+Remote.m */; };
- 356DB76A1824EAFD0020CEA0 /* ExtendedNSSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 356DB7691824EAFD0020CEA0 /* ExtendedNSSplitView.m */; };
35730FCF113424C100066B68 /* RemoteHosts.m in Sources */ = {isa = PBXBuildFile; fileRef = 35730FCE113424C100066B68 /* RemoteHosts.m */; };
35730FDD1134291300066B68 /* Remote old.png in Resources */ = {isa = PBXBuildFile; fileRef = 35730FDC1134291300066B68 /* Remote old.png */; };
35730FE911342C6E00066B68 /* Remote_disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = 35730FE811342C6E00066B68 /* Remote_disabled.png */; };
- 35738409110209AB00E8DB54 /* HostsListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 35738408110209AB00E8DB54 /* HostsListView.m */; };
3579F0EA1114B7E700123416 /* launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 35FC65991114B12600BD18C3 /* launcher.m */; };
3579F0EB1114B7EF00123416 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
3579F1181114B95300123416 /* Launcher.app in Resources */ = {isa = PBXBuildFile; fileRef = 3579F0CD1114B7B900123416 /* Launcher.app */; };
@@ -107,7 +92,6 @@
35D33291152F5B7B001DA824 /* CombinedHostsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35D33290152F5B7B001DA824 /* CombinedHostsController.m */; };
35D83BEF20DD97CF00169358 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35D83BEE20DD97CF00169358 /* Assets.xcassets */; };
35DA4DF6123BF4F30043CA87 /* sparkle_dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 35DA4DF5123BF4F30043CA87 /* sparkle_dsa_pub.pem */; };
- 35E32D841211D52F00B2C631 /* OfflineBadge.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E32D831211D52F00B2C631 /* OfflineBadge.m */; };
35E32EDC12145CF900B2C631 /* Logger.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E32EDB12145CF900B2C631 /* Logger.m */; };
35E33075121490B100B2C631 /* ExtendedNSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E33074121490B100B2C631 /* ExtendedNSThread.m */; };
35E9008A1147F42900851A25 /* MAAttachedWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E900891147F42900851A25 /* MAAttachedWindow.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@@ -133,14 +117,17 @@
AA00000E000000000000AAAA /* URLSheetPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00000D000000000000AAAA /* URLSheetPresenterTests.swift */; };
AA000010000000000000AAAA /* URLSheetViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00000F000000000000AAAA /* URLSheetViewTests.swift */; };
AA000012000000000000AAAA /* HostsDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000011000000000000AAAA /* HostsDataStore.swift */; };
+ 4367D8248BF62656D4AC86D1 /* EditorToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD2C7D6281D5A0139260D12A /* EditorToolbar.swift */; };
+ DD2A255B82569B83ED993DC2 /* StatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D979CFF69FCB07AB746051E /* StatusBarView.swift */; };
+ 7189711AD9756F2CBD4BCF22 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C64FE428AF00EB0DEEAAEBD /* EditorView.swift */; };
+ 3CC80FFF3B4950D6CB6B71D1 /* EditorWindowPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 682E8D22B3228ABF7EBFDC08 /* EditorWindowPresenter.swift */; };
AA000014000000000000AAAA /* HostsRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000013000000000000AAAA /* HostsRowView.swift */; };
AA000016000000000000AAAA /* SidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000015000000000000AAAA /* SidebarView.swift */; };
- AA000018000000000000AAAA /* SidebarInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000017000000000000AAAA /* SidebarInstaller.swift */; };
AA00001A000000000000AAAA /* HostsDataStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000019000000000000AAAA /* HostsDataStoreTests.swift */; };
+ EE000002000000000000EE01 /* EditorWindowPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE000001000000000000EE01 /* EditorWindowPresenterTests.swift */; };
AA00001C000000000000AAAA /* HostsTextViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00001B000000000000AAAA /* HostsTextViewRepresentable.swift */; };
AA00001E000000000000AAAA /* CombinedHostsPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00001D000000000000AAAA /* CombinedHostsPickerView.swift */; };
AA000020000000000000AAAA /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA00001F000000000000AAAA /* ContentView.swift */; };
- AA000022000000000000AAAA /* ContentInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA000021000000000000AAAA /* ContentInstaller.swift */; };
BB000002000000000000BBBB /* RemoteIntervalMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB000001000000000000BBBB /* RemoteIntervalMapper.swift */; };
BB000004000000000000BBBB /* ShortcutRecorderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB000003000000000000BBBB /* ShortcutRecorderView.swift */; };
CC000002000000000000CC01 /* GlobalShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC000001000000000000CC01 /* GlobalShortcuts.swift */; };
@@ -148,14 +135,14 @@
BB000008000000000000BBBB /* LoginItemObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB000007000000000000BBBB /* LoginItemObserver.swift */; };
BB00000A000000000000BBBB /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB000009000000000000BBBB /* PreferencesView.swift */; };
BB00000C000000000000BBBB /* PreferencesPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB00000B000000000000BBBB /* PreferencesPresenter.swift */; };
- EE000002000000000000EE01 /* AboutBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE000001000000000000EE01 /* AboutBoxView.swift */; };
- EE000004000000000000EE01 /* AboutBoxPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE000003000000000000EE01 /* AboutBoxPresenter.swift */; };
+ FF000002000000000000FF01 /* AboutBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF000001000000000000FF01 /* AboutBoxView.swift */; };
+ FF000004000000000000FF01 /* AboutBoxPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF000003000000000000FF01 /* AboutBoxPresenter.swift */; };
BB00000E000000000000BBBB /* RemoteIntervalMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB00000D000000000000BBBB /* RemoteIntervalMapperTests.swift */; };
BB000010000000000000BBBB /* SparkleObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB00000F000000000000BBBB /* SparkleObserverTests.swift */; };
BB000012000000000000BBBB /* PreferencesPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB000011000000000000BBBB /* PreferencesPresenterTests.swift */; };
DD000002000000000000DD01 /* GlobalShortcutsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD000001000000000000DD01 /* GlobalShortcutsTests.swift */; };
DD000004000000000000DD01 /* ShortcutRecorderViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD000003000000000000DD01 /* ShortcutRecorderViewTests.swift */; };
- EE000006000000000000EE01 /* AboutBoxPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE000005000000000000EE01 /* AboutBoxPresenterTests.swift */; };
+ FF000006000000000000FF01 /* AboutBoxPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF000005000000000000FF01 /* AboutBoxPresenterTests.swift */; };
/* Begin PBXContainerItemProxy section */
353D18A01114C067005C4E54 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
@@ -202,16 +189,8 @@
350920C41226EDD600ACA0F4 /* AbstractHostsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AbstractHostsManager.m; path = Source/AbstractHostsManager.m; sourceTree = ""; };
350C7F381A3C55B000B46B09 /* Create@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Create@2x.png"; path = "Resources/Images/Create@2x.png"; sourceTree = ""; };
350C7F3A1A3C56BB00B46B09 /* Read Only@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Read Only@2x.png"; path = "Resources/Images/Read Only@2x.png"; sourceTree = ""; };
- 350E7D3C121093E400D2F5F5 /* AlertBadge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AlertBadge.h; path = Source/AlertBadge.h; sourceTree = ""; };
- 350E7D3D121093E400D2F5F5 /* AlertBadge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AlertBadge.m; path = Source/AlertBadge.m; sourceTree = ""; };
- 350E7D7C12111B2300D2F5F5 /* Badge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Badge.h; path = Source/Badge.h; sourceTree = ""; };
- 350E7D7D12111B2300D2F5F5 /* Badge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Badge.m; path = Source/Badge.m; sourceTree = ""; };
- 350E7D921211A7AE00D2F5F5 /* BadgeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BadgeManager.h; path = Source/BadgeManager.h; sourceTree = ""; };
- 350E7D931211A7AE00D2F5F5 /* BadgeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BadgeManager.m; path = Source/BadgeManager.m; sourceTree = ""; };
351167BE10D6346000A5FAA1 /* HostsGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostsGroup.h; path = Source/HostsGroup.h; sourceTree = ""; };
351167BF10D6346000A5FAA1 /* HostsGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostsGroup.m; path = Source/HostsGroup.m; sourceTree = ""; };
- 3511697610D68B1000A5FAA1 /* FilesCountTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FilesCountTransformer.h; path = Source/FilesCountTransformer.h; sourceTree = ""; };
- 3511697710D68B1000A5FAA1 /* FilesCountTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FilesCountTransformer.m; path = Source/FilesCountTransformer.m; sourceTree = ""; };
35116A6E10D6AAD200A5FAA1 /* Menulet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Menulet.h; path = Source/Menulet.h; sourceTree = ""; };
35116A6F10D6AAD200A5FAA1 /* Menulet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Menulet.m; path = Source/Menulet.m; sourceTree = ""; };
35116ABE10D6AF0500A5FAA1 /* LoginItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoginItem.h; path = Source/LoginItem.h; sourceTree = ""; };
@@ -219,8 +198,6 @@
3513A5FF113908A900AD789D /* Read Only.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Read Only.png"; path = "Resources/Images/Read Only.png"; sourceTree = ""; };
3513A61A11390B7900AD789D /* Error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Error.h; path = Source/Error.h; sourceTree = ""; };
3513A61B11390B7900AD789D /* Error.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Error.m; path = Source/Error.m; sourceTree = ""; };
- 3516864911187EDE00314609 /* HostsTextController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostsTextController.h; path = Source/HostsTextController.h; sourceTree = ""; };
- 3516864A11187EDE00314609 /* HostsTextController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostsTextController.m; path = Source/HostsTextController.m; sourceTree = ""; };
351D904110E76F7100CA6B5E /* Help */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Help; sourceTree = ""; };
3522BEDE153316AA00035B90 /* ExtendedNSArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtendedNSArray.h; path = Source/ExtendedNSArray.h; sourceTree = ""; };
3522BEDF153316AA00035B90 /* ExtendedNSArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ExtendedNSArray.m; path = Source/ExtendedNSArray.m; sourceTree = ""; };
@@ -232,19 +209,12 @@
3528ECE610E3F87E003C8CB9 /* Syncing_arrows4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Syncing_arrows4.png; path = Resources/Images/Syncing_arrows4.png; sourceTree = ""; };
3528ECE710E3F87E003C8CB9 /* Syncing_arrows5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Syncing_arrows5.png; path = Resources/Images/Syncing_arrows5.png; sourceTree = ""; };
3528ECE810E3F87E003C8CB9 /* Syncing_arrows6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Syncing_arrows6.png; path = Resources/Images/Syncing_arrows6.png; sourceTree = ""; };
- 352E048B106279F50071E25B /* ListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ListController.h; path = Source/ListController.h; sourceTree = ""; };
- 352E048C106279F50071E25B /* ListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ListController.m; path = Source/ListController.m; sourceTree = ""; };
- 352E049E10627A830071E25B /* Editor.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Editor.xib; sourceTree = ""; };
352E04B810627C1D0071E25B /* ApplicationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ApplicationController.h; path = Source/ApplicationController.h; sourceTree = ""; };
352E04B910627C1D0071E25B /* ApplicationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ApplicationController.m; path = Source/ApplicationController.m; sourceTree = ""; };
352E04F9106281940071E25B /* Create.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Create.png; path = Resources/Images/Create.png; sourceTree = ""; };
352E04FB106281940071E25B /* Save.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Save.png; path = Resources/Images/Save.png; sourceTree = ""; };
- 352E050C106283630071E25B /* EditorController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EditorController.h; path = Source/EditorController.h; sourceTree = ""; };
- 352E050D106283630071E25B /* EditorController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EditorController.m; path = Source/EditorController.m; sourceTree = ""; };
352E0554106288400071E25B /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = Source/Node.h; sourceTree = ""; };
352E0555106288400071E25B /* Node.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Node.m; path = Source/Node.m; sourceTree = ""; };
- 352E059110628A2F0071E25B /* Cell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Cell.h; path = Source/Cell.h; sourceTree = ""; };
- 352E059210628A2F0071E25B /* Cell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Cell.m; path = Source/Cell.m; sourceTree = ""; };
352E05B310628D790071E25B /* Activated.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Activated.png; path = Resources/Images/Activated.png; sourceTree = ""; };
352E05B410628D790071E25B /* Blue Dot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Blue Dot.png"; path = "Resources/Images/Blue Dot.png"; sourceTree = ""; };
352E05D910628E400071E25B /* Local File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Local File.png"; path = "Resources/Images/Local File.png"; sourceTree = ""; };
@@ -261,23 +231,14 @@
353A80C810B01F320005CAD1 /* ExtendedNSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtendedNSString.h; path = Source/ExtendedNSString.h; sourceTree = ""; };
353A80C910B01F320005CAD1 /* ExtendedNSString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ExtendedNSString.m; path = Source/ExtendedNSString.m; sourceTree = ""; };
353A80FB10B020B10005CAD1 /* UserDefaults.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = UserDefaults.plist; path = Resources/UserDefaults.plist; sourceTree = ""; };
- 3541CE0310E4AF9B00FA00CB /* SyncingArrowsBadge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SyncingArrowsBadge.h; path = Source/SyncingArrowsBadge.h; sourceTree = ""; };
- 3541CE0410E4AF9B00FA00CB /* SyncingArrowsBadge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SyncingArrowsBadge.m; path = Source/SyncingArrowsBadge.m; sourceTree = ""; };
3544E2D110E4CCB1009AC525 /* Map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Map.h; path = Source/Map.h; sourceTree = ""; };
3544E2D210E4CCB1009AC525 /* Map.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Map.m; path = Source/Map.m; sourceTree = ""; };
3545DC7210E38DDE00EBA66D /* Offline.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Offline.png; path = Resources/Images/Offline.png; sourceTree = ""; };
3545DCA710E396CF00EBA66D /* Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Network.h; path = Source/Network.h; sourceTree = ""; };
3545DCA810E396CF00EBA66D /* Network.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Network.m; path = Source/Network.m; sourceTree = ""; };
3545DCE310E3997200EBA66D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = ""; };
- 3546AF7615318F48006B293B /* CombinedHostsPredicateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CombinedHostsPredicateController.h; path = Source/CombinedHostsPredicateController.h; sourceTree = ""; };
- 3546AF7715318F48006B293B /* CombinedHostsPredicateController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CombinedHostsPredicateController.m; path = Source/CombinedHostsPredicateController.m; sourceTree = ""; };
- 3546AF7D1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CombinedHostsPredicateEditorRowTemplate.h; path = Source/CombinedHostsPredicateEditorRowTemplate.h; sourceTree = ""; };
- 3546AF7E1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CombinedHostsPredicateEditorRowTemplate.m; path = Source/CombinedHostsPredicateEditorRowTemplate.m; sourceTree = ""; };
35498EDA12187F5D00E46952 /* Offline_rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Offline_rollover.png; path = Resources/Images/Offline_rollover.png; sourceTree = ""; };
354C0BC410E782A5005B9A33 /* hosts.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = hosts.icns; path = Resources/hosts.icns; sourceTree = ""; };
- 354CCF7F1117285300EB6948 /* HostsListViewMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostsListViewMenu.h; path = Source/HostsListViewMenu.h; sourceTree = ""; };
- 354CCF801117285300EB6948 /* HostsListViewMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostsListViewMenu.m; path = Source/HostsListViewMenu.m; sourceTree = ""; };
- 354DDCED114EAC5000DB76D7 /* NSToolbarPoofAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSToolbarPoofAnimator.h; path = Source/NSToolbarPoofAnimator.h; sourceTree = ""; };
354E7E3E10AEB09D00FC4757 /* HostsMainController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostsMainController.h; path = Source/HostsMainController.h; sourceTree = ""; };
354E7E3F10AEB09D00FC4757 /* HostsMainController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostsMainController.m; path = Source/HostsMainController.m; sourceTree = ""; };
354E7E7210AEB25100FC4757 /* Hosts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hosts.h; path = Source/Hosts.h; sourceTree = ""; };
@@ -300,14 +261,10 @@
3567121F1132E2A700DF30E0 /* NetworkStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NetworkStatus.m; path = Source/NetworkStatus.m; sourceTree = ""; };
3569AEBD12303479007DF95F /* Preferences+Remote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Preferences+Remote.h"; path = "Source/Preferences+Remote.h"; sourceTree = ""; };
3569AEBE12303479007DF95F /* Preferences+Remote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "Preferences+Remote.m"; path = "Source/Preferences+Remote.m"; sourceTree = ""; };
- 356DB7681824EAFD0020CEA0 /* ExtendedNSSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtendedNSSplitView.h; path = Source/ExtendedNSSplitView.h; sourceTree = ""; };
- 356DB7691824EAFD0020CEA0 /* ExtendedNSSplitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ExtendedNSSplitView.m; path = Source/ExtendedNSSplitView.m; sourceTree = ""; };
35730FCD113424C100066B68 /* RemoteHosts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RemoteHosts.h; path = Source/RemoteHosts.h; sourceTree = ""; };
35730FCE113424C100066B68 /* RemoteHosts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RemoteHosts.m; path = Source/RemoteHosts.m; sourceTree = ""; };
35730FDC1134291300066B68 /* Remote old.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Remote old.png"; path = "Resources/Images/Remote old.png"; sourceTree = ""; };
35730FE811342C6E00066B68 /* Remote_disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Remote_disabled.png; path = Resources/Images/Remote_disabled.png; sourceTree = ""; };
- 35738407110209AB00E8DB54 /* HostsListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostsListView.h; path = Source/HostsListView.h; sourceTree = ""; };
- 35738408110209AB00E8DB54 /* HostsListView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostsListView.m; path = Source/HostsListView.m; sourceTree = ""; };
3579F0CD1114B7B900123416 /* Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Launcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
3579F0CF1114B7B900123416 /* Launcher-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Launcher-Info.plist"; sourceTree = ""; };
358448B110DFE283002E6A9B /* Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Util.h; path = Source/Util.h; sourceTree = ""; };
@@ -335,14 +292,17 @@
AA00000D000000000000AAAA /* URLSheetPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSheetPresenterTests.swift; sourceTree = ""; };
AA00000F000000000000AAAA /* URLSheetViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSheetViewTests.swift; sourceTree = ""; };
AA000011000000000000AAAA /* HostsDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HostsDataStore.swift; path = "Source/Swift/HostsDataStore.swift"; sourceTree = ""; };
+ CD2C7D6281D5A0139260D12A /* EditorToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EditorToolbar.swift; path = "Source/Swift/EditorToolbar.swift"; sourceTree = ""; };
+ 3D979CFF69FCB07AB746051E /* StatusBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StatusBarView.swift; path = "Source/Swift/StatusBarView.swift"; sourceTree = ""; };
+ 7C64FE428AF00EB0DEEAAEBD /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EditorView.swift; path = "Source/Swift/EditorView.swift"; sourceTree = ""; };
+ 682E8D22B3228ABF7EBFDC08 /* EditorWindowPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EditorWindowPresenter.swift; path = "Source/Swift/EditorWindowPresenter.swift"; sourceTree = ""; };
AA000013000000000000AAAA /* HostsRowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HostsRowView.swift; path = "Source/Swift/HostsRowView.swift"; sourceTree = ""; };
AA000015000000000000AAAA /* SidebarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SidebarView.swift; path = "Source/Swift/SidebarView.swift"; sourceTree = ""; };
- AA000017000000000000AAAA /* SidebarInstaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SidebarInstaller.swift; path = "Source/Swift/SidebarInstaller.swift"; sourceTree = ""; };
AA000019000000000000AAAA /* HostsDataStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostsDataStoreTests.swift; sourceTree = ""; };
+ EE000001000000000000EE01 /* EditorWindowPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorWindowPresenterTests.swift; sourceTree = ""; };
AA00001B000000000000AAAA /* HostsTextViewRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HostsTextViewRepresentable.swift; path = "Source/Swift/HostsTextViewRepresentable.swift"; sourceTree = ""; };
AA00001D000000000000AAAA /* CombinedHostsPickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CombinedHostsPickerView.swift; path = "Source/Swift/CombinedHostsPickerView.swift"; sourceTree = ""; };
AA00001F000000000000AAAA /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContentView.swift; path = "Source/Swift/ContentView.swift"; sourceTree = ""; };
- AA000021000000000000AAAA /* ContentInstaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContentInstaller.swift; path = "Source/Swift/ContentInstaller.swift"; sourceTree = ""; };
35A183A71A0ACF37002D6289 /* menuIcon@2x.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = "menuIcon@2x.tiff"; path = "Resources/Images/menuIcon@2x.tiff"; sourceTree = ""; };
BB000001000000000000BBBB /* RemoteIntervalMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RemoteIntervalMapper.swift; path = "Source/Swift/RemoteIntervalMapper.swift"; sourceTree = ""; };
BB000003000000000000BBBB /* ShortcutRecorderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShortcutRecorderView.swift; path = "Source/Swift/ShortcutRecorderView.swift"; sourceTree = ""; };
@@ -351,14 +311,14 @@
BB000007000000000000BBBB /* LoginItemObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoginItemObserver.swift; path = "Source/Swift/LoginItemObserver.swift"; sourceTree = ""; };
BB000009000000000000BBBB /* PreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferencesView.swift; path = "Source/Swift/PreferencesView.swift"; sourceTree = ""; };
BB00000B000000000000BBBB /* PreferencesPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferencesPresenter.swift; path = "Source/Swift/PreferencesPresenter.swift"; sourceTree = ""; };
- EE000001000000000000EE01 /* AboutBoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AboutBoxView.swift; path = "Source/Swift/AboutBoxView.swift"; sourceTree = ""; };
- EE000003000000000000EE01 /* AboutBoxPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AboutBoxPresenter.swift; path = "Source/Swift/AboutBoxPresenter.swift"; sourceTree = ""; };
+ FF000001000000000000FF01 /* AboutBoxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AboutBoxView.swift; path = "Source/Swift/AboutBoxView.swift"; sourceTree = ""; };
+ FF000003000000000000FF01 /* AboutBoxPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AboutBoxPresenter.swift; path = "Source/Swift/AboutBoxPresenter.swift"; sourceTree = ""; };
BB00000D000000000000BBBB /* RemoteIntervalMapperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteIntervalMapperTests.swift; sourceTree = ""; };
BB00000F000000000000BBBB /* SparkleObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SparkleObserverTests.swift; sourceTree = ""; };
BB000011000000000000BBBB /* PreferencesPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesPresenterTests.swift; sourceTree = ""; };
DD000001000000000000DD01 /* GlobalShortcutsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalShortcutsTests.swift; sourceTree = ""; };
DD000003000000000000DD01 /* ShortcutRecorderViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutRecorderViewTests.swift; sourceTree = ""; };
- EE000005000000000000EE01 /* AboutBoxPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutBoxPresenterTests.swift; sourceTree = ""; };
+ FF000005000000000000FF01 /* AboutBoxPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutBoxPresenterTests.swift; sourceTree = ""; };
35A4CD2F1534927F005176BD /* Combined Hosts Hint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Combined Hosts Hint.png"; path = "Resources/Images/Combined Hosts Hint.png"; sourceTree = ""; };
35B0499A1A462AE900EB89CA /* Activated@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Activated@2x.png"; path = "Resources/Images/Activated@2x.png"; sourceTree = ""; };
35B0499C1A462BC500EB89CA /* Blue Dot@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Blue Dot@2x.png"; path = "Resources/Images/Blue Dot@2x.png"; sourceTree = ""; };
@@ -374,8 +334,6 @@
35D33290152F5B7B001DA824 /* CombinedHostsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CombinedHostsController.m; path = Source/CombinedHostsController.m; sourceTree = ""; };
35D83BEE20DD97CF00169358 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
35DA4DF5123BF4F30043CA87 /* sparkle_dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = sparkle_dsa_pub.pem; path = Resources/sparkle_dsa_pub.pem; sourceTree = ""; };
- 35E32D821211D52F00B2C631 /* OfflineBadge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OfflineBadge.h; path = Source/OfflineBadge.h; sourceTree = ""; };
- 35E32D831211D52F00B2C631 /* OfflineBadge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OfflineBadge.m; path = Source/OfflineBadge.m; sourceTree = ""; };
35E32EDA12145CF900B2C631 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logger.h; path = Source/Logger.h; sourceTree = ""; };
35E32EDB12145CF900B2C631 /* Logger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Logger.m; path = Source/Logger.m; sourceTree = ""; };
35E33073121490B100B2C631 /* ExtendedNSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtendedNSThread.h; path = Source/ExtendedNSThread.h; sourceTree = ""; };
@@ -440,8 +398,6 @@
3511696F10D68AE800A5FAA1 /* GUI */,
3513A61A11390B7900AD789D /* Error.h */,
3513A61B11390B7900AD789D /* Error.m */,
- 352E050C106283630071E25B /* EditorController.h */,
- 352E050D106283630071E25B /* EditorController.m */,
35116ABE10D6AF0500A5FAA1 /* LoginItem.h */,
35116ABF10D6AF0500A5FAA1 /* LoginItem.m */,
);
@@ -529,7 +485,6 @@
3579F0CF1114B7B900123416 /* Launcher-Info.plist */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
- 352E049E10627A830071E25B /* Editor.xib */,
359289AA1659222E00492494 /* CHANGELOG.txt */,
);
name = Resources;
@@ -547,16 +502,6 @@
350E7D3A121093B400D2F5F5 /* Cell Badges */ = {
isa = PBXGroup;
children = (
- 350E7D921211A7AE00D2F5F5 /* BadgeManager.h */,
- 350E7D931211A7AE00D2F5F5 /* BadgeManager.m */,
- 350E7D7C12111B2300D2F5F5 /* Badge.h */,
- 350E7D7D12111B2300D2F5F5 /* Badge.m */,
- 3541CE0310E4AF9B00FA00CB /* SyncingArrowsBadge.h */,
- 3541CE0410E4AF9B00FA00CB /* SyncingArrowsBadge.m */,
- 350E7D3C121093E400D2F5F5 /* AlertBadge.h */,
- 350E7D3D121093E400D2F5F5 /* AlertBadge.m */,
- 35E32D821211D52F00B2C631 /* OfflineBadge.h */,
- 35E32D831211D52F00B2C631 /* OfflineBadge.m */,
);
name = "Cell Badges";
sourceTree = "";
@@ -616,8 +561,6 @@
children = (
3513F353115153560046FFF7 /* Hosts Text View */,
3536E03B114BB4B700972A49 /* Hosts List */,
- 3511697610D68B1000A5FAA1 /* FilesCountTransformer.h */,
- 3511697710D68B1000A5FAA1 /* FilesCountTransformer.m */,
);
name = Editor;
sourceTree = "";
@@ -627,8 +570,6 @@
children = (
353A804510B01AEF0005CAD1 /* HostsTextView.h */,
353A804610B01AEF0005CAD1 /* HostsTextView.m */,
- 3516864911187EDE00314609 /* HostsTextController.h */,
- 3516864A11187EDE00314609 /* HostsTextController.m */,
);
name = "Hosts Text View";
sourceTree = "";
@@ -646,14 +587,6 @@
isa = PBXGroup;
children = (
350E7D3A121093B400D2F5F5 /* Cell Badges */,
- 352E048B106279F50071E25B /* ListController.h */,
- 352E048C106279F50071E25B /* ListController.m */,
- 35738407110209AB00E8DB54 /* HostsListView.h */,
- 35738408110209AB00E8DB54 /* HostsListView.m */,
- 354CCF7F1117285300EB6948 /* HostsListViewMenu.h */,
- 354CCF801117285300EB6948 /* HostsListViewMenu.m */,
- 352E059110628A2F0071E25B /* Cell.h */,
- 352E059210628A2F0071E25B /* Cell.m */,
352E0554106288400071E25B /* Node.h */,
352E0555106288400071E25B /* Node.m */,
351167BE10D6346000A5FAA1 /* HostsGroup.h */,
@@ -770,16 +703,18 @@
AA000005000000000000AAAA /* NetworkStatusObserver.swift */,
AA000007000000000000AAAA /* URLSheetView.swift */,
AA000009000000000000AAAA /* URLSheetPresenter.swift */,
- EE000001000000000000EE01 /* AboutBoxView.swift */,
- EE000003000000000000EE01 /* AboutBoxPresenter.swift */,
+ FF000001000000000000FF01 /* AboutBoxView.swift */,
+ FF000003000000000000FF01 /* AboutBoxPresenter.swift */,
AA000011000000000000AAAA /* HostsDataStore.swift */,
+ CD2C7D6281D5A0139260D12A /* EditorToolbar.swift */,
+ 3D979CFF69FCB07AB746051E /* StatusBarView.swift */,
+ 7C64FE428AF00EB0DEEAAEBD /* EditorView.swift */,
+ 682E8D22B3228ABF7EBFDC08 /* EditorWindowPresenter.swift */,
AA000013000000000000AAAA /* HostsRowView.swift */,
AA000015000000000000AAAA /* SidebarView.swift */,
- AA000017000000000000AAAA /* SidebarInstaller.swift */,
AA00001B000000000000AAAA /* HostsTextViewRepresentable.swift */,
AA00001D000000000000AAAA /* CombinedHostsPickerView.swift */,
AA00001F000000000000AAAA /* ContentView.swift */,
- AA000021000000000000AAAA /* ContentInstaller.swift */,
BB000020000000000000BBBB /* Preferences */,
);
name = Swift;
@@ -805,10 +740,6 @@
35D3328D152F5A87001DA824 /* CombinedHosts.m */,
35D3328F152F5B7B001DA824 /* CombinedHostsController.h */,
35D33290152F5B7B001DA824 /* CombinedHostsController.m */,
- 3546AF7615318F48006B293B /* CombinedHostsPredicateController.h */,
- 3546AF7715318F48006B293B /* CombinedHostsPredicateController.m */,
- 3546AF7D1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.h */,
- 3546AF7E1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.m */,
);
name = "Combined Hosts";
sourceTree = "";
@@ -816,7 +747,6 @@
35D4C98210E64D8800B9F63A /* Extended Next Step */ = {
isa = PBXGroup;
children = (
- 354DDCED114EAC5000DB76D7 /* NSToolbarPoofAnimator.h */,
353A80C810B01F320005CAD1 /* ExtendedNSString.h */,
353A80C910B01F320005CAD1 /* ExtendedNSString.m */,
35E33073121490B100B2C631 /* ExtendedNSThread.h */,
@@ -825,8 +755,6 @@
3522BEDF153316AA00035B90 /* ExtendedNSArray.m */,
3522BEE11533552200035B90 /* ExtendedNSPredicate.h */,
3522BEE21533552200035B90 /* ExtendedNSPredicate.m */,
- 356DB7681824EAFD0020CEA0 /* ExtendedNSSplitView.h */,
- 356DB7691824EAFD0020CEA0 /* ExtendedNSSplitView.m */,
);
name = "Extended Next Step";
sourceTree = "";
@@ -860,12 +788,13 @@
AA00000D000000000000AAAA /* URLSheetPresenterTests.swift */,
AA00000F000000000000AAAA /* URLSheetViewTests.swift */,
AA000019000000000000AAAA /* HostsDataStoreTests.swift */,
+ EE000001000000000000EE01 /* EditorWindowPresenterTests.swift */,
BB00000D000000000000BBBB /* RemoteIntervalMapperTests.swift */,
BB00000F000000000000BBBB /* SparkleObserverTests.swift */,
BB000011000000000000BBBB /* PreferencesPresenterTests.swift */,
DD000001000000000000DD01 /* GlobalShortcutsTests.swift */,
DD000003000000000000DD01 /* ShortcutRecorderViewTests.swift */,
- EE000005000000000000EE01 /* AboutBoxPresenterTests.swift */,
+ FF000005000000000000FF01 /* AboutBoxPresenterTests.swift */,
CC2B3C4D5E6F000100000010 /* NodeTests.m */,
CC2B3C4D5E6F000100000011 /* HostsTests.m */,
CC2B3C4D5E6F000100000012 /* HostsGroupTests.m */,
@@ -997,7 +926,6 @@
3579F1181114B95300123416 /* Launcher.app in Resources */,
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
- 352E049F10627A830071E25B /* Editor.xib in Resources */,
352E04FD106281940071E25B /* Create.png in Resources */,
352E04FF106281940071E25B /* Save.png in Resources */,
358E0A891A3A1E1A004521D1 /* Remote yosemite@2x.tiff in Resources */,
@@ -1063,11 +991,8 @@
buildActionMask = 2147483647;
files = (
8D11072D0486CEB800E47090 /* main.m in Sources */,
- 352E048D106279F50071E25B /* ListController.m in Sources */,
352E04BA10627C1D0071E25B /* ApplicationController.m in Sources */,
- 352E050E106283630071E25B /* EditorController.m in Sources */,
352E0556106288400071E25B /* Node.m in Sources */,
- 352E059310628A2F0071E25B /* Cell.m in Sources */,
354E7E4010AEB09D00FC4757 /* HostsMainController.m in Sources */,
354E7E7410AEB25100FC4757 /* Hosts.m in Sources */,
354E7EB110AEEF3D00FC4757 /* StructureConverter.m in Sources */,
@@ -1078,17 +1003,12 @@
353A80BB10B01C050005CAD1 /* Preferences.m in Sources */,
353A80CA10B01F320005CAD1 /* ExtendedNSString.m in Sources */,
351167C010D6346000A5FAA1 /* HostsGroup.m in Sources */,
- 3511697810D68B1000A5FAA1 /* FilesCountTransformer.m in Sources */,
35116A7010D6AAD200A5FAA1 /* Menulet.m in Sources */,
35116AC010D6AF0500A5FAA1 /* LoginItem.m in Sources */,
358448B310DFE283002E6A9B /* Util.m in Sources */,
3545DCA910E396CF00EBA66D /* Network.m in Sources */,
- 3541CE0510E4AF9B00FA00CB /* SyncingArrowsBadge.m in Sources */,
3544E2D310E4CCB1009AC525 /* Map.m in Sources */,
- 35738409110209AB00E8DB54 /* HostsListView.m in Sources */,
3597135D110DED0F00C7ECAF /* HostsMenu.m in Sources */,
- 354CCF811117285300EB6948 /* HostsListViewMenu.m in Sources */,
- 3516864B11187EDE00314609 /* HostsTextController.m in Sources */,
356712201132E2A700DF30E0 /* NetworkStatus.m in Sources */,
35730FCF113424C100066B68 /* RemoteHosts.m in Sources */,
35D2C253113507A6007C8037 /* RemoteHostsManager.m in Sources */,
@@ -1098,13 +1018,15 @@
AA000008000000000000AAAA /* URLSheetView.swift in Sources */,
AA00000A000000000000AAAA /* URLSheetPresenter.swift in Sources */,
AA000012000000000000AAAA /* HostsDataStore.swift in Sources */,
+ 4367D8248BF62656D4AC86D1 /* EditorToolbar.swift in Sources */,
+ DD2A255B82569B83ED993DC2 /* StatusBarView.swift in Sources */,
+ 7189711AD9756F2CBD4BCF22 /* EditorView.swift in Sources */,
+ 3CC80FFF3B4950D6CB6B71D1 /* EditorWindowPresenter.swift in Sources */,
AA000014000000000000AAAA /* HostsRowView.swift in Sources */,
AA000016000000000000AAAA /* SidebarView.swift in Sources */,
- AA000018000000000000AAAA /* SidebarInstaller.swift in Sources */,
AA00001C000000000000AAAA /* HostsTextViewRepresentable.swift in Sources */,
AA00001E000000000000AAAA /* CombinedHostsPickerView.swift in Sources */,
AA000020000000000000AAAA /* ContentView.swift in Sources */,
- AA000022000000000000AAAA /* ContentInstaller.swift in Sources */,
BB000002000000000000BBBB /* RemoteIntervalMapper.swift in Sources */,
BB000004000000000000BBBB /* ShortcutRecorderView.swift in Sources */,
CC000002000000000000CC01 /* GlobalShortcuts.swift in Sources */,
@@ -1112,14 +1034,9 @@
BB000008000000000000BBBB /* LoginItemObserver.swift in Sources */,
BB00000A000000000000BBBB /* PreferencesView.swift in Sources */,
BB00000C000000000000BBBB /* PreferencesPresenter.swift in Sources */,
- EE000002000000000000EE01 /* AboutBoxView.swift in Sources */,
- EE000004000000000000EE01 /* AboutBoxPresenter.swift in Sources */,
- 356DB76A1824EAFD0020CEA0 /* ExtendedNSSplitView.m in Sources */,
+ FF000002000000000000FF01 /* AboutBoxView.swift in Sources */,
+ FF000004000000000000FF01 /* AboutBoxPresenter.swift in Sources */,
35E9008A1147F42900851A25 /* MAAttachedWindow.m in Sources */,
- 350E7D3E121093E400D2F5F5 /* AlertBadge.m in Sources */,
- 350E7D7E12111B2300D2F5F5 /* Badge.m in Sources */,
- 350E7D941211A7AE00D2F5F5 /* BadgeManager.m in Sources */,
- 35E32D841211D52F00B2C631 /* OfflineBadge.m in Sources */,
35E32EDC12145CF900B2C631 /* Logger.m in Sources */,
35E33075121490B100B2C631 /* ExtendedNSThread.m in Sources */,
35FBCA3B1223172300860FDA /* RegexKitLite.m in Sources */,
@@ -1135,8 +1052,6 @@
35F414F4152E1B7800B99583 /* VDKQueue.m in Sources */,
35D3328E152F5A87001DA824 /* CombinedHosts.m in Sources */,
35D33291152F5B7B001DA824 /* CombinedHostsController.m in Sources */,
- 3546AF7815318F48006B293B /* CombinedHostsPredicateController.m in Sources */,
- 3546AF7F1531B7C2006B293B /* CombinedHostsPredicateEditorRowTemplate.m in Sources */,
3522BEE0153316AA00035B90 /* ExtendedNSArray.m in Sources */,
3522BEE31533552200035B90 /* ExtendedNSPredicate.m in Sources */,
359967541656B52500BCF16D /* NotificationHelper.m in Sources */,
@@ -1156,12 +1071,13 @@
AA00000E000000000000AAAA /* URLSheetPresenterTests.swift in Sources */,
AA000010000000000000AAAA /* URLSheetViewTests.swift in Sources */,
AA00001A000000000000AAAA /* HostsDataStoreTests.swift in Sources */,
+ EE000002000000000000EE01 /* EditorWindowPresenterTests.swift in Sources */,
BB00000E000000000000BBBB /* RemoteIntervalMapperTests.swift in Sources */,
BB000010000000000000BBBB /* SparkleObserverTests.swift in Sources */,
BB000012000000000000BBBB /* PreferencesPresenterTests.swift in Sources */,
DD000002000000000000DD01 /* GlobalShortcutsTests.swift in Sources */,
DD000004000000000000DD01 /* ShortcutRecorderViewTests.swift in Sources */,
- EE000006000000000000EE01 /* AboutBoxPresenterTests.swift in Sources */,
+ FF000006000000000000FF01 /* AboutBoxPresenterTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/AlertBadge.h b/Source/AlertBadge.h
deleted file mode 100644
index dc3b84c..0000000
--- a/Source/AlertBadge.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "Badge.h"
-
-@class RemoteHosts;
-
-@interface AlertBadge : Badge {
- @private
- NSImage *icon;
- NSImage *rolloverIcon;
- RemoteHosts *hosts;
-}
-
-- (id) initWithRemoteHosts:(RemoteHosts*)remoteHosts;
-
-@end
diff --git a/Source/AlertBadge.m b/Source/AlertBadge.m
deleted file mode 100644
index 028bd13..0000000
--- a/Source/AlertBadge.m
+++ /dev/null
@@ -1,58 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "AlertBadge.h"
-#import "Error.h"
-#import "RemoteHosts.h"
-#import "ListController.h"
-
-
-@implementation AlertBadge
-
-- (id) initWithRemoteHosts:(RemoteHosts*)remoteHosts
-{
- self = [super init];
-
- [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:[self frame]
- options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
- owner:self
- userInfo:nil]];
-
- icon = [NSImage imageNamed: @"Alert.png"];
- rolloverIcon = [NSImage imageNamed: @"Alert_rollover.png"];
-
- [self setActiveIcon:icon];
-
- hosts = remoteHosts;
-
- return self;
-}
-
-- (void)mouseEntered:(NSEvent *)theEvent
-{
- [self setActiveIcon:rolloverIcon];
-}
-
-- (void)mouseExited:(NSEvent *)theEvent
-{
- [self setActiveIcon:icon];
-}
-
-@end
diff --git a/Source/ApplicationController.h b/Source/ApplicationController.h
index 6af5f81..cb89884 100644
--- a/Source/ApplicationController.h
+++ b/Source/ApplicationController.h
@@ -26,10 +26,8 @@
@interface ApplicationController : NSObject {
@private
- IBOutlet NSProgressIndicator *busyIndicator;
IBOutlet HostsMainController *hostsController;
IBOutlet NSMenuItem *checkForUpdatesMenuItem;
- int busyThreads;
BOOL shouldQuit;
BOOL editorWindowOpened;
SPUStandardUpdaterController *_updaterController;
diff --git a/Source/ApplicationController.m b/Source/ApplicationController.m
index ebcf993..39b37c0 100644
--- a/Source/ApplicationController.m
+++ b/Source/ApplicationController.m
@@ -31,7 +31,6 @@
@interface ApplicationController ()
{
__weak NSWindow *_editorWindow;
- NSArray *_editorNibTopLevelObjects; // retains top-level NIB objects (e.g. EditorController)
}
@end
@@ -62,7 +61,6 @@ - (id)init
return sharedInstance;
}
if (self = [super init]) {
- busyThreads = 0;
shouldQuit = YES;
BOOL isTesting = NSClassFromString(@"XCTestCase") != nil;
@@ -118,7 +116,7 @@ -(IBAction)quit:(id)sender
- (IBAction)openEditorWindow:(id)sender
{
if (!editorWindowOpened) {
- if (_editorNibTopLevelObjects) {
+ if (_editorWindow) {
editorWindowOpened = YES;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(editorWindowWillClose:)
@@ -167,22 +165,6 @@ - (BOOL)editorWindowOpened
return editorWindowOpened;
}
-- (void)increaseBusyThreadsCount:(NSNotification *)notification
-{
- busyThreads++;
- [busyIndicator startAnimation:self];
-}
-
-- (void)decreaseBusyThreadsCount:(NSNotification *)notification
-{
- if (busyThreads > 0) {
- busyThreads--;
- }
- if (busyThreads == 0) {
- [busyIndicator stopAnimation:self];
- }
-}
-
#pragma mark - Application Delegate
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
@@ -195,11 +177,7 @@ - (void)applicationWillFinishLaunching:(NSNotification *)aNotification
[NSApp setServicesProvider:self];
[self initStructure];
-
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self selector:@selector(increaseBusyThreadsCount:) name:ThreadBusyNotification object:nil];
- [nc addObserver:self selector:@selector(decreaseBusyThreadsCount:) name:ThreadNotBusyNotification object:nil];
-
+
[hostsController load];
if (!openedAtLogin() && [Preferences showEditorWindow]) {
@@ -286,20 +264,12 @@ - (void)initStructure
- (void)initEditorWindow
{
logDebug(@"Initializing editor window");
- NSArray *topLevelObjects = nil;
- [[NSBundle mainBundle] loadNibNamed:@"Editor" owner:self topLevelObjects:&topLevelObjects];
- _editorNibTopLevelObjects = topLevelObjects;
+ _editorWindow = [EditorWindowPresenter createEditorWindow];
editorWindowOpened = YES;
- for (id obj in topLevelObjects) {
- if ([obj isKindOfClass:[NSWindow class]]) {
- _editorWindow = obj;
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(editorWindowWillClose:)
- name:NSWindowWillCloseNotification
- object:obj];
- break;
- }
- }
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(editorWindowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:_editorWindow];
}
- (void)activatePreviousFile:(NSNotification *)note
diff --git a/Source/Badge.h b/Source/Badge.h
deleted file mode 100644
index 69cbcd3..0000000
--- a/Source/Badge.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-
-@interface Badge : NSView {
- @private
- NSImage *activeIcon;
-}
-
-- (void)setActiveIcon:(NSImage*)icon;
-
-@end
diff --git a/Source/Badge.m b/Source/Badge.m
deleted file mode 100644
index 7c86b33..0000000
--- a/Source/Badge.m
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "Badge.h"
-
-
-@implementation Badge
-
-- (id) init
-{
- NSRect frame = NSMakeRect(0.0f, 0.0f, 16.0f, 16.0f);
- self = [super initWithFrame:frame];
-
- return self;
-}
-
-- (void)setActiveIcon:(NSImage*)icon
-{
- if (activeIcon == icon) {
- return;
- }
- activeIcon = icon;
-
- [self setNeedsDisplay:YES];
-}
-
-- (void)drawRect:(NSRect)dirtyRect
-{
- if (activeIcon != nil) {
- [activeIcon drawAtPoint:[self bounds].origin fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0];
- }
-}
-
-@end
diff --git a/Source/BadgeManager.h b/Source/BadgeManager.h
deleted file mode 100644
index 950d133..0000000
--- a/Source/BadgeManager.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class Map;
-@class Badge;
-
-@interface BadgeManager : NSObject {
- @private
- Map *badges;
- id target;
- SEL action;
-}
-
-+ (id)badgeManagerWithCreator:(SEL)creator target:(id)t;
-
-- (Badge*)getBadgeForObject:(id)object;
-- (void)removeBadgeForObject:(id)object;
-
-@end
diff --git a/Source/BadgeManager.m b/Source/BadgeManager.m
deleted file mode 100644
index 740fb64..0000000
--- a/Source/BadgeManager.m
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "BadgeManager.h"
-#import "Badge.h"
-#import "Map.h"
-
-@interface BadgeManager (Private)
-
-- (id)initWithCreator:(SEL)creator target:(id)t;
-
-@end
-
-
-@implementation BadgeManager
-
-+ (id)badgeManagerWithCreator:(SEL)creator target:(id)t
-{
- return [[self alloc] initWithCreator:creator target:t];
-}
-
-- (Badge*)getBadgeForObject:(id)object
-{
- Badge *badge;
- if ([badges haveObjectForKey:object]) {
- badge = (Badge*)[badges objectForKey:object];
- }
- else {
- SuppressPerformSelectorLeakWarning(badge = [target performSelector:action]);
- [badges addObject:badge forKey:object];
- }
-
- return badge;
-}
-
-- (void)removeBadgeForObject:(id)object
-{
- if ([badges haveObjectForKey:object]) {
- Badge *badge = (Badge*)[badges objectForKey:object];
- [badge removeFromSuperview];
- [badges removeObjectForKey:object];
- }
-}
-
-@end
-
-@implementation BadgeManager (Private)
-
-- (id)initWithCreator:(SEL)creator target:(id)t
-{
- self = [super init];
- action = creator;
- target = t;
- badges = [Map new];
-
- return self;
-
-}
-
-@end
-
diff --git a/Source/Cell.h b/Source/Cell.h
deleted file mode 100644
index 2f0064f..0000000
--- a/Source/Cell.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class Hosts;
-@class BadgeManager;
-
-@interface Cell : NSTextFieldCell {
- @private
- Hosts *item;
-
- NSImage *localFileIcon;
- NSImage *remoteFileIcon;
- NSImage *remoteDisabledFileIcon;
- NSImage *combinedFileIcon;
- NSImage *activeIcon;
- NSImage *unsavedIcon;
-
- BadgeManager *syncingArrowsBadgeManager;
- BadgeManager *alertBadgeManager;
- BadgeManager *offlineBadgeManager;
-
- BOOL offline;
-}
-
-- (void)setItem:(Hosts*)i;
-- (void)removeAllBadges;
-
-@end
diff --git a/Source/Cell.m b/Source/Cell.m
deleted file mode 100644
index 41d29a2..0000000
--- a/Source/Cell.m
+++ /dev/null
@@ -1,400 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "Cell.h"
-#import "Hosts.h"
-#import "RemoteHosts.h"
-#import "CombinedHosts.h"
-#import "HostsGroup.h"
-#import "SyncingArrowsBadge.h"
-#import "AlertBadge.h"
-#import "OfflineBadge.h"
-#import "BadgeManager.h"
-#import "ListController.h"
-#import "HostsListView.h"
-
-#define kIconImageSize 16.0
-#define kImageOriginXOffset 3
-#define kImageOriginYOffset 1
-
-#define kActiveImageXOffset 32
-
-#define kTextOriginXOffset 4
-#define kTextOriginYOffset 2
-#define kTextHeightAdjust 4
-
-#define kImageSize 13
-#define kRightImageArea 22
-
-CGFloat const kWidthOfProgressIndicator = 16.0f;
-
-@interface Cell(Private)
-
-- (void)drawActiveIconWithFrame:(NSRect)cellFrame;
-- (void)drawUnsavedIconWithFrame:(NSRect)cellFrame;
-
-- (void)drawIconRight:(NSImage*)icon withFrame:(NSRect)cellFrame;
-
-- (NSRect)textFrame:(NSRect)cellFrame;
-- (NSRect)fileIconFrame:(NSRect)cellFrame icon:(NSImage*)icon;
-- (NSRect)rightIconFrame:(NSRect)cellFrame;
-
-- (void)cleanUpForHosts:(NSNotification *)notification;
-@end
-
-@interface Cell(Badge)
-- (void)placeBadge:(Badge*)badge inFrame:(NSRect)cellFrame view:(NSView *)controlView;
-
-- (AlertBadge*)createAlertBadge;
-- (void)placeAlertBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView;
-- (void)removeAlertBadge;
-
-- (SyncingArrowsBadge*)createSyncArrowsBadge;
-- (void)placeSyncArrowsBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView;
-- (void)removeSyncArrowsBadge;
-
-- (void)placeOfflineBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView;
-- (OfflineBadge*)createOfflineBadge;
-- (void)removeOfflineBadge;
-
-@end
-
-
-@implementation Cell
-
-- (id)init
-{
- self = [super init];
-
- [self setTruncatesLastVisibleLine:YES];
- [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-
- if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9) {
- localFileIcon = [NSImage imageNamed: @"Local File.png"];
- remoteFileIcon = [NSImage imageNamed: @"Remote old.png"];
- remoteDisabledFileIcon = [NSImage imageNamed: @"Remote_disabled.png"];
- combinedFileIcon = [NSImage imageNamed: @"Combined_File.png"];
- }
- else {
- localFileIcon = [NSImage imageNamed: @"Local File yosemite.tiff"];
- remoteFileIcon = [NSImage imageNamed: @"Remote yosemite.tiff"];
- remoteDisabledFileIcon = [NSImage imageNamed: @"Remote yosemite.tiff"];
- combinedFileIcon = [NSImage imageNamed: @"Combined_File_yosemite.tiff"];
- }
-
- activeIcon = [NSImage imageNamed: @"Activated"];
- unsavedIcon = [NSImage imageNamed: @"Blue Dot"];
-
- syncingArrowsBadgeManager = [BadgeManager badgeManagerWithCreator:@selector(createSyncArrowsBadge) target:self];
- alertBadgeManager = [BadgeManager badgeManagerWithCreator:@selector(createAlertBadge) target:self];
- offlineBadgeManager = [BadgeManager badgeManagerWithCreator:@selector(createOfflineBadge) target:self];
-
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self selector:@selector(cleanUpForHosts:) name:HostsFileRemovedNotification object:nil];
-
- return self;
-}
-
-- (void)setItem:(Hosts*)i
-{
- item = i;
- offline = [item isKindOfClass:[HostsGroup class]] && ![(HostsGroup*)item online];
-}
-
-- (void)removeAllBadges
-{
- [self removeAlertBadge];
- [self removeOfflineBadge];
- [self removeSyncArrowsBadge];
-}
-
-- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
-{
- if (!item) {
- return;
- }
- if ([item isGroup]) {
- HostsGroup *group = (HostsGroup*)item;
- if ([[group children] count] == 0) {
- return;
- }
-
- if (offline) {
- [self placeOfflineBadgeInFrame:cellFrame view:controlView];
- }
- else {
- [self removeOfflineBadge];
- }
-
- if ([group synchronizing]) {
- [self placeSyncArrowsBadgeInFrame:cellFrame view:controlView];
- }
- else {
- [self removeSyncArrowsBadge];
- }
-
- if ([item error] != nil) {
- [self placeAlertBadgeInFrame:cellFrame view:controlView];
- }
- else {
- [self removeAlertBadge];
- }
-
- [super drawWithFrame:cellFrame inView:controlView];
- return;
- }
-
- NSImage *image;
- [self setEnabled:YES];
-
- if (![item enabled]) {
- [self setEnabled:NO];
- }
-
- if ([item isKindOfClass:[RemoteHosts class]]) {
- image = [item enabled] ? remoteFileIcon : remoteDisabledFileIcon;
- }
- else if ([item isKindOfClass:[CombinedHosts class]]) {
- image = combinedFileIcon;
- }
- else {
- image = localFileIcon;
- }
-
- NSRect frame = [self fileIconFrame:cellFrame icon:image];
- [image drawInRect:frame fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
-
- [super drawWithFrame:[self textFrame:cellFrame] inView:controlView];
-
- if ([item active]) {
- [self drawActiveIconWithFrame:cellFrame];
- }
-
- if (![item saved]) {
- [self drawUnsavedIconWithFrame:cellFrame];
- }
-
- if ([item error] != nil) {
- [self placeAlertBadgeInFrame:cellFrame view:controlView];
- }
- else {
- [self removeAlertBadge];
- }
-}
-
-- (NSRect)titleRectForBounds:(NSRect)cellRect
-{
- NSRect newFrame = cellRect;
-
- int xOffset = kImageOriginXOffset + kIconImageSize + 4;
- newFrame.origin.x += xOffset;
- newFrame.origin.y += kTextOriginYOffset;
- newFrame.size.height -= kTextHeightAdjust;
- newFrame.size.width -= xOffset;
-
- if (![item saved] || [item error] != nil) {
- newFrame.size.width -= kRightImageArea;
- }
-
- return newFrame;
-}
-
-- (NSCellHitResult) hitTestForEvent: (NSEvent *) event inRect: (NSRect) cellFrame ofView: (NSView *) controlView
-{
- NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
-
- if (([item error] != nil || offline) && NSMouseInRect(point, [self rightIconFrame:cellFrame], [controlView isFlipped])) {
- return NSCellHitTrackableArea;
- }
- else if (NSMouseInRect(point, [self textFrame:cellFrame], [controlView isFlipped])) {
- return NSCellHitEditableTextArea;
- }
-
- return NSCellHitContentArea;
-}
-
-- (BOOL) trackMouse: (NSEvent *) event inRect: (NSRect) cellFrame ofView: (NSView *) controlView untilMouseUp: (BOOL) flag
-{
- return YES;
-}
-
-
-- (void)editWithFrame:(NSRect)aRect inView:(NSView*)controlView editor:(NSText*)textObj delegate:(id)anObject event:(NSEvent*)theEvent
-{
- NSRect textFrame = [self titleRectForBounds:aRect];
- [super editWithFrame:textFrame inView:controlView editor:textObj delegate:anObject event:theEvent];
-}
-
-- (void)selectWithFrame:(NSRect)aRect inView:(NSView*)controlView editor:(NSText*)textObj delegate:(id)anObject start:(long)selStart length:(NSInteger)selLength
-{
- NSRect textFrame = [self titleRectForBounds:aRect];
- [super selectWithFrame:textFrame inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
-}
-
-@end
-
-@implementation Cell(Private)
-
-- (void)drawActiveIconWithFrame:(NSRect)cellFrame
-{
- NSSize imageSize = [activeIcon size];
- NSRect frame;
- NSDivideRect(cellFrame, &frame, &cellFrame, imageSize.width, NSMinXEdge);
-
- frame.size = imageSize;
- frame.origin.x -= imageSize.width + 1;
- frame.origin.y += ceil((cellFrame.size.height - imageSize.height) / 2);
-
- [activeIcon drawInRect:frame fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
-}
-
-- (void)drawUnsavedIconWithFrame:(NSRect)cellFrame
-{
- [self drawIconRight:unsavedIcon withFrame:cellFrame];
-}
-
-- (void)drawIconRight:(NSImage*)icon withFrame:(NSRect)cellFrame
-{
- NSRect frame = [self rightIconFrame:cellFrame];
- [icon drawInRect:frame fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
-}
-
-- (NSRect)textFrame:(NSRect)cellFrame
-{
- NSRect frame = cellFrame;
- frame.origin.x += kTextOriginXOffset + kIconImageSize;
- frame.origin.y += kTextOriginYOffset;
- frame.size.height -= kTextHeightAdjust;
- frame.size.width -= frame.origin.x;
-
- return frame;
-}
-
-- (NSRect)fileIconFrame:(NSRect)cellFrame icon:(NSImage*)icon
-{
- NSSize imageSize = [icon size];
- NSRect frame;
- NSDivideRect(cellFrame, &frame, &cellFrame, imageSize.width, NSMinXEdge);
-
- frame.size = imageSize;
- frame.origin.x += 2;
- frame.origin.y += ceil((cellFrame.size.height - imageSize.height) / 2);
-
- return frame;
-}
-
-- (NSRect)rightIconFrame:(NSRect)cellFrame
-{
- NSSize iconSize = NSMakeSize(kImageSize, kImageSize);
- NSRect frame;
- NSDivideRect(cellFrame, &frame, &cellFrame, iconSize.width, NSMaxXEdge);
- frame.size = iconSize;
- frame.origin.y += ceil((cellFrame.size.height - iconSize.height) / 2);
-
- return frame;
-}
-
-- (void)cleanUpForHosts:(NSNotification *)notification
-{
- Hosts *hosts = item;
- item = [notification object];
-
- [self removeSyncArrowsBadge];
- [self removeAlertBadge];
-
- item = hosts;
-}
-
-@end
-
-@implementation Cell (Badge)
-
-- (void)placeBadge:(Badge*)badge inFrame:(NSRect)cellFrame view:(NSView *)controlView
-{
- NSSize size;
- NSRect frame;
-
- size = [badge frame].size;
- NSDivideRect(cellFrame, &frame, &cellFrame, size.width, NSMaxXEdge);
- frame.size = size;
-
- [badge setFrame:frame];
- [controlView addSubview:badge];
-}
-
-#pragma mark Alert
-
-- (AlertBadge*)createAlertBadge
-{
- return [[AlertBadge alloc] initWithRemoteHosts:(RemoteHosts*)item];
-}
-
-- (void)placeAlertBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView
-{
- Badge *badge = [alertBadgeManager getBadgeForObject:item];
- [self placeBadge:badge inFrame:cellFrame view:controlView];
-}
-
-- (void)removeAlertBadge
-{
- [alertBadgeManager removeBadgeForObject:item];
-}
-
-#pragma mark Syncing Arrows
-
-- (SyncingArrowsBadge*)createSyncArrowsBadge
-{
- SyncingArrowsBadge *badge = [SyncingArrowsBadge new];
- [badge start];
- return badge;
-}
-
-- (void)placeSyncArrowsBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView
-{
- Badge *badge = [syncingArrowsBadgeManager getBadgeForObject:item];
- [self placeBadge:badge inFrame:cellFrame view:controlView];
-}
-
-- (void)removeSyncArrowsBadge
-{
- [syncingArrowsBadgeManager removeBadgeForObject:item];
-}
-
-#pragma mark Offline
-
-- (void)placeOfflineBadgeInFrame:(NSRect)cellFrame view:(NSView *)controlView
-{
- Badge *badge = [offlineBadgeManager getBadgeForObject:item];
- [self placeBadge:badge inFrame:cellFrame view:controlView];
-
-}
-
-- (OfflineBadge*)createOfflineBadge
-{
- return [[OfflineBadge alloc] initWithHosts:item];
-}
-
-- (void)removeOfflineBadge
-{
- [offlineBadgeManager removeBadgeForObject:item];
-}
-
-@end
-
diff --git a/Source/CombinedHostsPredicateController.h b/Source/CombinedHostsPredicateController.h
deleted file mode 100644
index 31ab200..0000000
--- a/Source/CombinedHostsPredicateController.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class Hosts;
-@class CombinedHosts;
-
-@interface CombinedHostsPredicateController : NSObject {
- IBOutlet NSPredicateEditor *predicateEditor;
- IBOutlet NSScrollView *lowerScrollView;
- IBOutlet NSView *parentView;
- @private
- int rowCount;
- CombinedHosts *selectedHostsFile;
- NSImageView *hintView;
-}
-
-- (IBAction)predicateEditorChanged:(id)sender;
-- (void)setSelectedFile:(Hosts*)value;
-- (Hosts*)selectedFile;
-
-@end
diff --git a/Source/CombinedHostsPredicateController.m b/Source/CombinedHostsPredicateController.m
deleted file mode 100644
index ec9a3d0..0000000
--- a/Source/CombinedHostsPredicateController.m
+++ /dev/null
@@ -1,197 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "CombinedHostsPredicateController.h"
-#import "CombinedHostsPredicateEditorRowTemplate.h"
-#import "HostsMainController.h"
-#import "CombinedHosts.h"
-#import "Hosts.h"
-#import "ExtendedNSArray.h"
-#import "ExtendedNSPredicate.h"
-
-@interface CombinedHostsPredicateController (Private)
-- (void)updateHostsFileContents;
-- (void)fillTemplate;
-@end
-
-@implementation CombinedHostsPredicateController
-
-- (id)init
-{
- self = [super init];
- rowCount = 1;
-
- return self;
-}
-
-- (void)awakeFromNib
-{
- [self bind:@"selectedFile" toObject:[HostsMainController defaultInstance] withKeyPath:@"selection" options:nil];
-
- [predicateEditor setRowHeight:25];
-
- [predicateEditor setObjectValue:[NSPredicate predicateWithFormat:@"name = ''"]];
-
- [self setSelectedFile:[[HostsMainController defaultInstance] activeHostsFile]];
-}
-
-- (IBAction)predicateEditorChanged:(id)sender
-{
- [self updateHostsFileContents];
-
- NSInteger newRowCount = [predicateEditor numberOfRows];
-
- if (newRowCount == rowCount) {
- return;
- }
-
- BOOL growing = (newRowCount > rowCount);
-
- CGFloat heightDifference = fabs([predicateEditor rowHeight] * (newRowCount - rowCount));
- NSSize sizeChange = [predicateEditor convertSize:NSMakeSize(0, heightDifference) toView:nil];
-
- NSScrollView *predicateEditorScrollView = [predicateEditor enclosingScrollView];
-
- NSRect frame = [predicateEditorScrollView frame];
- frame.size.height += growing? sizeChange.height : -sizeChange.height;
- frame.origin.y += growing? -sizeChange.height : sizeChange.height;
- [predicateEditorScrollView setFrame:frame];
-
- frame = [lowerScrollView frame];
- frame.origin.y += growing? -sizeChange.height : sizeChange.height;
- [lowerScrollView setFrame:frame];
-
- rowCount = newRowCount;
-
- [selectedHostsFile setSaved:NO];
-}
-
-- (void)setSelectedFile:(Hosts*)value
-{
- Hosts *hosts = [[HostsMainController defaultInstance] selectedHosts];
- NSScrollView *scrollView = [predicateEditor enclosingScrollView];
-
- if ([hosts isMemberOfClass:[CombinedHosts class]]) {
- int previousRowCount = rowCount;
- [scrollView setHidden:NO];
- [predicateEditor reloadCriteria];
-
- selectedHostsFile = (CombinedHosts*)hosts;
- [self fillTemplate];
-
- int rowHeight = [predicateEditor rowHeight];
- rowCount = [predicateEditor numberOfRows];
- int height = rowCount * rowHeight;
- int difference = (rowCount - previousRowCount) * rowHeight;
-
- NSRect frame = [lowerScrollView frame];
- frame.origin.y = 0;
- frame.size.height = [parentView frame].size.height - height;
- [lowerScrollView setFrame:frame];
-
- NSRect frame2 = [scrollView frame];
- frame2.size.height = height;
- frame2.origin.y -= difference;
- [scrollView setFrame:frame2];
-
- if ([[selectedHostsFile hostsFiles] count] == 0 && hintView == nil) {
- hintView = [[NSImageView alloc] initWithFrame:NSMakeRect(140, -20, 210, 99)];
- [hintView setImage:[NSImage imageNamed: @"Combined Hosts Hint.png"]];
- [lowerScrollView addSubview:hintView];
- }
- else if (hintView != nil) {
- [hintView removeFromSuperview];
- hintView = nil;
- }
-
- } else {
- [scrollView setHidden:YES];
- NSRect frame = [lowerScrollView frame];
- frame.size.height = [parentView frame].size.height;
- frame.origin.y = 0;
- [lowerScrollView setFrame:frame];
-
- if (hintView != nil) {
- [hintView removeFromSuperview];
- hintView = nil;
- }
- }
-}
-- (Hosts*)selectedFile
-{
- return selectedHostsFile;
-}
-
-@end
-
-@implementation CombinedHostsPredicateController (Private)
-
-- (void)updateHostsFileContents
-{
- if (selectedHostsFile == nil) {
- return;
- }
-
- logDebug(@"Updating hosts file: \"%@\"", [selectedHostsFile name]);
-
- NSPredicate *predicate = [predicateEditor predicate];
- if (predicate == nil) {
- return;
- }
-
- NSArray *predicates;
-
- if ([predicateEditor numberOfRows] > 1 && [predicate containsNestedPredicates]) {
- NSCompoundPredicate * compound = (NSCompoundPredicate*)predicate;
- predicates = [compound subpredicates];
- }
- else {
- predicates = [NSArray arrayWithObject:predicate];
- }
-
- NSArray *files = [[[HostsMainController defaultInstance] allHostsFiles] filteredOrderedArrayUsingPredicates:predicates];
-
- [selectedHostsFile setHostsFiles:files];
-
- if (hintView != nil) {
- [hintView removeFromSuperview];
- hintView = nil;
- }
-}
-
-- (void)fillTemplate
-{
- BOOL emptyPredicate = YES;
- NSMutableArray *predicates = [NSMutableArray new];
- for (Hosts *hosts in [selectedHostsFile hostsFiles]) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"type = %@ AND name = %@" argumentArray:[NSArray arrayWithObjects:[hosts type], [hosts name], nil]];
- [predicates addObject:predicate];
- emptyPredicate = NO;
- }
-
- if (emptyPredicate) {
- [predicates addObject:[NSPredicate predicateWithFormat:@"name = ''"]];
- }
-
- NSPredicate *compound = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
- [predicateEditor setObjectValue:compound];
-}
-
-@end
diff --git a/Source/CombinedHostsPredicateEditorRowTemplate.h b/Source/CombinedHostsPredicateEditorRowTemplate.h
deleted file mode 100644
index c108211..0000000
--- a/Source/CombinedHostsPredicateEditorRowTemplate.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@interface CombinedHostsPredicateEditorRowTemplate : NSPredicateEditorRowTemplate {
- @private
- NSTextField * textField;
- NSPopUpButton *select;
-}
-
-@end
diff --git a/Source/CombinedHostsPredicateEditorRowTemplate.m b/Source/CombinedHostsPredicateEditorRowTemplate.m
deleted file mode 100644
index b239101..0000000
--- a/Source/CombinedHostsPredicateEditorRowTemplate.m
+++ /dev/null
@@ -1,152 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "CombinedHostsPredicateEditorRowTemplate.h"
-#import "HostsMainController.h"
-#import "RemoteHosts.h"
-#import "Pair.h"
-#import "CombinedHosts.h"
-
-@interface CombinedHostsPredicateEditorRowTemplate (Private)
-- (NSTextField*)label;
-- (NSPopUpButton*)select;
-- (void)populateSelectMenu;
-- (IBAction)hostsFileRemoved:(NSNotification *)notification;
-- (IBAction)hostsFileAdded:(NSNotification *)notification;
-- (IBAction)hostsFileRenamed:(NSNotification *)notification;
-@end
-
-@implementation CombinedHostsPredicateEditorRowTemplate
-
-- (void)awakeFromNib
-{
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self selector:@selector(hostsFileRemoved:) name:HostsFileRemovedNotification object:nil];
- [nc addObserver:self selector:@selector(hostsFileAdded:) name:HostsFileCreatedNotification object:nil];
- [nc addObserver:self selector:@selector(hostsFileRenamed:) name:HostsFileRenamedNotification object:nil];
-}
-
-- (NSArray *) templateViews
-{
- return [NSArray arrayWithObjects:[self label], [self select], nil];
-}
-
-- (double)matchForPredicate:(NSPredicate *)predicate
-{
- return 1;
-}
-
-- (NSPredicate *)predicateWithSubpredicates:(NSArray *)subpredicates
-{
-
- NSMenuItem * item = [[self select] selectedItem];
- Hosts *hosts = (Hosts*)[item representedObject];
- if (hosts == nil) {
- return nil;
- }
-
- return [NSPredicate predicateWithFormat:@"type = %@ AND name = %@" argumentArray:[NSArray arrayWithObjects:[hosts type], [hosts name], nil]];
-}
-
-- (void)setPredicate:(NSPredicate *)predicate
-{
- NSMenu *menu = [[self select] menu];
- for (NSMenuItem * item in [menu itemArray]) {
- Hosts *hosts = [item representedObject];
- if ([predicate evaluateWithObject:hosts]) {
- [[self select] selectItem:item];
- return;
- }
- }
-
- [[self select] selectItemAtIndex:0];
-}
-
-@end
-
-@implementation CombinedHostsPredicateEditorRowTemplate (Private)
-
-- (NSTextField*)label
-{
- if (textField == nil) {
- textField = [[NSTextField alloc] init];
- [textField setFrame:NSMakeRect(0, 0, 100, 15)];
- [textField setEditable:NO];
- [textField setSelectable:NO];
- [textField setBordered:NO];
- [textField setDrawsBackground:NO];
- [textField setAlignment:NSCenterTextAlignment];
- [textField setTitleWithMnemonic:@"Hosts File:"];
- }
- return textField;
-}
-
-- (NSPopUpButton*)select
-{
- if (select == nil) {
- select = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 200, 15) pullsDown:YES];
- [self populateSelectMenu];
- }
- return select;
-}
-
-- (void)populateSelectMenu
-{
- [select removeAllItems];
- [select addItemWithTitle:@" "];
-
- NSMenu *menu = [select menu];
-
- NSArray *allHosts = [[HostsMainController defaultInstance] allHostsFiles];
- for (Hosts *hosts in allHosts) {
- if ([hosts isKindOfClass:[CombinedHosts class]]) {
- continue;
- }
- NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[hosts name] action:NULL keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [menu addItem:item];
- }
-}
-
-- (IBAction)hostsFileRemoved:(NSNotification *)notification
-{
- Hosts *removedHosts = [notification object];
- NSMenu *menu = [[self select] menu];
- for (NSMenuItem * item in [menu itemArray]) {
- Hosts *hosts = [item representedObject];
- if ([removedHosts isEqualTo:hosts]) {
- [menu removeItem:item];
- break;
- }
- }
-}
-
-- (IBAction)hostsFileAdded:(NSNotification *)notification
-{
- logDebug(@"Hosts file added: %@", [[notification object] name]);
- [self populateSelectMenu];
-}
-
-- (IBAction)hostsFileRenamed:(NSNotification *)notification
-{
- [self populateSelectMenu];
-}
-
-@end
diff --git a/Source/EditorController.h b/Source/EditorController.h
deleted file mode 100644
index 087845e..0000000
--- a/Source/EditorController.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-
-@interface EditorController : NSObject {
- IBOutlet NSSplitView *splitView;
- IBOutlet NSWindow *editorWindow;
- IBOutlet NSTextField *filesCountTextField;
- IBOutlet NSImageView *readOnlyIconView;
-}
-
-@end
diff --git a/Source/EditorController.m b/Source/EditorController.m
deleted file mode 100644
index 5d60de7..0000000
--- a/Source/EditorController.m
+++ /dev/null
@@ -1,100 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "EditorController.h"
-#import "Preferences.h"
-#import "ExtendedNSSplitView.h"
-#import "Gas_Mask-Swift.h"
-
-#define SplitViewMinWidth 140
-#define SplitViewMaxWidth 300
-#define SplitViewDefaultWidth 160
-
-
-@implementation EditorController
-
-- (void)awakeFromNib
-{
- [editorWindow setContentBorderThickness: [splitView frame].origin.y forEdge: NSMinYEdge];
- [[filesCountTextField cell] setBackgroundStyle: NSBackgroundStyleRaised];
-
- [readOnlyIconView setToolTip:@"Hosts file can not be modified"];
-
- int dividerIndex = 0;
- CGFloat position = [splitView positionOfDividerAtIndex:dividerIndex];
- if (position > SplitViewMaxWidth) {
- [splitView setPosition:SplitViewDefaultWidth ofDividerAtIndex:dividerIndex];
- }
-
- [SidebarInstaller installIn:splitView];
- [ContentInstaller installIn:splitView];
-}
-
-#pragma mark - Split View Delegate
-
-- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex;
-{
- return proposedMinimumPosition + SplitViewMinWidth;
-}
-
-- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex;
-{
- return SplitViewMaxWidth;
-}
-
-- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
-{
- NSRect newFrame = [sender frame];
- NSView *left = [[sender subviews] objectAtIndex:0];
- NSRect leftFrame = [left frame];
- NSView *right = [[sender subviews] objectAtIndex:1];
- NSRect rightFrame = [right frame];
-
- CGFloat dividerThickness = [sender dividerThickness];
-
- leftFrame.size.height = newFrame.size.height;
-
- rightFrame.size.width = newFrame.size.width - leftFrame.size.width - dividerThickness;
- rightFrame.size.height = newFrame.size.height;
- rightFrame.origin.x = leftFrame.size.width + dividerThickness;
-
- [left setFrame:leftFrame];
- [right setFrame:rightFrame];
-}
-
-- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview
-{
- return NO;
-}
-
-#pragma mark - NSWindow Delegate
-
-- (void)windowDidBecomeMain:(NSNotification *)notification
-{
- [Preferences setShowEditorWindow:YES];
-}
-
-- (BOOL)windowShouldClose:(id)sender
-{
- [Preferences setShowEditorWindow:NO];
- return YES;
-}
-
-@end
diff --git a/Source/ExtendedNSSplitView.h b/Source/ExtendedNSSplitView.h
deleted file mode 100644
index 269ff06..0000000
--- a/Source/ExtendedNSSplitView.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2013 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@interface NSSplitView (Extended)
-- (CGFloat)positionOfDividerAtIndex:(NSInteger)dividerIndex;
-@end
diff --git a/Source/ExtendedNSSplitView.m b/Source/ExtendedNSSplitView.m
deleted file mode 100644
index cb13d31..0000000
--- a/Source/ExtendedNSSplitView.m
+++ /dev/null
@@ -1,39 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2013 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "ExtendedNSSplitView.h"
-
-@implementation NSSplitView (Extended)
-
-- (CGFloat)positionOfDividerAtIndex:(NSInteger)dividerIndex
-{
- while (dividerIndex >= 0 && [self isSubviewCollapsed:[[self subviews] objectAtIndex:dividerIndex]]) {
- dividerIndex--;
- }
-
- if (dividerIndex < 0) {
- return 0.0f;
- }
-
- NSRect priorViewFrame = [[[self subviews] objectAtIndex:dividerIndex] frame];
- return [self isVertical] ? NSMaxX(priorViewFrame) : NSMaxY(priorViewFrame);
-}
-
-@end
diff --git a/Source/FilesCountTransformer.h b/Source/FilesCountTransformer.h
deleted file mode 100644
index 71e76f5..0000000
--- a/Source/FilesCountTransformer.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@interface FilesCountTransformer : NSValueTransformer
-@end
diff --git a/Source/FilesCountTransformer.m b/Source/FilesCountTransformer.m
deleted file mode 100644
index a71321d..0000000
--- a/Source/FilesCountTransformer.m
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "FilesCountTransformer.h"
-
-
-@implementation FilesCountTransformer
-
-+ (Class)transformedValueClass
-{
- return [NSString class];
-}
-
-+ (BOOL)allowsReverseTransformation
-{
- return NO;
-}
-
-- (id)transformedValue:(id)count
-{
- if ([count intValue] == 0) {
- return @"No files";
- }
- else if ([count intValue] == 1) {
- return @"One file";
- }
- else {
- return [NSString stringWithFormat:@"%d files", [count intValue]];
- }
-}
-
-@end
\ No newline at end of file
diff --git a/Source/HostsListView.h b/Source/HostsListView.h
deleted file mode 100644
index 8e4af8b..0000000
--- a/Source/HostsListView.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class Cell;
-
-@interface HostsListView : NSOutlineView {
- @private
- BOOL showEmptyHostsGroups;
- Cell *cell;
-}
-
-@property (readonly) BOOL showEmptyHostsGroups;
-
-- (void)removeBadgesFromGroups;
-
-@end
diff --git a/Source/HostsListView.m b/Source/HostsListView.m
deleted file mode 100644
index a36c8da..0000000
--- a/Source/HostsListView.m
+++ /dev/null
@@ -1,151 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "HostsListView.h"
-#import "HostsListViewMenu.h"
-#import "HostsGroup.h"
-#import "Hosts.h"
-#import "Cell.h"
-
-#define kColumnIdName @"NameColumn"
-
-@interface HostsListView (Private)
-
-- (void)hideEmptyHostsGroups;
-
-@end
-
-
-@implementation HostsListView
-
-
-@synthesize showEmptyHostsGroups;
-
-- (void)awakeFromNib
-{
- [self registerForDraggedTypes:@[NSPasteboardTypeString, NSPasteboardTypeFileURL]];
- [self setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
- [self setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO];
-
- [self setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
-
- NSTableColumn *tableColumn = [self tableColumnWithIdentifier:kColumnIdName];
- cell = [[Cell alloc] init];
- [cell setEditable:YES];
- [tableColumn setDataCell:cell];
-
-}
-
-
-- (NSMenu *)menuForEvent:(NSEvent *)theEvent
-{
- NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
- int row = [self rowAtPoint:point];
-
- if (row == -1) {
- return nil;
- }
-
- Hosts *hosts = [[self itemAtRow:row] representedObject];
- if (![hosts selectable]) {
- return nil;
- }
-
- [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
-
- return [[HostsListViewMenu alloc] initWithHosts:hosts];
-}
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
-{
- return YES;
-}
-
-/* Removes all badges from HostGroup items.
- It is needed because item with no height will not be redrawn and bages
- would not be removed.
- */
-- (void)removeBadgesFromGroups
-{
- for (int i=0; i<[self numberOfRows]; i++) {
- Hosts *hosts = (Hosts*)[[self itemAtRow:i] representedObject];
- if ([hosts isKindOfClass:[HostsGroup class]]) {
-
- [cell setItem:hosts];
- [cell removeAllBadges];
-
- }
- }
-}
-
-#pragma mark -
-#pragma mark NSDraggingSource
-
-- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation
-{
- // Dragged item ended up in Trash
- if (operation == NSDragOperationDelete) {
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc postNotificationName:DraggedFileShouldBeRemovedNotification object:nil];
- }
- else {
- [super draggedImage:image endedAt:screenPoint operation:operation];
- }
-}
-
-#pragma mark -
-#pragma mark NSDraggingDestination
-
-- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
-{
- // Unhide empty hosts groups
- showEmptyHostsGroups = YES;
- [self reloadData];
-
- return [super draggingEntered:sender];
-}
-
-- (void)draggingEnded:(id < NSDraggingInfo >)sender
-{
- [self hideEmptyHostsGroups];
-}
-
-- (void)draggingExited:(id < NSDraggingInfo >)sender
-{
- [self hideEmptyHostsGroups];
- [super draggingExited:sender];
-}
-
-@end
-
-@implementation HostsListView (Private)
-
-- (void)hideEmptyHostsGroups
-{
- if (showEmptyHostsGroups) {
- showEmptyHostsGroups = NO;
-
- [self removeBadgesFromGroups];
- [self reloadData];
- }
-}
-
-@end
-
diff --git a/Source/HostsListViewMenu.h b/Source/HostsListViewMenu.h
deleted file mode 100644
index 32dcdba..0000000
--- a/Source/HostsListViewMenu.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class Hosts;
-
-@interface HostsListViewMenu : NSMenu
-
-- (id)initWithHosts:(Hosts*)hosts;
-
-@end
diff --git a/Source/HostsListViewMenu.m b/Source/HostsListViewMenu.m
deleted file mode 100644
index b31728e..0000000
--- a/Source/HostsListViewMenu.m
+++ /dev/null
@@ -1,103 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "HostsListViewMenu.h"
-#import "HostsMainController.h"
-#import "Hosts.h"
-#import "RemoteHosts.h"
-#import "LocalHostsController.h"
-
-
-@implementation HostsListViewMenu
-
-- (id)initWithHosts:(Hosts*)hosts
-{
- self = [self init];
- [self setAutoenablesItems:NO];
-
- HostsMainController *controller = [HostsMainController defaultInstance];
- NSMenuItem *item;
-
- if (![hosts saved]) {
- item = [[NSMenuItem alloc] initWithTitle:@"Save" action:@selector(save:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setTarget:controller];
- [self addItem:item];
- }
-
- if (![hosts active]) {
- item = [[NSMenuItem alloc] initWithTitle:@"Activate" action:@selector(activate:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setEnabled:[hosts exists]];
- [item setTarget:controller];
- [self addItem:item];
- }
-
- item = [[NSMenuItem alloc] initWithTitle:@"Show In Finder" action:@selector(showInFinder:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setTarget:self];
- [item setEnabled:[hosts exists]];
- [self addItem:item];
-
- if ([controller canRemoveFiles]) {
- item = [[NSMenuItem alloc] initWithTitle:@"Remove" action:@selector(remove:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setTarget:controller];
- [self addItem:item];
- }
-
- if ([hosts isMemberOfClass:[RemoteHosts class]]) {
- [self addItem:[NSMenuItem separatorItem]];
-
- item = [[NSMenuItem alloc] initWithTitle:@"Move to Local" action:@selector(moveToLocal:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setTarget:self];
- [item setEnabled:[hosts exists]];
- [self addItem:item];
-
- [self addItem:[NSMenuItem separatorItem]];
-
- item = [[NSMenuItem alloc] initWithTitle:@"Open in Browser" action:@selector(openInBrowser:) keyEquivalent:@""];
- [item setRepresentedObject:hosts];
- [item setTarget:self];
- [self addItem:item];
- }
-
- return self;
-}
-
-- (IBAction)openInBrowser:(id)sender
-{
- [[NSWorkspace sharedWorkspace] openURL:[[sender representedObject] url]];
-}
-
-- (IBAction)showInFinder:(id)sender
-{
- NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
- NSString *path = [[sender representedObject] path];
- [workspace selectFile: path inFileViewerRootedAtPath:@""];
-}
-
-- (IBAction)moveToLocal:(id)sender
-{
- [[HostsMainController defaultInstance] move:[sender representedObject] toControllerClass:[LocalHostsController class]];
-}
-
-@end
diff --git a/Source/HostsTextController.h b/Source/HostsTextController.h
deleted file mode 100644
index 7e789dc..0000000
--- a/Source/HostsTextController.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-@class HostsTextView;
-
-@interface HostsTextController : NSObject {
- @private
- IBOutlet HostsTextView *view;
-}
-
-@end
diff --git a/Source/HostsTextController.m b/Source/HostsTextController.m
deleted file mode 100644
index 540e02a..0000000
--- a/Source/HostsTextController.m
+++ /dev/null
@@ -1,58 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "HostsTextController.h"
-#import "HostsTextView.h"
-#import "Preferences.h"
-#import "HostsMainController.h"
-
-@interface HostsTextController (Private)
-
-- (void)bindValue;
-
-@end
-
-
-
-@implementation HostsTextController
-
-- (void)awakeFromNib
-{
- [self bindValue];
- [view bind:@"syntaxHighlighting" toObject:[Preferences instance] withKeyPath:@"values.syntaxHighlighting" options:nil];
-}
-
-- (void)bindValue:(NSNotification *)notification
-{
- logDebug(@"Bind?");
- //[self bindValue];
-}
-@end
-
-@implementation HostsTextController (Private)
-
-- (void)bindValue
-{
- NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:NSContinuouslyUpdatesValueBindingOption];
- [view bind:@"value" toObject:[HostsMainController defaultInstance] withKeyPath:@"selection.contents" options:options];
-}
-
-@end
-
diff --git a/Source/ListController.h b/Source/ListController.h
deleted file mode 100644
index 6129004..0000000
--- a/Source/ListController.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-
-@class HostsMainController, Hosts, HostsListView;
-
-@interface ListController : NSObject {
- @private
- IBOutlet HostsListView *list;
- IBOutlet HostsMainController *hostsController;
- Hosts *draggedHosts;
-}
-
-+ (ListController*)defaultInstance;
-
-- (Hosts*)selectedHosts;
-- (void)deactivate;
-
-@end
diff --git a/Source/ListController.m b/Source/ListController.m
deleted file mode 100644
index f1b6b22..0000000
--- a/Source/ListController.m
+++ /dev/null
@@ -1,437 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "NSToolbarPoofAnimator.h"
-
-#import "ListController.h"
-#import "HostsListView.h"
-#import "Node.h"
-#import "Cell.h"
-#import "Hosts.h"
-#import "HostsGroup.h"
-#import "RemoteHosts.h"
-#import "HostsMainController.h"
-
-#define kFileURLType @"public.file-url"
-#define kTextType @"public.utf8-plain-text"
-
-#define kHostsHeight 20.0
-#define kEmptyHostsGroupHeight 0.1
-
-@interface ListController (Private)
-- (void)hostsFilesLoaded:(NSNotification *)notification;
-- (void)selectActiveHostsFile;
-- (void)expandAllItems;
-- (void)showEditError:(NSString*)message;
-- (NSString*)urlFromPasteBoard:(NSPasteboard*)pasteboard;
-- (BOOL)allowToDropTo:(Hosts*)target;
-- (int)indexOfHosts:(Hosts*)hosts;
-- (NSPoint)locationOfHosts:(Hosts*)hosts;
-- (NSPoint)rightCenterLocationOfHosts:(Hosts*)hosts;
-- (NSPoint)centerLocationOfHostsOnScreen:(Hosts*)hosts;
-@end
-
-@implementation ListController
-
-static ListController *sharedInstance = nil;
-
-+ (ListController*)defaultInstance
-{
- return sharedInstance;
-}
-
-- (id)init
-{
- if (sharedInstance) {
- return sharedInstance;
- }
- if (self = [super init]) {
-
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self selector:@selector(updateItem:) name:HostsNodeNeedsUpdateNotification object:nil];
- [nc addObserver:self selector:@selector(updateItem:) name:SynchronizingStatusChangedNotification object:nil];
- [nc addObserver:self selector:@selector(renameHostsFile:) name:HostsFileShouldBeRenamedNotification object:nil];
- [nc addObserver:self selector:@selector(selectHostsFile:) name:HostsFileShouldBeSelectedNotification object:nil];
- [nc addObserver:self selector:@selector(deleteDraggedHostsFile:) name:DraggedFileShouldBeRemovedNotification object:nil];
- [nc addObserver:self selector:@selector(handleHostsFileRemoval:) name:HostsFileWillBeRemovedNotification object:nil];
- [nc addObserver:self selector:@selector(hostsFilesLoaded:) name:AllHostsFilesLoadedFromDiskNotification object:nil];
-
- sharedInstance = self;
- }
- return sharedInstance;
-}
-
-- (void)awakeFromNib
-{
- [self expandAllItems];
- [self selectActiveHostsFile];
-}
-
-- (void)deactivate
-{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-}
-
-- (void)updateItem:(NSNotification *)notification
-{
- int index = [self indexOfHosts:[notification object]];
- [list reloadItem:[list itemAtRow:index]];
-}
-
-- (Hosts*) selectedHosts
-{
- return [[list itemAtRow:[list selectedRow]] representedObject];
-}
-
-@end
-
-@implementation ListController (Private)
-
-- (void)hostsFilesLoaded:(NSNotification *)notification
-{
- [self expandAllItems];
- [self selectActiveHostsFile];
-}
-
-- (void)selectActiveHostsFile
-{
- for (int i=0; i<[list numberOfRows]; i++) {
- Hosts *hosts = [[list itemAtRow:i] representedObject];
- if ([hosts active]) {
-
- logInfo(@"Selecting active item: %@", [hosts name]);
- NSIndexSet *idx = [[NSIndexSet alloc] initWithIndex:i];
- [list selectRowIndexes:idx byExtendingSelection:NO];
-
- return;
- }
- }
- logWarn(@"No active item to select!");
-}
-
-- (void)renameHostsFile:(NSNotification *)notification
-{
- [list editColumn:0 row:[self indexOfHosts:[notification object]] withEvent:nil select:YES];
-}
-
-- (void)selectHostsFile:(NSNotification *)notification
-{
- int index = [self indexOfHosts:[notification object]];
- NSIndexSet *idx = [[NSIndexSet alloc] initWithIndex:index];
- [list selectRowIndexes:idx byExtendingSelection:NO];
-}
-
-- (void)deleteDraggedHostsFile:(NSNotification *)notification
-{
- if ([hostsController canRemoveFiles]) {
- [hostsController removeHostsFile:draggedHosts moveToTrash:YES];
- draggedHosts = nil;
- }
-}
-
-- (void)handleHostsFileRemoval:(NSNotification *)notification
-{
- [list removeBadgesFromGroups];
-
- // Let's have some fun :)
- NSPoint point = [self centerLocationOfHostsOnScreen:[notification object]];
- [NSToolbarPoofAnimator runPoofAtPoint:point];
-}
-
-
-- (void)expandAllItems
-{
- logDebug(@"Expanding all items");
- for (int i=0; i<[list numberOfRows]; i++) {
- [list expandItem:[list itemAtRow:i]];
- }
-}
-
-
-#pragma mark -
-#pragma mark NSOutlineView delegate
-
--(BOOL)outlineView:(NSOutlineView*)outlineView isGroupItem:(id)item
-{
- return [[item representedObject] isGroup];
-}
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
-{
- return [[item representedObject] selectable];
-}
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item
-{
- return NO;
-}
-
-- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
-{
- [(Cell*)cell setItem:[item representedObject]];
-}
-
-- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
-{
- Hosts *hosts = [item representedObject];
- if (![list showEmptyHostsGroups] && [hosts isMemberOfClass:[HostsGroup class]] && [[hosts children] count] == 0) {
- return kEmptyHostsGroupHeight;
- }
-
- return kHostsHeight;
-}
-
-#pragma mark -
-#pragma mark Drag and Drop
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
-{
- Hosts *hosts = [[items objectAtIndex:0] representedObject];
- if ([hosts isKindOfClass:[HostsGroup class]]) {
- return NO;
- }
-
- [pboard setString:[hosts contents] forType:NSPasteboardTypeString];
- draggedHosts = hosts;
-
- return YES;
-}
-
-/*
- Proposing data for dropping.
- */
-- (NSDragOperation)outlineView:(NSOutlineView *)ov validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(NSInteger)childIndex
-{
- Hosts *destinationHosts = [item representedObject];
- if (destinationHosts == nil) {
- return NSDragOperationNone;
- }
-
- // Data is dragged from external application
- if ([info draggingSource] == nil) {
-
- NSString *rawURL = [self urlFromPasteBoard:[info draggingPasteboard]];
-
- // URL is dragged to the list
- if (rawURL) {
-
- id target = item;
- if (![destinationHosts isMemberOfClass:[HostsGroup class]]) {
- target = [list parentForItem:item];
- }
-
- NSURL *url = [NSURL URLWithString:rawURL];
- // Local URL
- if ([url isFileURL]) {
- if (![[rawURL pathExtension] isEqual:HostsFileExtension]) {
- return NSDragOperationNone;
- }
-
- if (![hostsController canCreateHostsFromLocalURL:url toGroup:(HostsGroup*)[target representedObject]]) {
- return NSDragOperationNone;
- }
- }
- // Remote URL
- else {
- if (![hostsController canCreateHostsFromURL:url toGroup:(HostsGroup*)[target representedObject]]) {
- return NSDragOperationNone;
- }
- }
-
- [list setDropItem:target dropChildIndex:NSOutlineViewDropOnItemIndex];
-
- return NSDragOperationGeneric;
- }
-
- return NSDragOperationNone;
- }
-
- NSDragOperation result = NSDragOperationGeneric;
-
- id target = item;
- if ([destinationHosts isMemberOfClass:[Hosts class]]) {
- target = [list parentForItem:item];
- }
-
- if ([info draggingSource] == list) {
- if (![self allowToDropTo:destinationHosts]) {
- return NSDragOperationNone;
- }
- }
-
- [list setDropItem:target dropChildIndex:NSOutlineViewDropOnItemIndex];
-
- return result;
-}
-
-/*
- Actually droping data.
- */
-- (BOOL)outlineView:(NSOutlineView *)ov acceptDrop:(id )info item:(id)item childIndex:(NSInteger)childIndex
-{
-
- if ([info draggingSource] == list) {
- [hostsController move:draggedHosts to:[item representedObject]];
- draggedHosts = nil;
- return YES;
- }
-
- NSString *rawURL = [self urlFromPasteBoard:[info draggingPasteboard]];
- if (rawURL) {
- NSURL *url = [NSURL URLWithString:rawURL];
- HostsGroup *group = [item representedObject];
-
- // Local URL
- if ([url isFileURL]) {
- return [hostsController createHostsFromLocalURL:url toGroup:group];
- }
- // WEB URL
- else {
- logDebug(@"Creating from URL \"%@\" to group \"%@\"", [url absoluteString], group);
-
- return [hostsController createHostsFromURL:url toGroup:group];
- }
- }
-
- return NO;
-}
-
-
-- (NSArray *)outlineView:(NSOutlineView *)outlineView namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedItems:(NSArray *)items
-{
- // TODO
- logDebug(@"PROMISE!");
- return nil;
-}
-
-- (NSString*)urlFromPasteBoard:(NSPasteboard*)pasteboard
-{
- for (NSPasteboardItem *item in [pasteboard pasteboardItems]) {
- if ([[item types] containsObject:kFileURLType]) {
- return [item stringForType:kFileURLType];
- }
- }
-
- for (NSPasteboardItem *item in [pasteboard pasteboardItems]) {
- if ([[item types] containsObject:kTextType]) {
- NSString *text = [item stringForType:kTextType];
- NSURL *url = [NSURL URLWithString:text];
- if (url && [url scheme] != nil) {
- return text;
- }
- }
- }
-
- return nil;
-}
-
-- (BOOL)allowToDropTo:(Hosts*)target
-{
- if ([draggedHosts isMemberOfClass:[RemoteHosts class]]) {
- if ([target isMemberOfClass:[Hosts class]] && [draggedHosts exists]) {
- return YES;
- }
- }
- return NO;
-}
-
-- (int)indexOfHosts:(Hosts*)hosts
-{
- for (int i=0; i<[list numberOfRows]; i++) {
- Hosts *obj = [[list itemAtRow:i] representedObject];
- if ([obj isEqual:hosts]) {
- return i;
- }
- }
-
- return -1;
-}
-
-- (NSPoint)locationOfHosts:(Hosts*)hosts
-{
- NSRect frame = [list rectOfRow:[self indexOfHosts:hosts]];
-
- NSPoint widgetOrigin = frame.origin;
- NSPoint point = [list convertPoint:widgetOrigin toView:nil];
-
- return point;
-}
-
-- (NSPoint)rightCenterLocationOfHosts:(Hosts*)hosts
-{
- NSPoint point = [self locationOfHosts:hosts];
- NSRect frame = [list rectOfRow:[list selectedRow]];
-
- point.x += frame.size.width;
- point.y -= frame.size.height / 2;
-
- return point;
-}
-
-- (NSPoint)centerLocationOfHostsOnScreen:(Hosts*)hosts
-{
- NSPoint hostsPoint = [self locationOfHosts:hosts];
-
- NSRect frame = [list rectOfRow:[list selectedRow]];
-
- hostsPoint.x += frame.size.width / 2;
- hostsPoint.y -= frame.size.height / 2;
-
- NSPoint point = [[NSApp mainWindow] frame].origin;
- point.x += hostsPoint.x;
- point.y += hostsPoint.y;
-
- return point;
-}
-
-#pragma mark -
-#pragma mark NSControlTextEditingDelegate
-
-- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
-{
- Hosts *selectedHosts = [self selectedHosts];
-
- // Nothing changed
- if ([[selectedHosts name] isEqualToString:[fieldEditor string]]) {
- return YES;
- }
-
- NSRange range = [[fieldEditor string] rangeOfString:@"/"];
- if (range.location != NSNotFound) {
- [self showEditError:@"File Name Can Not Contain Forward Slash."];
- [fieldEditor setString:[selectedHosts name]];
- return YES;
- }
-
- BOOL renamed = [hostsController rename:selectedHosts to:[fieldEditor string]];
- if (renamed) {
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc postNotificationName:HostsFileRenamedNotification object:selectedHosts];
- }
- else {
- [self showEditError:@"File With Specified Name Already Exists."];
- [fieldEditor setString:[selectedHosts name]];
- return YES;
- }
-
- return YES;
-}
-
-@end
diff --git a/Source/NSToolbarPoofAnimator.h b/Source/NSToolbarPoofAnimator.h
deleted file mode 100644
index 9063fb3..0000000
--- a/Source/NSToolbarPoofAnimator.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import
-
-@interface NSToolbarPoofAnimator:NSObject
-
-+ (void)runPoofAtPoint:(NSPoint)location;
-
-@end
\ No newline at end of file
diff --git a/Source/OfflineBadge.h b/Source/OfflineBadge.h
deleted file mode 100644
index 290c04f..0000000
--- a/Source/OfflineBadge.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "Badge.h"
-
-@class Hosts;
-
-@interface OfflineBadge : Badge {
- @private
- NSImage *icon;
- NSImage *rolloverIcon;
- Hosts *hosts;
-}
-
-- (id)initWithHosts:(Hosts*)hostsValue;
-
-@end
diff --git a/Source/OfflineBadge.m b/Source/OfflineBadge.m
deleted file mode 100644
index f47e4be..0000000
--- a/Source/OfflineBadge.m
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2012 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "OfflineBadge.h"
-#import "ListController.h"
-#import "Hosts.h"
-
-
-@implementation OfflineBadge
-
-- (id)initWithHosts:(Hosts*)hostsValue
-{
- self = [super init];
- icon = [NSImage imageNamed: @"Offline.png"];
- rolloverIcon = [NSImage imageNamed: @"Offline_rollover.png"];
- hosts = hostsValue;
-
- [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:[self frame]
- options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
- owner:self
- userInfo:nil]];
-
- [self setActiveIcon:icon];
-
- return self;
-}
-
-- (void)mouseEntered:(NSEvent *)theEvent
-{
- [self setActiveIcon:rolloverIcon];
-}
-
-- (void)mouseExited:(NSEvent *)theEvent
-{
- [self setActiveIcon:icon];
-}
-
-@end
diff --git a/Source/Swift/ContentInstaller.swift b/Source/Swift/ContentInstaller.swift
deleted file mode 100644
index d4d8531..0000000
--- a/Source/Swift/ContentInstaller.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-import SwiftUI
-
-@objc final class ContentInstaller: NSObject {
- @objc static func install(in splitView: NSSplitView) {
- guard splitView.subviews.count >= 2 else { return }
-
- let store = HostsDataStore.shared
- let content = ContentView(store: store)
- let hostingView = NSHostingView(rootView: content)
-
- let rightPane = splitView.subviews[1]
- hostingView.frame = rightPane.frame
- hostingView.autoresizingMask = [.width, .height]
- splitView.replaceSubview(rightPane, with: hostingView)
- }
-}
diff --git a/Source/Swift/EditorToolbar.swift b/Source/Swift/EditorToolbar.swift
new file mode 100644
index 0000000..f7bbee1
--- /dev/null
+++ b/Source/Swift/EditorToolbar.swift
@@ -0,0 +1,75 @@
+import SwiftUI
+
+struct EditorToolbar: ToolbarContent {
+ @ObservedObject var store: HostsDataStore
+
+ @State private var hostsToRemove: Hosts?
+
+ var body: some ToolbarContent {
+ ToolbarItem(id: "create", placement: .automatic) {
+ Menu {
+ Button("Local") {
+ HostsMainController.defaultInstance()?.createNewHostsFile(nil)
+ }
+ Button("Remote") {
+ URLSheetPresenter.presentInWindow(nil)
+ }
+ Button("Combined") {
+ HostsMainController.defaultInstance()?.createCombinedHostsFile(nil)
+ }
+ } label: {
+ Label("Create", systemImage: "plus")
+ }
+ }
+
+ ToolbarItem(id: "remove", placement: .automatic) {
+ Button {
+ hostsToRemove = store.selectedHosts
+ } label: {
+ Label("Remove", systemImage: "minus")
+ }
+ .disabled(!store.canRemoveFiles || store.selectedHosts == nil)
+ .alert("Remove Hosts File", isPresented: Binding(
+ get: { hostsToRemove != nil },
+ set: { if !$0 { hostsToRemove = nil } }
+ )) {
+ Button("Cancel", role: .cancel) { hostsToRemove = nil }
+ Button("Remove", role: .destructive) {
+ if let hosts = hostsToRemove {
+ HostsMainController.defaultInstance()?.removeHostsFile(hosts, moveToTrash: true)
+ }
+ hostsToRemove = nil
+ }
+ } message: {
+ Text("Are you sure you want to remove \"\(hostsToRemove?.name() ?? "")\"? The file will be moved to Trash.")
+ }
+ }
+
+ ToolbarItem(id: "save", placement: .automatic) {
+ Button {
+ if let hosts = store.selectedHosts {
+ HostsMainController.defaultInstance()?.save(hosts)
+ }
+ } label: {
+ Label("Save", systemImage: "square.and.arrow.down")
+ }
+ .keyboardShortcut("s", modifiers: .command)
+ .disabled(store.selectedHosts == nil || store.selectedHosts?.saved() != false)
+ }
+
+ ToolbarItem(id: "activate", placement: .automatic) {
+ Button {
+ if let hosts = store.selectedHosts {
+ HostsMainController.defaultInstance()?.activateHostsFile(hosts)
+ }
+ } label: {
+ Label("Activate", systemImage: "power")
+ }
+ .disabled(
+ store.selectedHosts == nil
+ || store.selectedHosts?.active() == true
+ || store.selectedHosts?.exists != true
+ )
+ }
+ }
+}
diff --git a/Source/Swift/EditorView.swift b/Source/Swift/EditorView.swift
new file mode 100644
index 0000000..74141e2
--- /dev/null
+++ b/Source/Swift/EditorView.swift
@@ -0,0 +1,16 @@
+import SwiftUI
+
+struct EditorView: View {
+ @StateObject private var store = HostsDataStore()
+
+ var body: some View {
+ NavigationSplitView {
+ SidebarView(store: store)
+ .navigationSplitViewColumnWidth(min: 140, ideal: 160, max: 300)
+ } detail: {
+ ContentView(store: store)
+ }
+ .toolbar { EditorToolbar(store: store) }
+ .safeAreaInset(edge: .bottom) { StatusBarView(store: store) }
+ }
+}
diff --git a/Source/Swift/EditorWindowPresenter.swift b/Source/Swift/EditorWindowPresenter.swift
new file mode 100644
index 0000000..93a3fda
--- /dev/null
+++ b/Source/Swift/EditorWindowPresenter.swift
@@ -0,0 +1,44 @@
+import Cocoa
+import SwiftUI
+
+@objc final class EditorWindowPresenter: NSObject, NSWindowDelegate {
+
+ private static var instance: EditorWindowPresenter?
+
+ private let window: NSWindow
+
+ private init(window: NSWindow) {
+ self.window = window
+ super.init()
+ window.delegate = self
+ }
+
+ @objc static func createEditorWindow() -> NSWindow {
+ let editorView = EditorView()
+ let hostingController = NSHostingController(rootView: editorView)
+
+ let window = NSWindow(contentViewController: hostingController)
+ window.title = "Gas Mask"
+ window.styleMask = [.titled, .closable, .miniaturizable, .resizable]
+ window.setContentSize(NSSize(width: 619, height: 479))
+ window.minSize = NSSize(width: 400, height: 400)
+ window.isReleasedWhenClosed = false
+ window.setFrameAutosaveName("editor_window")
+
+ let presenter = EditorWindowPresenter(window: window)
+ instance = presenter
+
+ return window
+ }
+
+ // MARK: - NSWindowDelegate
+
+ func windowDidBecomeMain(_ notification: Notification) {
+ Preferences.setShowEditorWindow(true)
+ }
+
+ func windowShouldClose(_ sender: NSWindow) -> Bool {
+ Preferences.setShowEditorWindow(false)
+ return true
+ }
+}
diff --git a/Source/Swift/GasMask-Bridging-Header.h b/Source/Swift/GasMask-Bridging-Header.h
index fbb3927..957f874 100644
--- a/Source/Swift/GasMask-Bridging-Header.h
+++ b/Source/Swift/GasMask-Bridging-Header.h
@@ -11,7 +11,6 @@
#import "Error.h"
#import "LocalHostsController.h"
#import "CombinedHostsController.h"
-#import "ListController.h"
#import "HostsTextView.h"
#import "Preferences+Remote.h"
#import "LoginItem.h"
diff --git a/Source/Swift/HostsDataStore.swift b/Source/Swift/HostsDataStore.swift
index 639a070..ea45e86 100644
--- a/Source/Swift/HostsDataStore.swift
+++ b/Source/Swift/HostsDataStore.swift
@@ -15,14 +15,14 @@ extension NSNotification.Name {
static let hostsFileShouldBeSelected = NSNotification.Name("HostsFileShouldBeSelectedNotification")
static let synchronizingStatusChanged = NSNotification.Name("SynchronizingStatusChangedNotification")
static let allHostsFilesLoadedFromDisk = NSNotification.Name("AllHostsFilesLoadedFromDiskNotification")
+ static let threadBusy = NSNotification.Name("ThreadBusyNotification")
+ static let threadNotBusy = NSNotification.Name("ThreadNotBusyNotification")
}
// MARK: - HostsDataStore
final class HostsDataStore: ObservableObject {
- static let shared = HostsDataStore()
-
// MARK: Published Properties
@Published var hostsGroups: [HostsGroup] = []
@@ -37,20 +37,28 @@ final class HostsDataStore: ObservableObject {
@Published var filesCount: Int = 0
@Published var canRemoveFiles: Bool = false
@Published var renamingHosts: Hosts?
+ @Published var isBusy: Bool = false
// MARK: Private
private var notificationObservers: [NSObjectProtocol] = []
private var isSyncingSelection = false
+ private var busyCount = 0
// MARK: Init
- private init() {
+ init() {
refreshGroups()
refreshFilesCount()
observeNotifications()
}
+ deinit {
+ for observer in notificationObservers {
+ NotificationCenter.default.removeObserver(observer)
+ }
+ }
+
// MARK: Refresh
func refreshGroups() {
@@ -118,6 +126,8 @@ final class HostsDataStore: ObservableObject {
for name in rowRefreshNames {
let observer = nc.addObserver(forName: name, object: nil, queue: .main) { [weak self] _ in
guard let self else { return }
+ // Re-assign to trigger @Published willSet — HostsGroup objects are reference types,
+ // so SwiftUI won't detect their property changes without this.
self.hostsGroups = self.hostsGroups
}
notificationObservers.append(observer)
@@ -139,6 +149,29 @@ final class HostsDataStore: ObservableObject {
}
}
notificationObservers.append(selectObserver)
+
+ // Busy state notifications — posted from background threads, so use queue: .main
+ let busyObserver = nc.addObserver(
+ forName: .threadBusy, object: nil, queue: .main
+ ) { [weak self] _ in
+ guard let self else { return }
+ self.busyCount += 1
+ self.isBusy = true
+ }
+ notificationObservers.append(busyObserver)
+
+ let notBusyObserver = nc.addObserver(
+ forName: .threadNotBusy, object: nil, queue: .main
+ ) { [weak self] _ in
+ guard let self else { return }
+ if self.busyCount > 0 {
+ self.busyCount -= 1
+ }
+ if self.busyCount == 0 {
+ self.isBusy = false
+ }
+ }
+ notificationObservers.append(notBusyObserver)
}
}
diff --git a/Source/Swift/SidebarInstaller.swift b/Source/Swift/SidebarInstaller.swift
deleted file mode 100644
index 07d5725..0000000
--- a/Source/Swift/SidebarInstaller.swift
+++ /dev/null
@@ -1,18 +0,0 @@
-import SwiftUI
-
-@objc final class SidebarInstaller: NSObject {
- @objc static func install(in splitView: NSSplitView) {
- let store = HostsDataStore.shared
- let sidebar = SidebarView(store: store)
- let hostingView = NSHostingView(rootView: sidebar)
-
- guard !splitView.subviews.isEmpty else { return }
- let leftPane = splitView.subviews[0]
- hostingView.frame = leftPane.frame
- hostingView.autoresizingMask = [.width, .height]
- splitView.replaceSubview(leftPane, with: hostingView)
-
- // Deactivate the old ListController to prevent duplicate notification handling
- ListController.defaultInstance()?.deactivate()
- }
-}
diff --git a/Source/Swift/StatusBarView.swift b/Source/Swift/StatusBarView.swift
new file mode 100644
index 0000000..0e660e6
--- /dev/null
+++ b/Source/Swift/StatusBarView.swift
@@ -0,0 +1,44 @@
+import SwiftUI
+
+struct StatusBarView: View {
+ @ObservedObject var store: HostsDataStore
+
+ var body: some View {
+ VStack(spacing: 0) {
+ Divider()
+ HStack {
+ if store.selectedHosts?.editable == false {
+ Image(systemName: "lock.fill")
+ .font(.system(size: 10))
+ .foregroundStyle(.secondary)
+ .help("Hosts file can not be modified")
+ .accessibilityLabel("Read-only")
+ }
+
+ Spacer()
+
+ Text(filesCountText)
+ .font(.system(size: NSFont.smallSystemFontSize))
+ .foregroundStyle(.secondary)
+
+ Spacer()
+
+ if store.isBusy {
+ ProgressView()
+ .controlSize(.small)
+ .accessibilityLabel("Busy")
+ }
+ }
+ .padding(.horizontal, 8)
+ .padding(.vertical, 3)
+ }
+ }
+
+ private var filesCountText: String {
+ switch store.filesCount {
+ case 0: return "No files"
+ case 1: return "One file"
+ default: return "\(store.filesCount) files"
+ }
+ }
+}
diff --git a/Source/SyncingArrowsBadge.h b/Source/SyncingArrowsBadge.h
deleted file mode 100644
index 143eb07..0000000
--- a/Source/SyncingArrowsBadge.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "Badge.h"
-
-@interface SyncingArrowsBadge : Badge {
- @private
- NSArray *images;
- NSTimer *timer;
- int index;
-}
-
-- (void)start;
-
-@end
diff --git a/Source/SyncingArrowsBadge.m b/Source/SyncingArrowsBadge.m
deleted file mode 100644
index e6c9fcd..0000000
--- a/Source/SyncingArrowsBadge.m
+++ /dev/null
@@ -1,58 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2009-2010 by Clockwise *
- * copyright@clockwise.ee *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#import "SyncingArrowsBadge.h"
-
-
-@implementation SyncingArrowsBadge
-
-- (id)init
-{
- self = [super init];
-
- images = [[NSArray alloc] initWithObjects:
- [NSImage imageNamed: @"Syncing_arrows1.png"],
- [NSImage imageNamed: @"Syncing_arrows2.png"],
- [NSImage imageNamed: @"Syncing_arrows3.png"],
- [NSImage imageNamed: @"Syncing_arrows4.png"],
- [NSImage imageNamed: @"Syncing_arrows5.png"],
- [NSImage imageNamed: @"Syncing_arrows6.png"],
- nil];
-
- return self;
-}
-
-- (void)start
-{
- timer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval).09 target:self selector:@selector(updateImage) userInfo:nil repeats:YES];
-}
-
-- (void)updateImage
-{
- if (index < 5) {
- index++;
- }
- else {
- index = 0;
- }
- [self setActiveIcon:[images objectAtIndex:index]];
-}
-
-@end
diff --git a/Tests/GasMaskTests/ApplicationControllerTests.m b/Tests/GasMaskTests/ApplicationControllerTests.m
index 90b5953..7cf1858 100644
--- a/Tests/GasMaskTests/ApplicationControllerTests.m
+++ b/Tests/GasMaskTests/ApplicationControllerTests.m
@@ -3,24 +3,25 @@
#import "ApplicationController.h"
@interface ApplicationController (Testing)
-- (void)loadEditorNibForTesting;
+- (void)loadEditorWindowForTesting;
- (void)closeEditorWindowForTesting;
- (NSWindow *)editorWindowForTesting;
@end
@implementation ApplicationController (Testing)
-- (void)loadEditorNibForTesting
+- (void)loadEditorWindowForTesting
{
- id objects = [self valueForKey:@"_editorNibTopLevelObjects"];
- if (objects) {
+ NSWindow *existing = [self editorWindowForTesting];
+ if (existing) {
[self setValue:@YES forKey:@"editorWindowOpened"];
return;
}
- NSArray *topLevelObjects = nil;
- [[NSBundle mainBundle] loadNibNamed:@"Editor" owner:self topLevelObjects:&topLevelObjects];
- [self setValue:topLevelObjects forKey:@"_editorNibTopLevelObjects"];
- [self setValue:@YES forKey:@"editorWindowOpened"];
+ // Call the private initEditorWindow method which uses EditorWindowPresenter internally
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ [self performSelector:NSSelectorFromString(@"initEditorWindow")];
+#pragma clang diagnostic pop
}
- (void)closeEditorWindowForTesting
@@ -87,26 +88,26 @@ - (void)testSingletonExists
XCTAssertEqual([ApplicationController defaultInstance], self.controller);
}
-#pragma mark - NIB loading / open
+#pragma mark - Window creation / open
-- (void)testLoadEditorNib_setsEditorWindowOpenedFlag
+- (void)testLoadEditorWindow_setsEditorWindowOpenedFlag
{
XCTAssertFalse([self.controller editorWindowOpened], @"precondition");
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
XCTAssertTrue([self.controller editorWindowOpened]);
}
-- (void)testLoadEditorNib_windowExistsAfterOpen
+- (void)testLoadEditorWindow_windowExistsAfterOpen
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
NSWindow *w = [self.controller editorWindowForTesting];
XCTAssertNotNil(w);
XCTAssertEqualObjects([w frameAutosaveName], @"editor_window");
}
-- (void)testLoadEditorNib_windowAppearsInNSAppWindows
+- (void)testLoadEditorWindow_windowAppearsInNSAppWindows
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
NSWindow *found = nil;
for (NSWindow *w in [NSApp windows]) {
@@ -122,7 +123,7 @@ - (void)testLoadEditorNib_windowAppearsInNSAppWindows
- (void)testCloseEditorWindow_clearsEditorWindowOpenedFlag
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
XCTAssertTrue([self.controller editorWindowOpened], @"precondition");
[self.controller closeEditorWindowForTesting];
XCTAssertFalse([self.controller editorWindowOpened]);
@@ -130,7 +131,7 @@ - (void)testCloseEditorWindow_clearsEditorWindowOpenedFlag
- (void)testCloseEditorWindow_windowStillAccessibleAfterClose
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
[self.controller closeEditorWindowForTesting];
runLoopDrain(0.05);
@@ -142,22 +143,22 @@ - (void)testCloseEditorWindow_windowStillAccessibleAfterClose
- (void)testReopenAfterClose_flagIsYes
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
[self.controller closeEditorWindowForTesting];
runLoopDrain(0.05);
XCTAssertFalse([self.controller editorWindowOpened], @"precondition: closed");
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
XCTAssertTrue([self.controller editorWindowOpened]);
}
- (void)testReopenAfterClose_windowAccessible
{
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
[self.controller closeEditorWindowForTesting];
runLoopDrain(0.05);
- [self.controller loadEditorNibForTesting];
+ [self.controller loadEditorWindowForTesting];
XCTAssertNotNil([self.controller editorWindowForTesting]);
}
diff --git a/Tests/GasMaskTests/EditorWindowPresenterTests.swift b/Tests/GasMaskTests/EditorWindowPresenterTests.swift
new file mode 100644
index 0000000..ff3fee0
--- /dev/null
+++ b/Tests/GasMaskTests/EditorWindowPresenterTests.swift
@@ -0,0 +1,54 @@
+import XCTest
+@testable import Gas_Mask
+
+final class EditorWindowPresenterTests: XCTestCase {
+
+ private var window: NSWindow!
+
+ override func setUp() {
+ super.setUp()
+ window = EditorWindowPresenter.createEditorWindow()
+ }
+
+ override func tearDown() {
+ window.orderOut(nil)
+ window = nil
+ super.tearDown()
+ }
+
+ func testWindowTitle() {
+ XCTAssertEqual(window.title, "Gas Mask")
+ }
+
+ func testFrameAutosaveName() {
+ XCTAssertEqual(window.frameAutosaveName, "editor_window")
+ }
+
+ func testMinSize() {
+ // Width should match the configured minimum.
+ // Height may be larger than 400 due to SwiftUI content minimum sizing.
+ XCTAssertEqual(window.minSize.width, 400)
+ XCTAssertGreaterThanOrEqual(window.minSize.height, 400)
+ }
+
+ func testStyleMask_containsExpectedOptions() {
+ let mask = window.styleMask
+ XCTAssertTrue(mask.contains(.titled))
+ XCTAssertTrue(mask.contains(.closable))
+ XCTAssertTrue(mask.contains(.miniaturizable))
+ XCTAssertTrue(mask.contains(.resizable))
+ }
+
+ func testContentViewController_exists() {
+ XCTAssertNotNil(window.contentViewController)
+ }
+
+ func testWindowDelegate_exists() {
+ XCTAssertNotNil(window.delegate)
+ }
+
+ func testWindowShouldClose_returnsTrue() {
+ let result = window.delegate?.windowShouldClose?(window) ?? false
+ XCTAssertTrue(result)
+ }
+}
diff --git a/Tests/GasMaskTests/HostsDataStoreTests.swift b/Tests/GasMaskTests/HostsDataStoreTests.swift
index 9020831..b52e61c 100644
--- a/Tests/GasMaskTests/HostsDataStoreTests.swift
+++ b/Tests/GasMaskTests/HostsDataStoreTests.swift
@@ -18,19 +18,18 @@ final class HostsDataStoreTests: XCTestCase {
XCTAssertEqual(NSNotification.Name.allHostsFilesLoadedFromDisk.rawValue, "AllHostsFilesLoadedFromDiskNotification")
}
- // MARK: - Singleton
+ // MARK: - Instance Creation
- func testShared_returnsSameInstance() {
- let a = HostsDataStore.shared
- let b = HostsDataStore.shared
- XCTAssertTrue(a === b)
+ func testInit_returnsDistinctInstances() {
+ let a = HostsDataStore()
+ let b = HostsDataStore()
+ XCTAssertFalse(a === b)
}
// MARK: - Notification Response
func testRenameNotification_setsRenamingHosts() {
- let store = HostsDataStore.shared
- addTeardownBlock { store.renamingHosts = nil }
+ let store = HostsDataStore()
let hosts = Hosts(path: "/tmp/test.hst")!
store.renamingHosts = nil
@@ -42,8 +41,7 @@ final class HostsDataStoreTests: XCTestCase {
}
func testSelectNotification_updatesSelectedHosts() {
- let store = HostsDataStore.shared
- addTeardownBlock { store.selectedHosts = nil }
+ let store = HostsDataStore()
let hosts = Hosts(path: "/tmp/test.hst")!
store.selectedHosts = nil
@@ -53,4 +51,29 @@ final class HostsDataStoreTests: XCTestCase {
XCTAssertTrue(store.selectedHosts === hosts)
}
+
+ // MARK: - Busy State
+
+ func testBusyNotification_setsIsBusy() {
+ let store = HostsDataStore()
+ XCTAssertFalse(store.isBusy, "precondition")
+
+ NotificationCenter.default.post(name: .threadBusy, object: nil)
+ RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
+
+ XCTAssertTrue(store.isBusy)
+ }
+
+ func testNotBusyNotification_clearsIsBusy() {
+ let store = HostsDataStore()
+
+ NotificationCenter.default.post(name: .threadBusy, object: nil)
+ RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
+ XCTAssertTrue(store.isBusy, "precondition")
+
+ NotificationCenter.default.post(name: .threadNotBusy, object: nil)
+ RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
+
+ XCTAssertFalse(store.isBusy)
+ }
}