├── .github └── FUNDING.yml ├── .gitignore ├── .gitmodules ├── HexFiendFramework ├── HexFiend.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── include │ └── HexFiend │ │ ├── HFAnnotatedTree.h │ │ ├── HFAssert.h │ │ ├── HFAttributedByteArray.h │ │ ├── HFBTree.h │ │ ├── HFBTreeByteArray.h │ │ ├── HFBinaryGlyphTable.h │ │ ├── HFBinaryTextRepresenter.h │ │ ├── HFByteArray.h │ │ ├── HFByteArrayEditScript.h │ │ ├── HFByteArrayProxiedData.h │ │ ├── HFByteArray_Internal.h │ │ ├── HFByteRangeAttribute.h │ │ ├── HFByteRangeAttributeArray.h │ │ ├── HFByteSlice.h │ │ ├── HFByteSliceFileOperation.h │ │ ├── HFByteSliceFileOperationQueueEntry.h │ │ ├── HFByteSlice_Private.h │ │ ├── HFByteTheme.h │ │ ├── HFByteThemeColor.h │ │ ├── HFCancelButton.h │ │ ├── HFColorRange.h │ │ ├── HFColumnRepresenter.h │ │ ├── HFColumnView.h │ │ ├── HFController.h │ │ ├── HFControllerCoalescedUndo.h │ │ ├── HFCustomEncoding.h │ │ ├── HFEncodingManager.h │ │ ├── HFFastMemchr.h │ │ ├── HFFileByteSlice.h │ │ ├── HFFileReference.h │ │ ├── HFFrameworkPrefix.h │ │ ├── HFFullMemoryByteArray.h │ │ ├── HFFullMemoryByteSlice.h │ │ ├── HFFunctions.h │ │ ├── HFGlyphTrie.h │ │ ├── HFHelperProcessSharedCode.h │ │ ├── HFHexGlyphTable.h │ │ ├── HFHexPasteboardOwner.h │ │ ├── HFHexTextRepresenter.h │ │ ├── HFLayoutRepresenter.h │ │ ├── HFLineCountingRepresenter.h │ │ ├── HFLineCountingView.h │ │ ├── HFNSStringEncoding.h │ │ ├── HFObjectGraph.h │ │ ├── HFPasteboardOwner.h │ │ ├── HFProgressTracker.h │ │ ├── HFRandomDataByteSlice.h │ │ ├── HFRepresenter.h │ │ ├── HFRepresenterBinaryTextView.h │ │ ├── HFRepresenterHexTextView.h │ │ ├── HFRepresenterStringEncodingTextView.h │ │ ├── HFRepresenterTextView.h │ │ ├── HFRepresenterTextViewCallout.h │ │ ├── HFRepresenter_Internal.h │ │ ├── HFSharedMemoryByteSlice.h │ │ ├── HFStatusBarRepresenter.h │ │ ├── HFStringEncoding.h │ │ ├── HFStringEncodingTextRepresenter.h │ │ ├── HFTest.h │ │ ├── HFTextField.h │ │ ├── HFTextRepresenter.h │ │ ├── HFTextRepresenter_Internal.h │ │ ├── HFTextSelectionPulseView.h │ │ ├── HFTextView.h │ │ ├── HFTextVisualStyleRun.h │ │ ├── HFTypes.h │ │ ├── HFUIUtils.h │ │ ├── HFVerticalScrollerRepresenter.h │ │ ├── HexFiend-Swift.h │ │ └── HexFiend.h └── src │ ├── HFAnnotatedTree.h │ ├── HFAnnotatedTree.m │ ├── HFAssert.h │ ├── HFAttributedByteArray.h │ ├── HFAttributedByteArray.m │ ├── HFBTree.h │ ├── HFBTree.m │ ├── HFBTreeByteArray.h │ ├── HFBTreeByteArray.m │ ├── HFBinaryGlyphTable.h │ ├── HFBinaryGlyphTable.m │ ├── HFBinaryTextRepresenter.h │ ├── HFBinaryTextRepresenter.m │ ├── HFByteArray.h │ ├── HFByteArray.m │ ├── HFByteArrayEditScript.h │ ├── HFByteArrayEditScript.m │ ├── HFByteArrayProxiedData.h │ ├── HFByteArrayProxiedData.m │ ├── HFByteArray_FileWriting.m │ ├── HFByteArray_FindReplace.m │ ├── HFByteArray_Internal.h │ ├── HFByteRangeAttribute.h │ ├── HFByteRangeAttribute.m │ ├── HFByteRangeAttributeArray.h │ ├── HFByteRangeAttributeArray.m │ ├── HFByteSlice.h │ ├── HFByteSlice.m │ ├── HFByteSliceFileOperation.h │ ├── HFByteSliceFileOperation.m │ ├── HFByteSliceFileOperationQueueEntry.h │ ├── HFByteSliceFileOperationQueueEntry.m │ ├── HFByteSlice_Private.h │ ├── HFByteTheme.h │ ├── HFByteTheme.m │ ├── HFByteThemeColor.h │ ├── HFCancelButton.h │ ├── HFCancelButton.m │ ├── HFColorRange.h │ ├── HFColorRange.m │ ├── HFColumnRepresenter.h │ ├── HFColumnRepresenter.m │ ├── HFColumnView.h │ ├── HFColumnView.m │ ├── HFController.h │ ├── HFController.m │ ├── HFControllerCoalescedUndo.h │ ├── HFControllerCoalescedUndo.m │ ├── HFCustomEncoding.h │ ├── HFCustomEncoding.m │ ├── HFEncodingManager.h │ ├── HFEncodingManager.m │ ├── HFFastMemchr.h │ ├── HFFastMemchr.m │ ├── HFFileByteSlice.h │ ├── HFFileByteSlice.m │ ├── HFFileReference.h │ ├── HFFileReference.m │ ├── HFFrameworkPrefix.h │ ├── HFFullMemoryByteArray.h │ ├── HFFullMemoryByteArray.m │ ├── HFFullMemoryByteSlice.h │ ├── HFFullMemoryByteSlice.m │ ├── HFFunctions.h │ ├── HFFunctions.m │ ├── HFGlyphTrie.h │ ├── HFGlyphTrie.m │ ├── HFHelperProcessSharedCode.h │ ├── HFHexGlyphTable.h │ ├── HFHexGlyphTable.m │ ├── HFHexPasteboardOwner.h │ ├── HFHexPasteboardOwner.m │ ├── HFHexTextRepresenter.h │ ├── HFHexTextRepresenter.m │ ├── HFLayoutRepresenter.h │ ├── HFLayoutRepresenter.m │ ├── HFLineCountingRepresenter.h │ ├── HFLineCountingRepresenter.m │ ├── HFLineCountingView.h │ ├── HFLineCountingView.m │ ├── HFNSStringEncoding.h │ ├── HFNSStringEncoding.m │ ├── HFObjectGraph.h │ ├── HFObjectGraph.m │ ├── HFPasteboardOwner.h │ ├── HFPasteboardOwner.m │ ├── HFProgressTracker.h │ ├── HFProgressTracker.m │ ├── HFRandomDataByteSlice.h │ ├── HFRandomDataByteSlice.m │ ├── HFRepresenter.h │ ├── HFRepresenter.m │ ├── HFRepresenterBinaryTextView.h │ ├── HFRepresenterBinaryTextView.m │ ├── HFRepresenterHexTextView.h │ ├── HFRepresenterHexTextView.m │ ├── HFRepresenterStringEncodingTextView.h │ ├── HFRepresenterStringEncodingTextView.m │ ├── HFRepresenterTextView.h │ ├── HFRepresenterTextView.m │ ├── HFRepresenterTextViewCallout.h │ ├── HFRepresenterTextViewCallout.m │ ├── HFRepresenter_Internal.h │ ├── HFSharedMemoryByteSlice.h │ ├── HFSharedMemoryByteSlice.m │ ├── HFStatusBarRepresenter.h │ ├── HFStatusBarRepresenter.m │ ├── HFStringEncoding.h │ ├── HFStringEncoding.m │ ├── HFStringEncodingTextRepresenter.h │ ├── HFStringEncodingTextRepresenter.m │ ├── HFTest.h │ ├── HFTextField.h │ ├── HFTextField.m │ ├── HFTextRepresenter.h │ ├── HFTextRepresenter.m │ ├── HFTextRepresenter_Internal.h │ ├── HFTextRepresenter_KeyBinding.m │ ├── HFTextSelectionPulseView.h │ ├── HFTextSelectionPulseView.m │ ├── HFTextView.h │ ├── HFTextView.m │ ├── HFTextVisualStyleRun.h │ ├── HFTextVisualStyleRun.m │ ├── HFTypes.h │ ├── HFUIUtils.h │ ├── HFUIUtils.m │ ├── HFVerticalScrollerRepresenter.h │ ├── HFVerticalScrollerRepresenter.m │ ├── HexFiend-Swift.h │ └── HexFiend.h ├── HexFiendShims ├── include │ ├── HFByteTheme.h │ └── HexFiend-Swift.h └── src │ └── HFByteTheme.m ├── LICENSE ├── LNPropertyListEditor ├── LNPropertyListEditor.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── LNPropertyListEditor.xcscheme ├── LNPropertyListEditor │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── minus.imageset │ │ │ ├── Contents.json │ │ │ └── minus.pdf │ │ └── plus.imageset │ │ │ ├── Contents.json │ │ │ └── plus.pdf │ ├── Implementation │ │ ├── LNPropertyListCellTextField.h │ │ ├── LNPropertyListCellTextField.m │ │ ├── LNPropertyListCellView.h │ │ ├── LNPropertyListCellView.m │ │ ├── LNPropertyListDataEditorPanel.h │ │ ├── LNPropertyListDataEditorPanel.m │ │ ├── LNPropertyListDatePicker.h │ │ ├── LNPropertyListDatePicker.m │ │ ├── LNPropertyListDatePickerCell.h │ │ ├── LNPropertyListDatePickerCell.mm │ │ ├── LNPropertyListDatePickerPanel.h │ │ ├── LNPropertyListDatePickerPanel.m │ │ ├── LNPropertyListEditor-Private.h │ │ ├── LNPropertyListEditor.m │ │ ├── LNPropertyListEditorOutline.xib │ │ ├── LNPropertyListNode-Private.h │ │ ├── LNPropertyListNode.m │ │ ├── LNPropertyListOutlineView.h │ │ ├── LNPropertyListOutlineView.m │ │ ├── LNPropertyListPopUpButtonCell.h │ │ ├── LNPropertyListPopUpButtonCell.m │ │ ├── LNPropertyListRowView.h │ │ ├── LNPropertyListRowView.m │ │ ├── NSObject+LNPropertyListValueSorting.h │ │ ├── NSObject+LNPropertyListValueSorting.m │ │ ├── _LNPropertyListDatePicker.h │ │ └── _LNPropertyListDatePicker.m │ ├── Info.plist │ ├── LNPropertyListEditor.h │ └── LNPropertyListNode.h └── include │ └── LNPropertyListEditor │ ├── LNPropertyListEditor.h │ └── LNPropertyListNode.h ├── LNPropertyListEditorExample ├── LNPropertyListEditorExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── LNPropertyListEditorExample.xcscheme └── LNPropertyListEditorExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── Package.swift ├── README.md ├── Supplements ├── Screenshot_1_Dark.png └── Screenshot_2_Dark.png ├── prepare_spm_support.rb └── releaseVersion.sh /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: LeoNatan 2 | custom: ['paypal.me/LeoNatan25'] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | /_tmp_release_notes.md 65 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "HexFiend"] 2 | path = HexFiend 3 | url = https://github.com/HexFiend/HexFiend.git 4 | -------------------------------------------------------------------------------- /HexFiendFramework/HexFiend.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HexFiendFramework/HexFiend.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFAnnotatedTree.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFAnnotatedTree.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFAssert.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFAssert.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFAttributedByteArray.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFAttributedByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFBTree.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/BTree/HFBTree.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFBTreeByteArray.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFBTreeByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFBinaryGlyphTable.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFBinaryGlyphTable.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFBinaryTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFBinaryTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteArray.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteArrayEditScript.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteArrayEditScript.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteArrayProxiedData.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteArrayProxiedData.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteArray_Internal.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteArray_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteRangeAttribute.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteRangeAttribute.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteRangeAttributeArray.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteRangeAttributeArray.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteSliceFileOperation.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteSliceFileOperation.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteSliceFileOperationQueueEntry.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteSliceFileOperationQueueEntry.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteSlice_Private.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteSlice_Private.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteTheme.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiendShims/include/HFByteTheme.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFByteThemeColor.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFByteThemeColor.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFCancelButton.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFCancelButton.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFColorRange.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFColorRange.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFColumnRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFColumnRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFColumnView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFColumnView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFController.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFController.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFControllerCoalescedUndo.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFControllerCoalescedUndo.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFCustomEncoding.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFCustomEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFEncodingManager.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFEncodingManager.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFastMemchr.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFastMemchr.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFileByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFileByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFileReference.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFileReference.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFrameworkPrefix.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFrameworkPrefix.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFullMemoryByteArray.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFullMemoryByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFullMemoryByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFullMemoryByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFFunctions.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFFunctions.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFGlyphTrie.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFGlyphTrie.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFHelperProcessSharedCode.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFHelperProcessSharedCode.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFHexGlyphTable.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFHexGlyphTable.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFHexPasteboardOwner.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFHexPasteboardOwner.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFHexTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFHexTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFLayoutRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFLayoutRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFLineCountingRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFLineCountingRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFLineCountingView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFLineCountingView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFNSStringEncoding.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFNSStringEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFObjectGraph.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFObjectGraph.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFPasteboardOwner.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFPasteboardOwner.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFProgressTracker.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFProgressTracker.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRandomDataByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRandomDataByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenterBinaryTextView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenterBinaryTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenterHexTextView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenterHexTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenterStringEncodingTextView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenterStringEncodingTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenterTextView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenterTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenterTextViewCallout.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenterTextViewCallout.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFRepresenter_Internal.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFRepresenter_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFSharedMemoryByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFSharedMemoryByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFStatusBarRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFStatusBarRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFStringEncoding.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFStringEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFStringEncodingTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFStringEncodingTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTest.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/tests/HFTest.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextField.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextField.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextRepresenter_Internal.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextRepresenter_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextSelectionPulseView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextSelectionPulseView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextView.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTextVisualStyleRun.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTextVisualStyleRun.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFTypes.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFTypes.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFUIUtils.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFUIUtils.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HFVerticalScrollerRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HFVerticalScrollerRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HexFiend-Swift.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiendShims/include/HexFiend-Swift.h -------------------------------------------------------------------------------- /HexFiendFramework/include/HexFiend/HexFiend.h: -------------------------------------------------------------------------------- 1 | ../../../HexFiend/framework/sources/HexFiend.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFAnnotatedTree.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFAnnotatedTree.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFAnnotatedTree.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFAnnotatedTree.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFAssert.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFAssert.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFAttributedByteArray.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFAttributedByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFAttributedByteArray.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFAttributedByteArray.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBTree.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/BTree/HFBTree.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBTree.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/BTree/HFBTree.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBTreeByteArray.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBTreeByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBTreeByteArray.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBTreeByteArray.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBinaryGlyphTable.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBinaryGlyphTable.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBinaryGlyphTable.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBinaryGlyphTable.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBinaryTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBinaryTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFBinaryTextRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFBinaryTextRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArray.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArray.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArray.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArrayEditScript.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArrayEditScript.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArrayEditScript.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArrayEditScript.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArrayProxiedData.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArrayProxiedData.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArrayProxiedData.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArrayProxiedData.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArray_FileWriting.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArray_FileWriting.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArray_FindReplace.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArray_FindReplace.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteArray_Internal.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteArray_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteRangeAttribute.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteRangeAttribute.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteRangeAttribute.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteRangeAttribute.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteRangeAttributeArray.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteRangeAttributeArray.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteRangeAttributeArray.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteRangeAttributeArray.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSlice.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSlice.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSliceFileOperation.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSliceFileOperation.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSliceFileOperation.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSliceFileOperation.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSliceFileOperationQueueEntry.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSliceFileOperationQueueEntry.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSliceFileOperationQueueEntry.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSliceFileOperationQueueEntry.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteSlice_Private.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteSlice_Private.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteTheme.h: -------------------------------------------------------------------------------- 1 | ../../HexFiendShims/include/HFByteTheme.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteTheme.m: -------------------------------------------------------------------------------- 1 | ../../HexFiendShims/src/HFByteTheme.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFByteThemeColor.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFByteThemeColor.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFCancelButton.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFCancelButton.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFCancelButton.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFCancelButton.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColorRange.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColorRange.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColorRange.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColorRange.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColumnRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColumnRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColumnRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColumnRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColumnView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColumnView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFColumnView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFColumnView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFController.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFController.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFController.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFController.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFControllerCoalescedUndo.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFControllerCoalescedUndo.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFControllerCoalescedUndo.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFControllerCoalescedUndo.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFCustomEncoding.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFCustomEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFCustomEncoding.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFCustomEncoding.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFEncodingManager.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFEncodingManager.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFEncodingManager.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFEncodingManager.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFastMemchr.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFastMemchr.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFastMemchr.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFastMemchr.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFileByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFileByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFileByteSlice.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFileByteSlice.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFileReference.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFileReference.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFileReference.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFileReference.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFrameworkPrefix.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFrameworkPrefix.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFullMemoryByteArray.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFullMemoryByteArray.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFullMemoryByteArray.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFullMemoryByteArray.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFullMemoryByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFullMemoryByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFullMemoryByteSlice.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFullMemoryByteSlice.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFunctions.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFunctions.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFFunctions.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFFunctions.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFGlyphTrie.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFGlyphTrie.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFGlyphTrie.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFGlyphTrie.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHelperProcessSharedCode.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHelperProcessSharedCode.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexGlyphTable.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexGlyphTable.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexGlyphTable.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexGlyphTable.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexPasteboardOwner.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexPasteboardOwner.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexPasteboardOwner.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexPasteboardOwner.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFHexTextRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFHexTextRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLayoutRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLayoutRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLayoutRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLayoutRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLineCountingRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLineCountingRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLineCountingRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLineCountingRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLineCountingView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLineCountingView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFLineCountingView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFLineCountingView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFNSStringEncoding.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFNSStringEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFNSStringEncoding.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFNSStringEncoding.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFObjectGraph.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFObjectGraph.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFObjectGraph.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFObjectGraph.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFPasteboardOwner.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFPasteboardOwner.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFPasteboardOwner.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFPasteboardOwner.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFProgressTracker.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFProgressTracker.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFProgressTracker.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFProgressTracker.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRandomDataByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRandomDataByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRandomDataByteSlice.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRandomDataByteSlice.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterBinaryTextView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterBinaryTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterBinaryTextView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterBinaryTextView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterHexTextView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterHexTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterHexTextView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterHexTextView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterStringEncodingTextView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterStringEncodingTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterStringEncodingTextView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterStringEncodingTextView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterTextView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterTextView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterTextView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterTextViewCallout.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterTextViewCallout.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenterTextViewCallout.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenterTextViewCallout.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFRepresenter_Internal.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFRepresenter_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFSharedMemoryByteSlice.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFSharedMemoryByteSlice.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFSharedMemoryByteSlice.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFSharedMemoryByteSlice.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStatusBarRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStatusBarRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStatusBarRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStatusBarRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStringEncoding.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStringEncoding.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStringEncoding.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStringEncoding.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStringEncodingTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStringEncodingTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFStringEncodingTextRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFStringEncodingTextRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTest.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/tests/HFTest.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextField.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextField.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextField.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextField.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextRepresenter_Internal.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextRepresenter_Internal.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextRepresenter_KeyBinding.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextRepresenter_KeyBinding.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextSelectionPulseView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextSelectionPulseView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextSelectionPulseView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextSelectionPulseView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextView.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextView.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextView.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextView.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextVisualStyleRun.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextVisualStyleRun.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTextVisualStyleRun.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTextVisualStyleRun.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFTypes.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFTypes.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFUIUtils.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFUIUtils.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFUIUtils.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFUIUtils.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HFVerticalScrollerRepresenter.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFVerticalScrollerRepresenter.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HFVerticalScrollerRepresenter.m: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HFVerticalScrollerRepresenter.m -------------------------------------------------------------------------------- /HexFiendFramework/src/HexFiend-Swift.h: -------------------------------------------------------------------------------- 1 | ../../HexFiendShims/include/HexFiend-Swift.h -------------------------------------------------------------------------------- /HexFiendFramework/src/HexFiend.h: -------------------------------------------------------------------------------- 1 | ../../HexFiend/framework/sources/HexFiend.h -------------------------------------------------------------------------------- /HexFiendShims/include/HFByteTheme.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface HFByteTheme : NSObject 5 | 6 | @property (readonly) struct HFByteThemeColor* darkColorTable; 7 | @property (readonly) struct HFByteThemeColor* lightColorTable; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /HexFiendShims/include/HexFiend-Swift.h: -------------------------------------------------------------------------------- 1 | #import -------------------------------------------------------------------------------- /HexFiendShims/src/HFByteTheme.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @implementation HFByteTheme @end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2021 Leo Natan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 391FF02B2084060000005D0F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 391FF02A2084060000005D0F /* Assets.xcassets */; }; 11 | 391FF02F208412CC00005D0F /* LNPropertyListRowView.h in Headers */ = {isa = PBXBuildFile; fileRef = 391FF02D208412CC00005D0F /* LNPropertyListRowView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 12 | 391FF030208412CC00005D0F /* LNPropertyListRowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 391FF02E208412CC00005D0F /* LNPropertyListRowView.m */; }; 13 | 391FF0332084270400005D0F /* LNPropertyListOutlineView.h in Headers */ = {isa = PBXBuildFile; fileRef = 391FF0312084270400005D0F /* LNPropertyListOutlineView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14 | 391FF0342084270400005D0F /* LNPropertyListOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 391FF0322084270400005D0F /* LNPropertyListOutlineView.m */; }; 15 | 3925913A263C52B100AF78D3 /* LNPropertyListCellTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = 39259138263C52B100AF78D3 /* LNPropertyListCellTextField.h */; settings = {ATTRIBUTES = (Private, ); }; }; 16 | 3925913B263C52B100AF78D3 /* LNPropertyListCellTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 39259139263C52B100AF78D3 /* LNPropertyListCellTextField.m */; }; 17 | 393E1872207F61C2002E6136 /* LNPropertyListEditorOutline.xib in Resources */ = {isa = PBXBuildFile; fileRef = 393E1871207F61C2002E6136 /* LNPropertyListEditorOutline.xib */; }; 18 | 393E1875207F64A0002E6136 /* LNPropertyListEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = 393E1873207F64A0002E6136 /* LNPropertyListEditor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | 393E1876207F64A0002E6136 /* LNPropertyListEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E1874207F64A0002E6136 /* LNPropertyListEditor.m */; }; 20 | 393E1879207F68B4002E6136 /* LNPropertyListNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 393E1877207F68B4002E6136 /* LNPropertyListNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 393E187A207F68B4002E6136 /* LNPropertyListNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E1878207F68B4002E6136 /* LNPropertyListNode.m */; }; 22 | 393E1882207FAD26002E6136 /* LNPropertyListNode-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 393E1881207FAD26002E6136 /* LNPropertyListNode-Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 23 | 393E1885207FAEC6002E6136 /* LNPropertyListCellView.h in Headers */ = {isa = PBXBuildFile; fileRef = 393E1883207FAEC6002E6136 /* LNPropertyListCellView.h */; settings = {ATTRIBUTES = (Private, ); }; }; 24 | 393E1886207FAEC6002E6136 /* LNPropertyListCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E1884207FAEC6002E6136 /* LNPropertyListCellView.m */; }; 25 | 3941486F2095E85900A21F96 /* LNPropertyListDatePickerCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 3941486D2095E85900A21F96 /* LNPropertyListDatePickerCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; 26 | 394148702095E85900A21F96 /* LNPropertyListDatePickerCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */; }; 27 | 3946906C20976ED300B4A457 /* LNPropertyListDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 28 | 3946906D20976ED300B4A457 /* LNPropertyListDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */; }; 29 | 39D1276E26D9255D007E64D1 /* HexFiend.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39D1276B26D9254C007E64D1 /* HexFiend.framework */; }; 30 | 39D1276F26D9255D007E64D1 /* HexFiend.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 39D1276B26D9254C007E64D1 /* HexFiend.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 31 | 39D1528F23289668009124C8 /* LNPropertyListDatePickerPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */; settings = {ATTRIBUTES = (Private, ); }; }; 32 | 39D1529023289668009124C8 /* LNPropertyListDatePickerPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */; }; 33 | 39D152962328A9C4009124C8 /* _LNPropertyListDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 34 | 39D152972328A9C4009124C8 /* _LNPropertyListDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */; }; 35 | 39D55F2026D82C100013B105 /* LNPropertyListDataEditorPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D55F1E26D82C100013B105 /* LNPropertyListDataEditorPanel.h */; settings = {ATTRIBUTES = (Private, ); }; }; 36 | 39D55F2126D82C100013B105 /* LNPropertyListDataEditorPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D55F1F26D82C100013B105 /* LNPropertyListDataEditorPanel.m */; }; 37 | 39DE8E942092030500ED16B4 /* LNPropertyListPopUpButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 39DE8E922092030500ED16B4 /* LNPropertyListPopUpButtonCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; 38 | 39DE8E952092030500ED16B4 /* LNPropertyListPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */; }; 39 | 39DE8E9C2092214400ED16B4 /* LNPropertyListEditor-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 39DE8E9B2092214300ED16B4 /* LNPropertyListEditor-Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 40 | 39F537F3264305AF00AB263A /* NSObject+LNPropertyListValueSorting.h in Headers */ = {isa = PBXBuildFile; fileRef = 39F537F1264305AF00AB263A /* NSObject+LNPropertyListValueSorting.h */; settings = {ATTRIBUTES = (Private, ); }; }; 41 | 39F537F4264305AF00AB263A /* NSObject+LNPropertyListValueSorting.m in Sources */ = {isa = PBXBuildFile; fileRef = 39F537F2264305AF00AB263A /* NSObject+LNPropertyListValueSorting.m */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXContainerItemProxy section */ 45 | 39D1276A26D9254C007E64D1 /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = 39D1276626D9254C007E64D1 /* HexFiend.xcodeproj */; 48 | proxyType = 2; 49 | remoteGlobalIDString = 2A5473BE36E204DC14FF8C9C; 50 | remoteInfo = HexFiend; 51 | }; 52 | 39D1276C26D92552007E64D1 /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = 39D1276626D9254C007E64D1 /* HexFiend.xcodeproj */; 55 | proxyType = 1; 56 | remoteGlobalIDString = AFF1D22ED47CE0FD180F70EB; 57 | remoteInfo = HexFiend; 58 | }; 59 | /* End PBXContainerItemProxy section */ 60 | 61 | /* Begin PBXCopyFilesBuildPhase section */ 62 | 39D55F1D26D829970013B105 /* Embed Frameworks */ = { 63 | isa = PBXCopyFilesBuildPhase; 64 | buildActionMask = 2147483647; 65 | dstPath = ""; 66 | dstSubfolderSpec = 10; 67 | files = ( 68 | 39D1276F26D9255D007E64D1 /* HexFiend.framework in Embed Frameworks */, 69 | ); 70 | name = "Embed Frameworks"; 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXCopyFilesBuildPhase section */ 74 | 75 | /* Begin PBXFileReference section */ 76 | 391FF02A2084060000005D0F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 77 | 391FF02D208412CC00005D0F /* LNPropertyListRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListRowView.h; sourceTree = ""; }; 78 | 391FF02E208412CC00005D0F /* LNPropertyListRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListRowView.m; sourceTree = ""; }; 79 | 391FF0312084270400005D0F /* LNPropertyListOutlineView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListOutlineView.h; sourceTree = ""; }; 80 | 391FF0322084270400005D0F /* LNPropertyListOutlineView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListOutlineView.m; sourceTree = ""; }; 81 | 39259138263C52B100AF78D3 /* LNPropertyListCellTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListCellTextField.h; sourceTree = ""; }; 82 | 39259139263C52B100AF78D3 /* LNPropertyListCellTextField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListCellTextField.m; sourceTree = ""; }; 83 | 393E1839207F6119002E6136 /* LNPropertyListEditor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LNPropertyListEditor.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 84 | 393E183D207F6119002E6136 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 85 | 393E1871207F61C2002E6136 /* LNPropertyListEditorOutline.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LNPropertyListEditorOutline.xib; sourceTree = ""; }; 86 | 393E1873207F64A0002E6136 /* LNPropertyListEditor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListEditor.h; sourceTree = ""; }; 87 | 393E1874207F64A0002E6136 /* LNPropertyListEditor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListEditor.m; sourceTree = ""; }; 88 | 393E1877207F68B4002E6136 /* LNPropertyListNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListNode.h; sourceTree = ""; }; 89 | 393E1878207F68B4002E6136 /* LNPropertyListNode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListNode.m; sourceTree = ""; }; 90 | 393E1881207FAD26002E6136 /* LNPropertyListNode-Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LNPropertyListNode-Private.h"; sourceTree = ""; }; 91 | 393E1883207FAEC6002E6136 /* LNPropertyListCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListCellView.h; sourceTree = ""; }; 92 | 393E1884207FAEC6002E6136 /* LNPropertyListCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListCellView.m; sourceTree = ""; }; 93 | 3941486D2095E85900A21F96 /* LNPropertyListDatePickerCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDatePickerCell.h; sourceTree = ""; }; 94 | 3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LNPropertyListDatePickerCell.mm; sourceTree = ""; }; 95 | 3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDatePicker.h; sourceTree = ""; }; 96 | 3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListDatePicker.m; sourceTree = ""; }; 97 | 39D1276626D9254C007E64D1 /* HexFiend.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HexFiend.xcodeproj; path = ../HexFiendFramework/HexFiend.xcodeproj; sourceTree = ""; }; 98 | 39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDatePickerPanel.h; sourceTree = ""; }; 99 | 39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListDatePickerPanel.m; sourceTree = ""; }; 100 | 39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _LNPropertyListDatePicker.h; sourceTree = ""; }; 101 | 39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = _LNPropertyListDatePicker.m; sourceTree = ""; }; 102 | 39D55F1E26D82C100013B105 /* LNPropertyListDataEditorPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDataEditorPanel.h; sourceTree = ""; }; 103 | 39D55F1F26D82C100013B105 /* LNPropertyListDataEditorPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListDataEditorPanel.m; sourceTree = ""; }; 104 | 39DE8E922092030500ED16B4 /* LNPropertyListPopUpButtonCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListPopUpButtonCell.h; sourceTree = ""; }; 105 | 39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListPopUpButtonCell.m; sourceTree = ""; }; 106 | 39DE8E9B2092214300ED16B4 /* LNPropertyListEditor-Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LNPropertyListEditor-Private.h"; sourceTree = ""; }; 107 | 39F537F1264305AF00AB263A /* NSObject+LNPropertyListValueSorting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+LNPropertyListValueSorting.h"; sourceTree = ""; }; 108 | 39F537F2264305AF00AB263A /* NSObject+LNPropertyListValueSorting.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+LNPropertyListValueSorting.m"; sourceTree = ""; }; 109 | /* End PBXFileReference section */ 110 | 111 | /* Begin PBXFrameworksBuildPhase section */ 112 | 393E1835207F6119002E6136 /* Frameworks */ = { 113 | isa = PBXFrameworksBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | 39D1276E26D9255D007E64D1 /* HexFiend.framework in Frameworks */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXFrameworksBuildPhase section */ 121 | 122 | /* Begin PBXGroup section */ 123 | 393E182F207F6119002E6136 = { 124 | isa = PBXGroup; 125 | children = ( 126 | 39D1276626D9254C007E64D1 /* HexFiend.xcodeproj */, 127 | 393E183B207F6119002E6136 /* LNPropertyListEditor */, 128 | 393E183A207F6119002E6136 /* Products */, 129 | 39D55F1926D829600013B105 /* Frameworks */, 130 | ); 131 | sourceTree = ""; 132 | }; 133 | 393E183A207F6119002E6136 /* Products */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 393E1839207F6119002E6136 /* LNPropertyListEditor.framework */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | 393E183B207F6119002E6136 /* LNPropertyListEditor */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 391FF02A2084060000005D0F /* Assets.xcassets */, 145 | 3954022126150727005EEA38 /* Implementation */, 146 | 393E1877207F68B4002E6136 /* LNPropertyListNode.h */, 147 | 393E1873207F64A0002E6136 /* LNPropertyListEditor.h */, 148 | 393E183D207F6119002E6136 /* Info.plist */, 149 | ); 150 | path = LNPropertyListEditor; 151 | sourceTree = ""; 152 | }; 153 | 3954022126150727005EEA38 /* Implementation */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */, 157 | 39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */, 158 | 39259138263C52B100AF78D3 /* LNPropertyListCellTextField.h */, 159 | 39259139263C52B100AF78D3 /* LNPropertyListCellTextField.m */, 160 | 393E1883207FAEC6002E6136 /* LNPropertyListCellView.h */, 161 | 393E1884207FAEC6002E6136 /* LNPropertyListCellView.m */, 162 | 3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */, 163 | 3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */, 164 | 3941486D2095E85900A21F96 /* LNPropertyListDatePickerCell.h */, 165 | 3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */, 166 | 39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */, 167 | 39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */, 168 | 39DE8E9B2092214300ED16B4 /* LNPropertyListEditor-Private.h */, 169 | 393E1874207F64A0002E6136 /* LNPropertyListEditor.m */, 170 | 393E1871207F61C2002E6136 /* LNPropertyListEditorOutline.xib */, 171 | 393E1881207FAD26002E6136 /* LNPropertyListNode-Private.h */, 172 | 393E1878207F68B4002E6136 /* LNPropertyListNode.m */, 173 | 391FF0312084270400005D0F /* LNPropertyListOutlineView.h */, 174 | 391FF0322084270400005D0F /* LNPropertyListOutlineView.m */, 175 | 39DE8E922092030500ED16B4 /* LNPropertyListPopUpButtonCell.h */, 176 | 39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */, 177 | 391FF02D208412CC00005D0F /* LNPropertyListRowView.h */, 178 | 391FF02E208412CC00005D0F /* LNPropertyListRowView.m */, 179 | 39F537F1264305AF00AB263A /* NSObject+LNPropertyListValueSorting.h */, 180 | 39F537F2264305AF00AB263A /* NSObject+LNPropertyListValueSorting.m */, 181 | 39D55F1E26D82C100013B105 /* LNPropertyListDataEditorPanel.h */, 182 | 39D55F1F26D82C100013B105 /* LNPropertyListDataEditorPanel.m */, 183 | ); 184 | path = Implementation; 185 | sourceTree = ""; 186 | }; 187 | 39D1276726D9254C007E64D1 /* Products */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 39D1276B26D9254C007E64D1 /* HexFiend.framework */, 191 | ); 192 | name = Products; 193 | sourceTree = ""; 194 | }; 195 | 39D55F1926D829600013B105 /* Frameworks */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | ); 199 | name = Frameworks; 200 | sourceTree = ""; 201 | }; 202 | /* End PBXGroup section */ 203 | 204 | /* Begin PBXHeadersBuildPhase section */ 205 | 393E1836207F6119002E6136 /* Headers */ = { 206 | isa = PBXHeadersBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | 393E1882207FAD26002E6136 /* LNPropertyListNode-Private.h in Headers */, 210 | 39D1528F23289668009124C8 /* LNPropertyListDatePickerPanel.h in Headers */, 211 | 391FF0332084270400005D0F /* LNPropertyListOutlineView.h in Headers */, 212 | 391FF02F208412CC00005D0F /* LNPropertyListRowView.h in Headers */, 213 | 393E1885207FAEC6002E6136 /* LNPropertyListCellView.h in Headers */, 214 | 39DE8E9C2092214400ED16B4 /* LNPropertyListEditor-Private.h in Headers */, 215 | 39DE8E942092030500ED16B4 /* LNPropertyListPopUpButtonCell.h in Headers */, 216 | 3946906C20976ED300B4A457 /* LNPropertyListDatePicker.h in Headers */, 217 | 3941486F2095E85900A21F96 /* LNPropertyListDatePickerCell.h in Headers */, 218 | 39F537F3264305AF00AB263A /* NSObject+LNPropertyListValueSorting.h in Headers */, 219 | 39D55F2026D82C100013B105 /* LNPropertyListDataEditorPanel.h in Headers */, 220 | 3925913A263C52B100AF78D3 /* LNPropertyListCellTextField.h in Headers */, 221 | 39D152962328A9C4009124C8 /* _LNPropertyListDatePicker.h in Headers */, 222 | 393E1875207F64A0002E6136 /* LNPropertyListEditor.h in Headers */, 223 | 393E1879207F68B4002E6136 /* LNPropertyListNode.h in Headers */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXHeadersBuildPhase section */ 228 | 229 | /* Begin PBXNativeTarget section */ 230 | 393E1838207F6119002E6136 /* LNPropertyListEditor */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 393E1841207F6119002E6136 /* Build configuration list for PBXNativeTarget "LNPropertyListEditor" */; 233 | buildPhases = ( 234 | 393E1834207F6119002E6136 /* Sources */, 235 | 393E1835207F6119002E6136 /* Frameworks */, 236 | 393E1836207F6119002E6136 /* Headers */, 237 | 393E1837207F6119002E6136 /* Resources */, 238 | 39D55F1D26D829970013B105 /* Embed Frameworks */, 239 | ); 240 | buildRules = ( 241 | ); 242 | dependencies = ( 243 | 39D1276D26D92552007E64D1 /* PBXTargetDependency */, 244 | ); 245 | name = LNPropertyListEditor; 246 | productName = LNPlistEditorView; 247 | productReference = 393E1839207F6119002E6136 /* LNPropertyListEditor.framework */; 248 | productType = "com.apple.product-type.framework"; 249 | }; 250 | /* End PBXNativeTarget section */ 251 | 252 | /* Begin PBXProject section */ 253 | 393E1830207F6119002E6136 /* Project object */ = { 254 | isa = PBXProject; 255 | attributes = { 256 | BuildIndependentTargetsInParallel = YES; 257 | LastUpgradeCheck = 1510; 258 | ORGANIZATIONNAME = "Leo Natan"; 259 | TargetAttributes = { 260 | 393E1838207F6119002E6136 = { 261 | CreatedOnToolsVersion = 9.4; 262 | }; 263 | }; 264 | }; 265 | buildConfigurationList = 393E1833207F6119002E6136 /* Build configuration list for PBXProject "LNPropertyListEditor" */; 266 | compatibilityVersion = "Xcode 9.3"; 267 | developmentRegion = en; 268 | hasScannedForEncodings = 0; 269 | knownRegions = ( 270 | en, 271 | Base, 272 | ); 273 | mainGroup = 393E182F207F6119002E6136; 274 | productRefGroup = 393E183A207F6119002E6136 /* Products */; 275 | projectDirPath = ""; 276 | projectReferences = ( 277 | { 278 | ProductGroup = 39D1276726D9254C007E64D1 /* Products */; 279 | ProjectRef = 39D1276626D9254C007E64D1 /* HexFiend.xcodeproj */; 280 | }, 281 | ); 282 | projectRoot = ""; 283 | targets = ( 284 | 393E1838207F6119002E6136 /* LNPropertyListEditor */, 285 | ); 286 | }; 287 | /* End PBXProject section */ 288 | 289 | /* Begin PBXReferenceProxy section */ 290 | 39D1276B26D9254C007E64D1 /* HexFiend.framework */ = { 291 | isa = PBXReferenceProxy; 292 | fileType = wrapper.framework; 293 | path = HexFiend.framework; 294 | remoteRef = 39D1276A26D9254C007E64D1 /* PBXContainerItemProxy */; 295 | sourceTree = BUILT_PRODUCTS_DIR; 296 | }; 297 | /* End PBXReferenceProxy section */ 298 | 299 | /* Begin PBXResourcesBuildPhase section */ 300 | 393E1837207F6119002E6136 /* Resources */ = { 301 | isa = PBXResourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | 391FF02B2084060000005D0F /* Assets.xcassets in Resources */, 305 | 393E1872207F61C2002E6136 /* LNPropertyListEditorOutline.xib in Resources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | /* End PBXResourcesBuildPhase section */ 310 | 311 | /* Begin PBXSourcesBuildPhase section */ 312 | 393E1834207F6119002E6136 /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | 391FF030208412CC00005D0F /* LNPropertyListRowView.m in Sources */, 317 | 393E187A207F68B4002E6136 /* LNPropertyListNode.m in Sources */, 318 | 393E1886207FAEC6002E6136 /* LNPropertyListCellView.m in Sources */, 319 | 39D55F2126D82C100013B105 /* LNPropertyListDataEditorPanel.m in Sources */, 320 | 391FF0342084270400005D0F /* LNPropertyListOutlineView.m in Sources */, 321 | 39D152972328A9C4009124C8 /* _LNPropertyListDatePicker.m in Sources */, 322 | 3946906D20976ED300B4A457 /* LNPropertyListDatePicker.m in Sources */, 323 | 3925913B263C52B100AF78D3 /* LNPropertyListCellTextField.m in Sources */, 324 | 394148702095E85900A21F96 /* LNPropertyListDatePickerCell.mm in Sources */, 325 | 393E1876207F64A0002E6136 /* LNPropertyListEditor.m in Sources */, 326 | 39F537F4264305AF00AB263A /* NSObject+LNPropertyListValueSorting.m in Sources */, 327 | 39DE8E952092030500ED16B4 /* LNPropertyListPopUpButtonCell.m in Sources */, 328 | 39D1529023289668009124C8 /* LNPropertyListDatePickerPanel.m in Sources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | /* End PBXSourcesBuildPhase section */ 333 | 334 | /* Begin PBXTargetDependency section */ 335 | 39D1276D26D92552007E64D1 /* PBXTargetDependency */ = { 336 | isa = PBXTargetDependency; 337 | name = HexFiend; 338 | targetProxy = 39D1276C26D92552007E64D1 /* PBXContainerItemProxy */; 339 | }; 340 | /* End PBXTargetDependency section */ 341 | 342 | /* Begin XCBuildConfiguration section */ 343 | 393E183F207F6119002E6136 /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ALWAYS_SEARCH_USER_PATHS = NO; 347 | CLANG_ANALYZER_NONNULL = YES; 348 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 349 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 350 | CLANG_CXX_LIBRARY = "libc++"; 351 | CLANG_ENABLE_MODULES = YES; 352 | CLANG_ENABLE_OBJC_ARC = YES; 353 | CLANG_ENABLE_OBJC_WEAK = YES; 354 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 355 | CLANG_WARN_BOOL_CONVERSION = YES; 356 | CLANG_WARN_COMMA = YES; 357 | CLANG_WARN_CONSTANT_CONVERSION = YES; 358 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 359 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 360 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 361 | CLANG_WARN_EMPTY_BODY = YES; 362 | CLANG_WARN_ENUM_CONVERSION = YES; 363 | CLANG_WARN_INFINITE_RECURSION = YES; 364 | CLANG_WARN_INT_CONVERSION = YES; 365 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 366 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 367 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 368 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 369 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 370 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 371 | CLANG_WARN_STRICT_PROTOTYPES = YES; 372 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 373 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 374 | CLANG_WARN_UNREACHABLE_CODE = YES; 375 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 376 | CODE_SIGN_IDENTITY = "-"; 377 | COPY_PHASE_STRIP = NO; 378 | CURRENT_PROJECT_VERSION = 1; 379 | DEAD_CODE_STRIPPING = YES; 380 | DEBUG_INFORMATION_FORMAT = dwarf; 381 | ENABLE_STRICT_OBJC_MSGSEND = YES; 382 | ENABLE_TESTABILITY = YES; 383 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 384 | GCC_C_LANGUAGE_STANDARD = gnu11; 385 | GCC_DYNAMIC_NO_PIC = NO; 386 | GCC_NO_COMMON_BLOCKS = YES; 387 | GCC_OPTIMIZATION_LEVEL = 0; 388 | GCC_PREPROCESSOR_DEFINITIONS = ( 389 | "DEBUG=1", 390 | "$(inherited)", 391 | ); 392 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 394 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 395 | GCC_WARN_UNDECLARED_SELECTOR = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 397 | GCC_WARN_UNUSED_FUNCTION = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | MACOSX_DEPLOYMENT_TARGET = 10.13; 400 | MTL_ENABLE_DEBUG_INFO = YES; 401 | ONLY_ACTIVE_ARCH = YES; 402 | SDKROOT = macosx; 403 | VERSIONING_SYSTEM = "apple-generic"; 404 | VERSION_INFO_PREFIX = ""; 405 | }; 406 | name = Debug; 407 | }; 408 | 393E1840207F6119002E6136 /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | ALWAYS_SEARCH_USER_PATHS = NO; 412 | CLANG_ANALYZER_NONNULL = YES; 413 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 414 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 415 | CLANG_CXX_LIBRARY = "libc++"; 416 | CLANG_ENABLE_MODULES = YES; 417 | CLANG_ENABLE_OBJC_ARC = YES; 418 | CLANG_ENABLE_OBJC_WEAK = YES; 419 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 420 | CLANG_WARN_BOOL_CONVERSION = YES; 421 | CLANG_WARN_COMMA = YES; 422 | CLANG_WARN_CONSTANT_CONVERSION = YES; 423 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 424 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 425 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 426 | CLANG_WARN_EMPTY_BODY = YES; 427 | CLANG_WARN_ENUM_CONVERSION = YES; 428 | CLANG_WARN_INFINITE_RECURSION = YES; 429 | CLANG_WARN_INT_CONVERSION = YES; 430 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 431 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 432 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 433 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 434 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 435 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 436 | CLANG_WARN_STRICT_PROTOTYPES = YES; 437 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 438 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 439 | CLANG_WARN_UNREACHABLE_CODE = YES; 440 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 441 | CODE_SIGN_IDENTITY = "-"; 442 | COPY_PHASE_STRIP = NO; 443 | CURRENT_PROJECT_VERSION = 1; 444 | DEAD_CODE_STRIPPING = YES; 445 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 446 | ENABLE_STRICT_OBJC_MSGSEND = YES; 447 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 448 | GCC_C_LANGUAGE_STANDARD = gnu11; 449 | GCC_NO_COMMON_BLOCKS = YES; 450 | GCC_TREAT_WARNINGS_AS_ERRORS = YES; 451 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 452 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 453 | GCC_WARN_UNDECLARED_SELECTOR = YES; 454 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 455 | GCC_WARN_UNUSED_FUNCTION = YES; 456 | GCC_WARN_UNUSED_VARIABLE = YES; 457 | MACOSX_DEPLOYMENT_TARGET = 10.13; 458 | MTL_ENABLE_DEBUG_INFO = NO; 459 | SDKROOT = macosx; 460 | VERSIONING_SYSTEM = "apple-generic"; 461 | VERSION_INFO_PREFIX = ""; 462 | }; 463 | name = Release; 464 | }; 465 | 393E1842207F6119002E6136 /* Debug */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; 469 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; 470 | CODE_SIGN_IDENTITY = ""; 471 | CODE_SIGN_STYLE = Automatic; 472 | COMBINE_HIDPI_IMAGES = YES; 473 | DEAD_CODE_STRIPPING = YES; 474 | DYLIB_COMPATIBILITY_VERSION = 1; 475 | DYLIB_CURRENT_VERSION = 1; 476 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 477 | ENABLE_MODULE_VERIFIER = YES; 478 | FRAMEWORK_VERSION = A; 479 | IBC_ERRORS = NO; 480 | IBC_NOTICES = NO; 481 | IBC_WARNINGS = NO; 482 | INFOPLIST_FILE = LNPropertyListEditor/Info.plist; 483 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 484 | LD_RUNPATH_SEARCH_PATHS = ( 485 | "$(inherited)", 486 | "@executable_path/../Frameworks", 487 | "@loader_path/Frameworks", 488 | ); 489 | MACOSX_DEPLOYMENT_TARGET = 10.14; 490 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 491 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; 492 | ONLY_ACTIVE_ARCH = NO; 493 | PRODUCT_BUNDLE_IDENTIFIER = com.leonatan.LNPropertyListEditor; 494 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 495 | SKIP_INSTALL = YES; 496 | WARNING_CFLAGS = "-Wno-incomplete-umbrella"; 497 | }; 498 | name = Debug; 499 | }; 500 | 393E1843207F6119002E6136 /* Release */ = { 501 | isa = XCBuildConfiguration; 502 | buildSettings = { 503 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; 504 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; 505 | CODE_SIGN_IDENTITY = ""; 506 | CODE_SIGN_STYLE = Automatic; 507 | COMBINE_HIDPI_IMAGES = YES; 508 | DEAD_CODE_STRIPPING = YES; 509 | DYLIB_COMPATIBILITY_VERSION = 1; 510 | DYLIB_CURRENT_VERSION = 1; 511 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 512 | ENABLE_MODULE_VERIFIER = YES; 513 | FRAMEWORK_VERSION = A; 514 | IBC_ERRORS = NO; 515 | IBC_NOTICES = NO; 516 | IBC_WARNINGS = NO; 517 | INFOPLIST_FILE = LNPropertyListEditor/Info.plist; 518 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 519 | LD_RUNPATH_SEARCH_PATHS = ( 520 | "$(inherited)", 521 | "@executable_path/../Frameworks", 522 | "@loader_path/Frameworks", 523 | ); 524 | MACOSX_DEPLOYMENT_TARGET = 10.14; 525 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; 526 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14"; 527 | PRODUCT_BUNDLE_IDENTIFIER = com.leonatan.LNPropertyListEditor; 528 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 529 | SKIP_INSTALL = YES; 530 | WARNING_CFLAGS = "-Wno-incomplete-umbrella"; 531 | }; 532 | name = Release; 533 | }; 534 | /* End XCBuildConfiguration section */ 535 | 536 | /* Begin XCConfigurationList section */ 537 | 393E1833207F6119002E6136 /* Build configuration list for PBXProject "LNPropertyListEditor" */ = { 538 | isa = XCConfigurationList; 539 | buildConfigurations = ( 540 | 393E183F207F6119002E6136 /* Debug */, 541 | 393E1840207F6119002E6136 /* Release */, 542 | ); 543 | defaultConfigurationIsVisible = 0; 544 | defaultConfigurationName = Release; 545 | }; 546 | 393E1841207F6119002E6136 /* Build configuration list for PBXNativeTarget "LNPropertyListEditor" */ = { 547 | isa = XCConfigurationList; 548 | buildConfigurations = ( 549 | 393E1842207F6119002E6136 /* Debug */, 550 | 393E1843207F6119002E6136 /* Release */, 551 | ); 552 | defaultConfigurationIsVisible = 0; 553 | defaultConfigurationName = Release; 554 | }; 555 | /* End XCConfigurationList section */ 556 | }; 557 | rootObject = 393E1830207F6119002E6136 /* Project object */; 558 | } 559 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor.xcodeproj/xcshareddata/xcschemes/LNPropertyListEditor.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/minus.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "filename" : "minus.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/minus.imageset/minus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPropertyListEditor/7688237cb69ad68dd53ecf6f9f60f37a619b80e0/LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/minus.imageset/minus.pdf -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/plus.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "filename" : "plus.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/plus.imageset/plus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPropertyListEditor/7688237cb69ad68dd53ecf6f9f60f37a619b80e0/LNPropertyListEditor/LNPropertyListEditor/Assets.xcassets/plus.imageset/plus.pdf -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListCellTextField.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListCellTextField.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/30/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LNPropertyListCellTextField : NSTextField 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListCellTextField.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListCellTextField.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/30/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListCellTextField.h" 10 | 11 | @implementation LNPropertyListCellTextField 12 | 13 | - (NSView *)hitTest:(NSPoint)point 14 | { 15 | if((self.currentEditor == nil || self.window.firstResponder != self.currentEditor) && 16 | (NSApp.currentEvent.type == NSEventTypeRightMouseDown || NSApp.currentEvent.type == NSEventTypeRightMouseUp)) 17 | { 18 | return nil; 19 | } 20 | 21 | return [super hitTest:point]; 22 | } 23 | 24 | - (BOOL)becomeFirstResponder 25 | { 26 | return [super becomeFirstResponder]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListCellView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListCellView.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LNPropertyListDatePicker.h" 11 | 12 | @interface LNPropertyListCellView : NSTableCellView 13 | 14 | @property (nonatomic, strong) IBOutlet LNPropertyListDatePicker *datePicker; 15 | @property (nonatomic, strong) IBOutlet NSPopUpButton *typeButton; 16 | @property (nonatomic, strong) IBOutlet NSLayoutConstraint *typeButtonLeadingConstraint; 17 | @property (nonatomic, weak) IBOutlet NSButton *minusButton; 18 | @property (nonatomic, weak) IBOutlet NSButton *plusButton; 19 | @property (nonatomic, strong) IBOutlet NSLayoutConstraint *buttonsConstraint; 20 | 21 | @property (nonatomic, readonly) BOOL showsControlButtons; 22 | - (void)setShowsControlButtons:(BOOL)showsControlButtons addButtonEnabled:(BOOL)addButtonEnabled deleteButtonEnabled:(BOOL)deleteButtonEnabled; 23 | 24 | - (void)setControlWithString:(NSString*)str setToolTip:(BOOL)setToolTip; 25 | - (void)setControlWithBoolean:(BOOL)boolean; 26 | - (void)setControlWithDate:(NSDate*)date; 27 | - (void)setControlEditable:(BOOL)editable; 28 | - (void)flashError; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListCellView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListCellView.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListCellView.h" 10 | @import QuartzCore; 11 | @import ObjectiveC; 12 | 13 | @interface LNPropertyListCellView () @end 14 | 15 | @implementation LNPropertyListCellView 16 | 17 | - (void)awakeFromNib 18 | { 19 | [super awakeFromNib]; 20 | 21 | objc_setAssociatedObject(self.typeButton.menu, "button", self.typeButton, OBJC_ASSOCIATION_ASSIGN); 22 | 23 | if(self.buttonsConstraint) 24 | { 25 | [NSLayoutConstraint deactivateConstraints:@[self.buttonsConstraint]]; 26 | } 27 | 28 | if(@available(macOS 11.0, *)) 29 | { 30 | _typeButtonLeadingConstraint.constant = -2; 31 | } 32 | } 33 | 34 | - (void)prepareForReuse 35 | { 36 | [super prepareForReuse]; 37 | 38 | self.plusButton.hidden = self.minusButton.hidden = YES; 39 | if(self.buttonsConstraint) 40 | { 41 | [NSLayoutConstraint deactivateConstraints:@[self.buttonsConstraint]]; 42 | } 43 | } 44 | 45 | - (void)setControlWithString:(NSString*)str setToolTip:(BOOL)setToolTip 46 | { 47 | if(self.typeButton) 48 | { 49 | [self.typeButton selectItemWithTitle:str]; 50 | } 51 | else 52 | { 53 | self.textField.stringValue = str; 54 | } 55 | 56 | if(setToolTip) 57 | { 58 | self.toolTip = str; 59 | } 60 | } 61 | 62 | - (void)setControlWithBoolean:(BOOL)boolean 63 | { 64 | [self.typeButton selectItemAtIndex:(NSInteger)boolean]; 65 | } 66 | 67 | - (void)setControlWithDate:(NSDate*)date 68 | { 69 | _datePicker.dateValue = date; 70 | } 71 | 72 | - (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle 73 | { 74 | [super setBackgroundStyle:backgroundStyle]; 75 | 76 | [_datePicker.cell setBackgroundStyle:backgroundStyle]; 77 | } 78 | 79 | - (void)flashError 80 | { 81 | CABasicAnimation* flashAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; 82 | flashAnimation.fromValue = (__bridge id)NSColor.clearColor.CGColor; 83 | flashAnimation.toValue = (__bridge id)NSColor.systemRedColor.CGColor; 84 | flashAnimation.duration = 0.25; 85 | flashAnimation.autoreverses = YES; 86 | flashAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 87 | flashAnimation.fillMode = kCAFillModeForwards; 88 | flashAnimation.removedOnCompletion = YES; 89 | 90 | [self.layer addAnimation:flashAnimation forKey:@"backgroundColor"]; 91 | } 92 | 93 | - (void)setShowsControlButtons:(BOOL)showsControlButtons addButtonEnabled:(BOOL)addButtonEnabled deleteButtonEnabled:(BOOL)deleteButtonEnabled 94 | { 95 | _showsControlButtons = showsControlButtons && (addButtonEnabled || deleteButtonEnabled); 96 | 97 | self.plusButton.hidden = self.minusButton.hidden = !_showsControlButtons; 98 | self.buttonsConstraint.active = _showsControlButtons; 99 | 100 | self.plusButton.enabled = addButtonEnabled; 101 | self.minusButton.enabled = deleteButtonEnabled; 102 | } 103 | 104 | - (void)setControlEditable:(BOOL)editable 105 | { 106 | self.textField.selectable = self.textField.editable = editable; 107 | _typeButton.enabled = editable; 108 | _datePicker.enabled = editable; 109 | 110 | NSColor* controlColor = editable ? NSColor.labelColor : NSColor.disabledControlTextColor; 111 | 112 | self.textField.textColor = controlColor; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDataEditorPanel.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDataEditorPanel.h 3 | // LNPropertyListDataEditorPanel 4 | // 5 | // Created by Leo Natan on 8/26/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LNPropertyListDataEditorPanel : NSPanel 14 | 15 | @property (nonatomic, copy) NSData* data; 16 | 17 | - (void)beginSheetModalForWindow:(NSWindow *)window completionHandler:(void (^)(NSModalResponse result))handler; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDataEditorPanel.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDataEditorPanel.m 3 | // LNPropertyListDataEditorPanel 4 | // 5 | // Created by Leo Natan on 8/26/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListDataEditorPanel.h" 10 | #import 11 | 12 | @interface _LNPropertyListDataEditorTextDividerRepresenter : HFRepresenter @end 13 | 14 | @implementation _LNPropertyListDataEditorTextDividerRepresenter 15 | 16 | - (NSView *)createView { 17 | NSBox* separator = [NSBox new]; 18 | separator.boxType = NSBoxSeparator; 19 | separator.autoresizingMask = NSViewHeightSizable; 20 | 21 | return separator; 22 | } 23 | 24 | - (CGFloat)minimumViewWidthForBytesPerLine:(NSUInteger)bytesPerLine { 25 | USE(bytesPerLine); 26 | return 1; 27 | } 28 | 29 | + (NSPoint)defaultLayoutPosition { 30 | return NSMakePoint(2, 0); 31 | } 32 | 33 | @end 34 | 35 | @interface LNPropertyListDataEditorPanel () 36 | 37 | @end 38 | 39 | @implementation LNPropertyListDataEditorPanel 40 | { 41 | HFTextView* _hexTextView; 42 | } 43 | 44 | - (void)setData:(NSData *)data 45 | { 46 | _data = [data copy]; 47 | 48 | [self _reloadHexTextField]; 49 | } 50 | 51 | - (void)_reloadHexTextField 52 | { 53 | _hexTextView.data = _data; 54 | 55 | [self _updateWindowSizeToContent]; 56 | 57 | [_hexTextView.layoutRepresenter performLayout]; 58 | [self.undoManager removeAllActions]; 59 | } 60 | 61 | - (instancetype)init 62 | { 63 | self = [super init]; 64 | 65 | if(self) 66 | { 67 | [self setFrame:NSMakeRect(0, 0, 900, 550) display:NO]; 68 | [self center]; 69 | self.styleMask |= NSWindowStyleMaskResizable; 70 | self.delegate = self; 71 | self.minSize = NSMakeSize(400, 300); 72 | 73 | _hexTextView = [[HFTextView alloc] initWithFrame:self.contentView.bounds]; 74 | _hexTextView.controller.bytesPerColumn = 4; 75 | _hexTextView.delegate = self; 76 | 77 | HFLineCountingRepresenter* lineCountingRepresenter = [HFLineCountingRepresenter new]; 78 | lineCountingRepresenter.lineNumberFormat = HFLineNumberFormatHexadecimal; 79 | // HFStatusBarRepresenter* statusBarRepresenter = [HFStatusBarRepresenter new]; 80 | // statusBarRepresenter.statusMode = HFStatusModeDecimal; 81 | _LNPropertyListDataEditorTextDividerRepresenter* textDivider = [_LNPropertyListDataEditorTextDividerRepresenter new]; 82 | 83 | _hexTextView.layoutRepresenter.maximizesBytesPerLine = YES; 84 | [_hexTextView.layoutRepresenter addRepresenter:lineCountingRepresenter]; 85 | [_hexTextView.layoutRepresenter addRepresenter:textDivider]; 86 | // [_hexTextView.layoutRepresenter addRepresenter:statusBarRepresenter]; 87 | [_hexTextView.controller addRepresenter:lineCountingRepresenter]; 88 | // [_hexTextView.controller addRepresenter:statusBarRepresenter]; 89 | _hexTextView.controller.font = [NSFont userFixedPitchFontOfSize:0]; 90 | 91 | _hexTextView.controller.undoManager = self.undoManager; 92 | 93 | _hexTextView.translatesAutoresizingMaskIntoConstraints = NO; 94 | [self.contentView addSubview:_hexTextView]; 95 | 96 | NSButton* OKButton = [NSButton buttonWithTitle:@"Save" target:self action:@selector(_save:)]; 97 | OKButton.keyEquivalent = [NSString stringWithFormat:@"\r"]; 98 | NSButton* cancelButton = [NSButton buttonWithTitle:@"Cancel" target:self action:@selector(_cancel:)]; 99 | cancelButton.keyEquivalent = [NSString stringWithFormat:@"%C", 0x1b]; 100 | 101 | NSStackView* controlButtonsStackView = [NSStackView stackViewWithViews:@[cancelButton, OKButton]]; 102 | controlButtonsStackView.translatesAutoresizingMaskIntoConstraints = NO; 103 | 104 | [self.contentView addSubview:controlButtonsStackView]; 105 | 106 | NSBox* backgroundBox = [NSBox new]; 107 | backgroundBox.translatesAutoresizingMaskIntoConstraints = NO; 108 | backgroundBox.boxType = NSBoxCustom; 109 | backgroundBox.borderColor = NSColor.clearColor; 110 | backgroundBox.fillColor = NSColor.windowBackgroundColor; 111 | 112 | NSBox* separator = [NSBox new]; 113 | separator.translatesAutoresizingMaskIntoConstraints = NO; 114 | separator.boxType = NSBoxSeparator; 115 | 116 | [self.contentView addSubview:backgroundBox positioned:NSWindowBelow relativeTo:nil]; 117 | [self.contentView addSubview:separator positioned:NSWindowAbove relativeTo:nil]; 118 | 119 | [NSLayoutConstraint activateConstraints:@[ 120 | [self.contentView.topAnchor constraintEqualToAnchor:_hexTextView.topAnchor], 121 | [self.contentView.leadingAnchor constraintEqualToAnchor:_hexTextView.leadingAnchor], 122 | [self.contentView.trailingAnchor constraintEqualToAnchor:_hexTextView.trailingAnchor], 123 | [_hexTextView.bottomAnchor constraintEqualToAnchor:controlButtonsStackView.topAnchor constant:-20], 124 | 125 | [self.contentView.trailingAnchor constraintEqualToAnchor:controlButtonsStackView.trailingAnchor constant:20], 126 | [self.contentView.bottomAnchor constraintEqualToAnchor:controlButtonsStackView.bottomAnchor constant:20], 127 | 128 | [OKButton.widthAnchor constraintEqualToAnchor:cancelButton.widthAnchor], 129 | 130 | [self.contentView.leadingAnchor constraintEqualToAnchor:backgroundBox.leadingAnchor], 131 | [self.contentView.trailingAnchor constraintEqualToAnchor:backgroundBox.trailingAnchor], 132 | [self.contentView.bottomAnchor constraintEqualToAnchor:backgroundBox.bottomAnchor], 133 | [controlButtonsStackView.topAnchor constraintEqualToAnchor:backgroundBox.topAnchor constant:20], 134 | 135 | [self.contentView.leadingAnchor constraintEqualToAnchor:separator.leadingAnchor], 136 | [self.contentView.trailingAnchor constraintEqualToAnchor:separator.trailingAnchor], 137 | [controlButtonsStackView.topAnchor constraintEqualToAnchor:separator.topAnchor constant:20], 138 | ]]; 139 | 140 | [_hexTextView.layoutRepresenter performLayout]; 141 | 142 | NSNotificationCenter *center = NSNotificationCenter.defaultCenter; 143 | [center addObserver:self selector:@selector(_updateWindowSizeToContent) name:HFLineCountingRepresenterMinimumViewWidthChanged object:lineCountingRepresenter]; 144 | } 145 | 146 | return self; 147 | } 148 | 149 | - (void)_save:(id)sender 150 | { 151 | _data = [_hexTextView.data copy]; 152 | 153 | [self.sheetParent endSheet:self returnCode:NSModalResponseOK]; 154 | } 155 | 156 | - (void)_cancel:(id)sender 157 | { 158 | [self.sheetParent endSheet:self returnCode:NSModalResponseCancel]; 159 | } 160 | 161 | - (void)beginSheetModalForWindow:(NSWindow *)window completionHandler:(void (^)(NSModalResponse))handler 162 | { 163 | // [self makeKeyAndOrderFront:nil]; 164 | 165 | [window beginCriticalSheet:self completionHandler:^(NSModalResponse returnCode) { 166 | handler(returnCode); 167 | }]; 168 | } 169 | 170 | - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize 171 | { 172 | if(_hexTextView.layoutRepresenter == nil) 173 | { 174 | return frameSize; 175 | } 176 | 177 | return [self minimumWindowFrameSizeForProposedSize:frameSize]; 178 | } 179 | 180 | - (NSSize)minimumWindowFrameSizeForProposedSize:(NSSize)frameSize 181 | { 182 | NSSize proposedSizeInLayoutCoordinates = [_hexTextView convertSize:frameSize fromView:nil]; 183 | CGFloat resultingWidthInLayoutCoordinates = [_hexTextView.layoutRepresenter minimumViewWidthForLayoutInProposedWidth:proposedSizeInLayoutCoordinates.width]; 184 | NSSize resultSize = [_hexTextView convertSize:NSMakeSize(resultingWidthInLayoutCoordinates, proposedSizeInLayoutCoordinates.height) toView:nil]; 185 | return resultSize; 186 | } 187 | 188 | - (void)_updateWindowSizeToContent 189 | { 190 | NSRect windowFrame = self.frame; 191 | CGFloat minViewWidth = [_hexTextView.layoutRepresenter minimumViewWidthForBytesPerLine:_hexTextView.controller.bytesPerLine]; 192 | CGFloat minWindowWidth = [_hexTextView convertSize:NSMakeSize(minViewWidth, 1) toView:nil].width; 193 | windowFrame.size.width = minWindowWidth; 194 | [self setFrame:windowFrame display:YES]; 195 | } 196 | 197 | #pragma mark HFTextViewDelegate 198 | 199 | - (void)hexTextView:(HFTextView *)view didChangeProperties:(HFControllerPropertyBits)properties 200 | { 201 | 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePicker.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/30/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LNPropertyListDatePicker : NSControl 12 | 13 | @property (nonatomic, copy) NSDate *dateValue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePicker.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/30/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListDatePicker.h" 10 | #import "_LNPropertyListDatePicker.h" 11 | #import "LNPropertyListDatePickerCell.h" 12 | 13 | @interface _LNPropertyListDatePickerInnerCell : NSCell 14 | 15 | @property (nonatomic, copy) NSArray* childCells; 16 | 17 | @end 18 | 19 | @implementation _LNPropertyListDatePickerInnerCell 20 | 21 | - (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle 22 | { 23 | [self.childCells enumerateObjectsUsingBlock:^(NSCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 24 | [obj setBackgroundStyle:backgroundStyle]; 25 | }]; 26 | } 27 | 28 | - (void)setHighlighted:(BOOL)highlighted 29 | {} 30 | 31 | @end 32 | 33 | IB_DESIGNABLE 34 | @implementation LNPropertyListDatePicker 35 | { 36 | _LNPropertyListDatePicker* _datePicker; 37 | } 38 | 39 | - (void)prepareForInterfaceBuilder 40 | { 41 | _datePicker.dateValue = [NSDate date]; 42 | } 43 | 44 | - (void)setEnabled:(BOOL)enabled 45 | { 46 | [super setEnabled:enabled]; 47 | 48 | [_datePicker setEnabled:enabled]; 49 | } 50 | 51 | - (void)awakeFromNib 52 | { 53 | [super awakeFromNib]; 54 | 55 | NSFont* font = [NSFont monospacedDigitSystemFontOfSize:NSFont.smallSystemFontSize weight:NSFontWeightRegular]; 56 | 57 | _datePicker = [_LNPropertyListDatePicker new]; 58 | _datePicker.cell = [LNPropertyListDatePickerCell new]; 59 | _datePicker.font = font; 60 | _datePicker.datePickerStyle = NSDatePickerStyleTextField; 61 | _datePicker.datePickerElements = NSDatePickerElementFlagYearMonthDay | NSDatePickerElementFlagEra | NSDatePickerElementFlagHourMinuteSecond | NSDatePickerElementFlagTimeZone; 62 | _datePicker.bordered = NO; 63 | _datePicker.drawsBackground = NO; 64 | _datePicker.translatesAutoresizingMaskIntoConstraints = NO; 65 | _datePicker.target = self; 66 | _datePicker.action = @selector(_internalDatePickerValueChanged:); 67 | 68 | _LNPropertyListDatePickerInnerCell* cell = [_LNPropertyListDatePickerInnerCell new]; 69 | cell.childCells = @[_datePicker.cell]; 70 | cell.bordered = NO; 71 | self.cell = cell; 72 | 73 | [self addSubview:_datePicker]; 74 | 75 | [_datePicker setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; 76 | [_datePicker setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; 77 | [NSLayoutConstraint activateConstraints:@[ 78 | [self.heightAnchor constraintEqualToAnchor:_datePicker.heightAnchor], 79 | [self.leadingAnchor constraintEqualToAnchor:_datePicker.leadingAnchor], 80 | [self.centerYAnchor constraintEqualToAnchor:_datePicker.centerYAnchor constant:-1.5], 81 | ]]; 82 | 83 | [self setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; 84 | [self setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; 85 | 86 | self.wantsLayer = YES; 87 | self.layer.masksToBounds = NO; 88 | } 89 | 90 | - (void)_setDateValue:(NSDate *)dateValue sendAction:(BOOL)sendAction 91 | { 92 | self.objectValue = dateValue; 93 | 94 | _datePicker.dateValue = self.dateValue; 95 | _datePicker.visualDatePicker.dateValue = self.dateValue; 96 | _datePicker.textDatePicker.dateValue = self.dateValue; 97 | 98 | if(sendAction) 99 | { 100 | [self sendAction:self.action to:self.target]; 101 | } 102 | } 103 | 104 | - (NSDate *)dateValue 105 | { 106 | return self.objectValue; 107 | } 108 | 109 | - (void)setDateValue:(NSDate *)dateValue 110 | { 111 | [self _setDateValue:dateValue sendAction:NO]; 112 | } 113 | 114 | - (IBAction)_internalDatePickerValueChanged:(id)sender 115 | { 116 | [self _setDateValue:[sender dateValue] sendAction:YES]; 117 | } 118 | 119 | - (BOOL)resignFirstResponder 120 | { 121 | return [super resignFirstResponder]; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePickerCell.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/29/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDatePickerCell () 12 | 13 | - (BOOL)_textFieldWithStepperTrackMouse:(id)arg1 inRect:(NSRect)arg2 ofView:(id)arg3 untilMouseUp:(BOOL)arg4; 14 | 15 | @end 16 | 17 | @interface LNLeadingZerosDatePickerCell : NSDatePickerCell 18 | 19 | @property (nonatomic) BOOL drawsBackgroundOnFirstResponder; 20 | 21 | @end 22 | 23 | @interface LNPropertyListDatePickerCell : LNLeadingZerosDatePickerCell 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePickerCell.mm: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePickerCell.mm 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/29/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListDatePickerCell.h" 10 | #import 11 | 12 | static NSDatePickerCell* __strong __drawingDatePickerCell; 13 | 14 | @interface NSDatePickerCell () 15 | 16 | - (void)_setForcesLeadingZeroes:(BOOL)arg1; 17 | - (NSColor*)_textColorBasedOnEnabledState; 18 | 19 | @end 20 | 21 | @interface NSBezierPath (LNPropertyListEditorDatePickerCustomization) @end 22 | 23 | @implementation NSBezierPath (LNPropertyListEditorDatePickerCustomization) 24 | 25 | + (void)load 26 | { 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | Method m1 = class_getClassMethod(NSBezierPath.class, @selector(__ln_bezierPathWithRoundedRect:xRadius:yRadius:)); 30 | Method m2 = class_getClassMethod(NSBezierPath.class, @selector(bezierPathWithRoundedRect:xRadius:yRadius:)); 31 | method_exchangeImplementations(m1, m2); 32 | }); 33 | } 34 | 35 | + (NSBezierPath *)__ln_bezierPathWithRoundedRect:(NSRect)rect xRadius:(CGFloat)xRadius yRadius:(CGFloat)yRadius 36 | { 37 | if(__drawingDatePickerCell != nil) 38 | { 39 | // [[__drawingDatePickerCell._textColorBasedOnEnabledState blendedColorWithFraction:0.6 ofColor:NSColor.alternateSelectedControlColor] set]; 40 | } 41 | 42 | NSBezierPath* rv = [self __ln_bezierPathWithRoundedRect:rect xRadius:xRadius yRadius:yRadius]; 43 | 44 | return rv; 45 | } 46 | 47 | @end 48 | 49 | @implementation LNLeadingZerosDatePickerCell 50 | 51 | - (instancetype)init 52 | { 53 | self = [super init]; 54 | 55 | if(self) 56 | { 57 | [self _setForcesLeadingZeroes:YES]; 58 | } 59 | 60 | return self; 61 | } 62 | 63 | @end 64 | 65 | @implementation LNPropertyListDatePickerCell 66 | 67 | - (BOOL)_ln_isFirstResponder 68 | { 69 | return self.controlView.window.firstResponder == self.controlView; 70 | } 71 | 72 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView 73 | { 74 | __drawingDatePickerCell = self; 75 | if(self._ln_isFirstResponder && self.drawsBackgroundOnFirstResponder) 76 | { 77 | [NSColor.textBackgroundColor setFill]; 78 | [[NSBezierPath bezierPathWithRect:cellFrame] fill]; 79 | } 80 | 81 | [super drawWithFrame:cellFrame inView:controlView]; 82 | 83 | __drawingDatePickerCell = nil; 84 | } 85 | 86 | //This is faster than setting the text color when the background color changes. 87 | - (NSColor*)_textColorBasedOnEnabledState 88 | { 89 | return self.isEnabled ? self.backgroundStyle == NSBackgroundStyleEmphasized ? self._ln_isFirstResponder ? NSColor.controlTextColor : NSColor.alternateSelectedControlTextColor : NSColor.controlTextColor : self.backgroundStyle == NSBackgroundStyleEmphasized ? [NSColor valueForKey:@"_alternateDisabledSelectedControlTextColor"] : NSColor.disabledControlTextColor; 90 | } 91 | 92 | - (BOOL)_shouldShowFocusRingInView:(id)arg1 93 | { 94 | return YES; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePickerPanel.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePickerPanel.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 9/11/19. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LNPropertyListDatePickerPanelBackgroundView : NSView 12 | 13 | @property (nonatomic, weak) NSView* textDatePicker; 14 | @property (nonatomic, weak) NSView* visualDatePicker; 15 | 16 | @end 17 | 18 | @class LNPropertyListDatePickerPanel; 19 | 20 | @protocol LNPropertyListDatePickerPanelDelegate 21 | 22 | - (void)propertyListDatePickerPanelDidClose:(LNPropertyListDatePickerPanel*)panel; 23 | 24 | @end 25 | 26 | @interface LNPropertyListDatePickerPanel : NSPanel 27 | 28 | @property (nonatomic, weak) id datePickerPanelDelegate; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListDatePickerPanel.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListDatePickerPanel.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 9/11/19. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListDatePickerPanel.h" 10 | 11 | @implementation LNPropertyListDatePickerPanelBackgroundView 12 | 13 | - (CGPathRef)_pathAroundView 14 | { 15 | const CGFloat radius = 4; 16 | 17 | CGMutablePathRef path = CGPathCreateMutable(); 18 | CGPathMoveToPoint(path, NULL, CGRectGetMinX(self.textDatePicker.frame), CGRectGetMaxY(self.textDatePicker.frame) - radius); 19 | CGPathAddArcToPoint(path, NULL, CGRectGetMinX(self.textDatePicker.frame), CGRectGetMaxY(self.textDatePicker.frame), 20 | CGRectGetMinX(self.textDatePicker.frame) + radius, CGRectGetMaxY(self.textDatePicker.frame), radius); 21 | CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(self.textDatePicker.frame) - radius, CGRectGetMaxY(self.textDatePicker.frame)); 22 | CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(self.textDatePicker.frame), CGRectGetMaxY(self.textDatePicker.frame), 23 | CGRectGetMaxX(self.textDatePicker.frame), CGRectGetMaxY(self.textDatePicker.frame) - radius, radius); 24 | CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(self.textDatePicker.frame), CGRectGetMaxY(self.visualDatePicker.frame) + radius); 25 | CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(self.textDatePicker.frame), CGRectGetMaxY(self.visualDatePicker.frame), 26 | CGRectGetMaxX(self.textDatePicker.frame) + radius, CGRectGetMaxY(self.visualDatePicker.frame), radius); 27 | CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(self.visualDatePicker.frame) - radius, CGRectGetMaxY(self.visualDatePicker.frame)); 28 | CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(self.visualDatePicker.frame), CGRectGetMaxY(self.visualDatePicker.frame), 29 | CGRectGetMaxX(self.visualDatePicker.frame), CGRectGetMaxY(self.visualDatePicker.frame) - radius, radius); 30 | CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(self.visualDatePicker.frame), CGRectGetMinY(self.visualDatePicker.frame) + radius); 31 | CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(self.visualDatePicker.frame), CGRectGetMinY(self.visualDatePicker.frame), 32 | CGRectGetMaxX(self.visualDatePicker.frame) - radius, CGRectGetMinY(self.visualDatePicker.frame), radius); 33 | CGPathAddLineToPoint(path, NULL, CGRectGetMinX(self.visualDatePicker.frame) + radius, CGRectGetMinY(self.visualDatePicker.frame)); 34 | CGPathAddArcToPoint(path, NULL, CGRectGetMinX(self.visualDatePicker.frame), CGRectGetMinY(self.visualDatePicker.frame), 35 | CGRectGetMinX(self.visualDatePicker.frame), CGRectGetMinY(self.visualDatePicker.frame) + radius, radius); 36 | CGPathCloseSubpath(path); 37 | 38 | return path; 39 | } 40 | 41 | - (void)drawRect:(NSRect)dirtyRect 42 | { 43 | [NSColor.controlBackgroundColor setFill]; 44 | 45 | CGContextRef ctx = NSGraphicsContext.currentContext.CGContext; 46 | 47 | CGContextAddPath(ctx, self._pathAroundView); 48 | CGContextFillPath(ctx); 49 | } 50 | 51 | @end 52 | 53 | @implementation LNPropertyListDatePickerPanel 54 | 55 | - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag 56 | { 57 | self = [super initWithContentRect:contentRect styleMask:NSWindowStyleMaskBorderless backing:backingStoreType defer:flag]; 58 | 59 | if(self) 60 | { 61 | self.releasedWhenClosed = NO; 62 | self.opaque = NO; 63 | self.hasShadow = YES; 64 | self.backgroundColor = NSColor.clearColor; 65 | self.hidesOnDeactivate = NO; 66 | } 67 | 68 | return self; 69 | } 70 | 71 | - (BOOL)canBecomeKeyWindow 72 | { 73 | return YES; 74 | } 75 | 76 | - (void)resignKeyWindow 77 | { 78 | [self close]; 79 | } 80 | 81 | - (void)close 82 | { 83 | if(self.isVisible == NO) 84 | { 85 | return; 86 | } 87 | 88 | [super close]; 89 | 90 | [self.datePickerPanelDelegate propertyListDatePickerPanelDidClose:self]; 91 | } 92 | 93 | - (void)setIsVisible:(BOOL)flag 94 | { 95 | if(self.isVisible == flag) 96 | { 97 | return; 98 | } 99 | 100 | [super setIsVisible:flag]; 101 | } 102 | 103 | - (void)setParentWindow:(NSWindow *)parentWindow 104 | { 105 | [super setParentWindow:parentWindow]; 106 | } 107 | 108 | - (void)dealloc 109 | { 110 | 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListEditor-Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListEditor.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LNPropertyListEditor.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | typedef struct { 15 | unsigned int delegate_willChangeNode : 1; 16 | unsigned int delegate_didChangeNode : 1; 17 | unsigned int delegate_canEditKeyOfNode : 1; 18 | unsigned int delegate_canEditTypeOfNode : 1; 19 | unsigned int delegate_canEditValueOfNode : 1; 20 | unsigned int delegate_canDeleteNode : 1; 21 | unsigned int delegate_canAddNewNodeInNode : 1; 22 | unsigned int delegate_canMoveNode : 1; 23 | unsigned int delegate_canPasteNode : 1; 24 | unsigned int delegate_canReorderChildrenOfNode : 1; 25 | unsigned int delegate_defaultPropertyListForAddingInNode : 1; 26 | 27 | unsigned int dataTransformer_displayNameForNode : 1; 28 | unsigned int dataTransformer_transformValueForDisplay : 1; 29 | unsigned int dataTransformer_transformValueForStorage : 1; 30 | } __LNPropertyListEditor_flags; 31 | 32 | @interface LNPropertyListEditor () 33 | 34 | @property (nonatomic) __LNPropertyListEditor_flags flags; 35 | @property (nonatomic, weak) IBOutlet NSOutlineView* outlineView; 36 | 37 | /// The current sort descriptors of the underlying outline view. 38 | @property (nullable, nonatomic, copy) NSArray* outlineViewSortDescriptors; 39 | 40 | - (BOOL)canInsertAtNode:(LNPropertyListNode*)node; 41 | - (BOOL)canDeleteNode:(LNPropertyListNode*)node; 42 | 43 | @end 44 | 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListNode-Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListNode.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LNPropertyListNode.h" 11 | 12 | #import 13 | 14 | extern NSString* const LNPropertyListNodePasteboardType; 15 | extern NSString* const LNPropertyListNodeXcodeKeyType; 16 | 17 | @interface LNPropertyListNode () 18 | 19 | @property (nonatomic, strong) id _cachedDisplayKey; 20 | @property (nonatomic, strong) id _cachedDisplayValue; 21 | @property (nonatomic, readonly) LNPropertyListNodeType _appropriateType; 22 | 23 | + (NSNumberFormatter*)_numberFormatter; 24 | 25 | + (LNPropertyListNodeType)_typeForObject:(id)obj; 26 | + (NSString*)stringForType:(LNPropertyListNodeType)type; 27 | + (LNPropertyListNodeType)typeForString:(NSString*)str; 28 | + (id)defaultValueForType:(LNPropertyListNodeType)type; 29 | + (id)convertString:(NSString*)str toObjectOfType:(LNPropertyListNodeType)type; 30 | + (NSString*)stringKeyOfNode:(LNPropertyListNode*)node; 31 | + (NSString*)stringValueOfNode:(LNPropertyListNode*)node; 32 | 33 | + (instancetype)_nodeFromPasteboard:(NSPasteboard*)pasteboard; 34 | + (void)_clearPasteboardMapping; 35 | 36 | - (void)_setObject:(id)object; 37 | 38 | - (void)_sortUsingDescriptors:(NSArray *)descriptors validator:(BOOL (^)(LNPropertyListNode*))validator callback:(void (^)(LNPropertyListNode*, BOOL))callback; 39 | 40 | - (id)pasteboardWriter; 41 | 42 | @end 43 | 44 | @interface LNPropertyListNodePasteboardWriter : NSObject 45 | 46 | - (instancetype)initWithNode:(LNPropertyListNode*)node; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListNode.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListNode-Private.h" 10 | #import 11 | 12 | #define NS(x) ((__bridge id)x) 13 | 14 | NSString* const LNPropertyListNodePasteboardType = @"com.LeoNatan.LNPropertyList.node"; 15 | NSString* const LNPropertyListNodeXcodeKeyType = @"com.apple.xcode.plist.key"; 16 | static NSMapTable* _pasteboardNodeMapping; 17 | 18 | @implementation LNPropertyListNode 19 | 20 | + (void)load 21 | { 22 | @autoreleasepool 23 | { 24 | _pasteboardNodeMapping = [NSMapTable strongToWeakObjectsMapTable]; 25 | } 26 | } 27 | 28 | + (BOOL)supportsSecureCoding 29 | { 30 | return YES; 31 | } 32 | 33 | + (NSNumberFormatter*)_numberFormatter 34 | { 35 | static NSNumberFormatter* __numberFormatter; 36 | static dispatch_once_t onceToken; 37 | dispatch_once(&onceToken, ^{ 38 | __numberFormatter = [NSNumberFormatter new]; 39 | __numberFormatter.numberStyle = NSNumberFormatterNoStyle; 40 | }); 41 | return __numberFormatter; 42 | } 43 | 44 | + (LNPropertyListNodeType)_typeForObject:(id)obj 45 | { 46 | if([obj isKindOfClass:[NSArray class]]) 47 | { 48 | return LNPropertyListNodeTypeArray; 49 | } 50 | if([obj isKindOfClass:[NSDictionary class]]) 51 | { 52 | return LNPropertyListNodeTypeDictionary; 53 | } 54 | if([obj isKindOfClass:[NSString class]]) 55 | { 56 | return LNPropertyListNodeTypeString; 57 | } 58 | if([obj isKindOfClass:[NSDate class]]) 59 | { 60 | return LNPropertyListNodeTypeDate; 61 | } 62 | if([obj isKindOfClass:[NSData class]]) 63 | { 64 | return LNPropertyListNodeTypeData; 65 | } 66 | if([obj isKindOfClass:NSClassFromString(@"__NSCFBoolean")]) 67 | { 68 | return LNPropertyListNodeTypeBoolean; 69 | } 70 | if([obj isKindOfClass:[NSNumber class]]) 71 | { 72 | return LNPropertyListNodeTypeNumber; 73 | } 74 | 75 | return LNPropertyListNodeTypeUnknown; 76 | } 77 | 78 | + (NSString *)stringForType:(LNPropertyListNodeType)type 79 | { 80 | switch (type) 81 | { 82 | case LNPropertyListNodeTypeUnknown: 83 | return nil; 84 | case LNPropertyListNodeTypeArray: 85 | return @"Array"; 86 | case LNPropertyListNodeTypeDictionary: 87 | return @"Dictionary"; 88 | case LNPropertyListNodeTypeBoolean: 89 | return @"Boolean"; 90 | case LNPropertyListNodeTypeDate: 91 | return @"Date"; 92 | case LNPropertyListNodeTypeData: 93 | return @"Data"; 94 | case LNPropertyListNodeTypeNumber: 95 | return @"Number"; 96 | case LNPropertyListNodeTypeString: 97 | return @"String"; 98 | } 99 | } 100 | 101 | + (LNPropertyListNodeType)typeForString:(NSString*)str 102 | { 103 | if([str isEqualToString:@"Array"]) 104 | { 105 | return LNPropertyListNodeTypeArray; 106 | } 107 | if([str isEqualToString:@"Dictionary"]) 108 | { 109 | return LNPropertyListNodeTypeDictionary; 110 | } 111 | if([str isEqualToString:@"String"]) 112 | { 113 | return LNPropertyListNodeTypeString; 114 | } 115 | if([str isEqualToString:@"Date"]) 116 | { 117 | return LNPropertyListNodeTypeDate; 118 | } 119 | if([str isEqualToString:@"Data"]) 120 | { 121 | return LNPropertyListNodeTypeData; 122 | } 123 | if([str isEqualToString:@"Boolean"]) 124 | { 125 | return LNPropertyListNodeTypeBoolean; 126 | } 127 | if([str isEqualToString:@"Number"]) 128 | { 129 | return LNPropertyListNodeTypeNumber; 130 | } 131 | 132 | return LNPropertyListNodeTypeUnknown; 133 | } 134 | 135 | + (id)defaultValueForType:(LNPropertyListNodeType)type; 136 | { 137 | switch (type) 138 | { 139 | case LNPropertyListNodeTypeUnknown: 140 | return nil; 141 | case LNPropertyListNodeTypeArray: 142 | case LNPropertyListNodeTypeDictionary: 143 | return nil; 144 | case LNPropertyListNodeTypeBoolean: 145 | return @NO; 146 | case LNPropertyListNodeTypeDate: 147 | return [NSDate date]; 148 | case LNPropertyListNodeTypeData: 149 | return [NSData data]; 150 | case LNPropertyListNodeTypeNumber: 151 | return @0; 152 | case LNPropertyListNodeTypeString: 153 | return @""; 154 | } 155 | } 156 | 157 | + (id)convertString:(NSString*)str toObjectOfType:(LNPropertyListNodeType)type 158 | { 159 | switch (type) 160 | { 161 | case LNPropertyListNodeTypeUnknown: 162 | return nil; 163 | case LNPropertyListNodeTypeArray: 164 | return nil; 165 | case LNPropertyListNodeTypeDictionary: 166 | return nil; 167 | case LNPropertyListNodeTypeBoolean: 168 | return [str isEqualToString:@"YES"] ? @YES : @NO; 169 | case LNPropertyListNodeTypeDate: 170 | return nil; 171 | case LNPropertyListNodeTypeData: 172 | return nil; 173 | case LNPropertyListNodeTypeNumber: 174 | return [LNPropertyListNode._numberFormatter numberFromString:str]; 175 | case LNPropertyListNodeTypeString: 176 | return str; 177 | } 178 | } 179 | 180 | + (NSString*)stringValueOfNode:(LNPropertyListNode*)node 181 | { 182 | id valueToTranslate = node._cachedDisplayValue ?: node.value; 183 | NSArray* childrenToTranslate = [node._cachedDisplayValue isKindOfClass:[NSArray class]] ? node._cachedDisplayValue : [node._cachedDisplayValue isKindOfClass:[NSDictionary class]] ? [node._cachedDisplayValue allKeys] : node.children; 184 | LNPropertyListNodeType typeToTranslate = node._cachedDisplayValue ? [self _typeForObject:node._cachedDisplayValue] : node.type; 185 | 186 | switch (typeToTranslate) 187 | { 188 | case LNPropertyListNodeTypeUnknown: 189 | return nil; 190 | case LNPropertyListNodeTypeArray: 191 | case LNPropertyListNodeTypeDictionary: 192 | return [NSString stringWithFormat:NSLocalizedString(@"(%lu items)", @""), childrenToTranslate.count]; 193 | case LNPropertyListNodeTypeBoolean: 194 | return [valueToTranslate boolValue] ? @"YES" : @"NO"; 195 | case LNPropertyListNodeTypeDate: 196 | return nil; 197 | case LNPropertyListNodeTypeData: 198 | return [NSByteCountFormatter stringFromByteCount:[valueToTranslate length] countStyle:NSByteCountFormatterCountStyleMemory]; 199 | // return [valueToTranslate description]; 200 | case LNPropertyListNodeTypeNumber: 201 | return [LNPropertyListNode._numberFormatter stringFromNumber:valueToTranslate]; 202 | case LNPropertyListNodeTypeString: 203 | return valueToTranslate; 204 | } 205 | } 206 | 207 | + (NSString*)stringKeyOfNode:(LNPropertyListNode*)node 208 | { 209 | switch (node.parent.type) 210 | { 211 | case LNPropertyListNodeTypeArray: 212 | return [NSString stringWithFormat:NSLocalizedString(@"Item %lu", @""), [node.parent.children indexOfObject:node]]; 213 | default: 214 | return node.key; 215 | } 216 | } 217 | 218 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 219 | { 220 | self = [super init]; 221 | 222 | if(self) 223 | { 224 | self.key = [aDecoder decodeObjectForKey:@"key"]; 225 | self.type = [[aDecoder decodeObjectForKey:@"type"] unsignedIntegerValue]; 226 | self.value = [aDecoder decodeObjectForKey:@"value"]; 227 | self.children = [aDecoder decodeObjectForKey:@"children"]; 228 | 229 | [self.children enumerateObjectsUsingBlock:^(LNPropertyListNode * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 230 | obj.parent = self; 231 | }]; 232 | } 233 | 234 | return self; 235 | } 236 | 237 | - (instancetype)initWithDictionary:(NSDictionary*)dictionary 238 | { 239 | self = [super init]; 240 | 241 | if(self) 242 | { 243 | [self _setAsDictionary:dictionary]; 244 | } 245 | 246 | return self; 247 | } 248 | 249 | - (void)_setAsDictionary:(NSDictionary*)dictionary 250 | { 251 | self.type = LNPropertyListNodeTypeDictionary; 252 | self.children = [NSMutableArray new]; 253 | 254 | [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { 255 | LNPropertyListNode* childNode = [[LNPropertyListNode alloc] initWithObject:obj]; 256 | childNode.key = key; 257 | childNode.parent = self; 258 | [self.children addObject:childNode]; 259 | }]; 260 | } 261 | 262 | - (instancetype)initWithArray:(NSArray*)array 263 | { 264 | self = [super init]; 265 | 266 | if(self) 267 | { 268 | [self _setAsArray:array]; 269 | } 270 | 271 | return self; 272 | } 273 | 274 | - (void)_setAsArray:(NSArray*)array 275 | { 276 | self.type = LNPropertyListNodeTypeArray; 277 | self.children = [NSMutableArray new]; 278 | 279 | [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 280 | LNPropertyListNode* childNode = [[LNPropertyListNode alloc] initWithObject:obj]; 281 | childNode.parent = self; 282 | [self.children addObject:childNode]; 283 | }]; 284 | } 285 | 286 | - (instancetype)initWithObject:(id)obj 287 | { 288 | if(obj == nil) 289 | { 290 | return nil; 291 | } 292 | 293 | self = [super init]; 294 | 295 | if(self) 296 | { 297 | [self _setObject:obj]; 298 | } 299 | 300 | return self; 301 | } 302 | 303 | - (void)_setObject:(id)obj 304 | { 305 | if(obj == nil) 306 | { 307 | return; 308 | } 309 | 310 | LNPropertyListNodeType type = [LNPropertyListNode _typeForObject:obj]; 311 | 312 | if(type == LNPropertyListNodeTypeDictionary) 313 | { 314 | [self _setAsDictionary:obj]; 315 | } 316 | else if(type == LNPropertyListNodeTypeArray) 317 | { 318 | [self _setAsArray:obj]; 319 | } 320 | else 321 | { 322 | self.type = type; 323 | self.value = obj; 324 | } 325 | } 326 | 327 | - (instancetype)initWithPropertyListObject:(id)obj 328 | { 329 | return [self initWithObject:obj]; 330 | } 331 | 332 | - (void)encodeWithCoder:(NSCoder *)aCoder 333 | { 334 | [aCoder encodeObject:self.key forKey:@"key"]; 335 | [aCoder encodeObject:@(self.type) forKey:@"type"]; 336 | [aCoder encodeObject:self.value forKey:@"value"]; 337 | [aCoder encodeObject:self.children forKey:@"children"]; 338 | } 339 | 340 | - (LNPropertyListNodeType)_appropriateType 341 | { 342 | return self._cachedDisplayValue ? [LNPropertyListNode _typeForObject:self._cachedDisplayValue] : self.type; 343 | } 344 | 345 | - (NSString *)description 346 | { 347 | NSMutableString* builder = [NSMutableString stringWithFormat:@"<%@ %p", self.className, self]; 348 | 349 | if(self.key != nil) 350 | { 351 | [builder appendFormat:@" key: “%@”", self.key]; 352 | } 353 | 354 | [builder appendFormat:@" type: “%@”", [LNPropertyListNode stringForType:self.type]]; 355 | 356 | if(self.type == LNPropertyListNodeTypeDictionary || self.type == LNPropertyListNodeTypeArray) 357 | { 358 | [builder appendFormat:@" children: “%lu items”", self.children.count]; 359 | } 360 | else 361 | { 362 | [builder appendFormat:@" value: “%@”", [self.value description]]; 363 | } 364 | 365 | [builder appendString:@">"]; 366 | 367 | return builder; 368 | } 369 | 370 | - (NSDictionary*)_dictionaryObject 371 | { 372 | NSMutableDictionary* rv = [NSMutableDictionary new]; 373 | 374 | [self.children enumerateObjectsUsingBlock:^(LNPropertyListNode * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 375 | rv[obj.key] = obj.propertyListObject; 376 | }]; 377 | 378 | return rv.copy; 379 | } 380 | 381 | - (NSArray*)_arrayObject 382 | { 383 | NSMutableArray* rv = [NSMutableArray new]; 384 | 385 | [self.children enumerateObjectsUsingBlock:^(LNPropertyListNode * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 386 | [rv addObject:obj.propertyListObject]; 387 | }]; 388 | 389 | return rv.copy; 390 | } 391 | 392 | - (id)propertyListObject 393 | { 394 | if(self.type == LNPropertyListNodeTypeDictionary) 395 | { 396 | return self._dictionaryObject; 397 | } 398 | if(self.type == LNPropertyListNodeTypeArray) 399 | { 400 | return self._arrayObject; 401 | } 402 | 403 | return self.value; 404 | } 405 | 406 | - (LNPropertyListNode*)childNodeContainingDescendantNode:(LNPropertyListNode*)descendantNode; 407 | { 408 | LNPropertyListNode* parent = descendantNode; 409 | 410 | while(parent != nil && [self.children containsObject:parent] == NO) 411 | { 412 | parent = parent.parent; 413 | } 414 | 415 | return parent; 416 | } 417 | 418 | - (LNPropertyListNode*)childNodeForKey:(NSString*)key 419 | { 420 | return [self.children filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"key == %@", key]].firstObject; 421 | } 422 | 423 | - (void)_sortUsingDescriptors:(NSArray *)descriptors validator:(BOOL (^)(LNPropertyListNode*))validator callback:(void (^)(LNPropertyListNode*, BOOL))callback 424 | { 425 | if(self.type != LNPropertyListNodeTypeDictionary && self.type != LNPropertyListNodeTypeArray) 426 | { 427 | return; 428 | } 429 | 430 | if(validator(self) == NO) 431 | { 432 | return; 433 | } 434 | 435 | callback(self, YES); 436 | [self.children sortUsingDescriptors:descriptors]; 437 | 438 | [self.children enumerateObjectsUsingBlock:^(LNPropertyListNode * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 439 | [obj _sortUsingDescriptors:descriptors validator:validator callback:callback]; 440 | }]; 441 | callback(self, NO); 442 | } 443 | 444 | - (id)pasteboardWriter 445 | { 446 | return [[LNPropertyListNodePasteboardWriter alloc] initWithNode:self]; 447 | } 448 | 449 | + (void)_clearPasteboardMapping 450 | { 451 | [_pasteboardNodeMapping removeAllObjects]; 452 | } 453 | 454 | + (instancetype)_nodeFromPasteboard:(NSPasteboard *)pasteboard 455 | { 456 | NSPasteboardType type = LNPropertyListNodePasteboardType; 457 | NSData* data = [pasteboard dataForType:type]; 458 | BOOL needsValueReading = NO; 459 | if(data == nil) 460 | { 461 | type = LNPropertyListNodeXcodeKeyType; 462 | data = [pasteboard dataForType:type]; 463 | needsValueReading = YES; 464 | } 465 | 466 | LNPropertyListNode* rv = [[LNPropertyListNode alloc] initWithPasteboardPropertyList:data ofType:type]; 467 | 468 | if(needsValueReading) 469 | { 470 | id obj = [NSPropertyListSerialization propertyListWithData:[pasteboard dataForType:NSPasteboardTypeString] options:0 format:nil error:NULL]; 471 | [rv _setObject:obj]; 472 | } 473 | 474 | return rv; 475 | } 476 | 477 | #pragma mark NSCopying 478 | 479 | - (id)copyWithZone:(NSZone *)zone 480 | { 481 | LNPropertyListNode* rv = [LNPropertyListNode new]; 482 | rv.key = self.key; 483 | rv.type = self.type; 484 | rv.value = self.value; 485 | rv.children = self.children.mutableCopy; 486 | 487 | return rv; 488 | } 489 | 490 | #pragma mark NSPasteboardReading 491 | 492 | + (nonnull NSArray *)readableTypesForPasteboard:(nonnull NSPasteboard *)pasteboard 493 | { 494 | return @[LNPropertyListNodePasteboardType, LNPropertyListNodeXcodeKeyType]; 495 | } 496 | 497 | - (nullable instancetype)initWithPasteboardPropertyList:(NSData*)propertyList ofType:(NSPasteboardType)type 498 | { 499 | LNPropertyListNode* rv = nil; 500 | 501 | if([type isEqualToString:LNPropertyListNodePasteboardType]) 502 | { 503 | NSDictionary* info = [NSPropertyListSerialization propertyListWithData:propertyList options:0 format:nil error:NULL]; 504 | NSString* UDIDString = info[@"UDID"]; 505 | rv = [_pasteboardNodeMapping objectForKey:UDIDString]; 506 | 507 | if(rv == nil) 508 | { 509 | NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:info[@"data"] error:NULL]; 510 | unarchiver.requiresSecureCoding = NO; 511 | 512 | rv = [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey]; 513 | } 514 | } 515 | 516 | if([type isEqualToString:LNPropertyListNodeXcodeKeyType]) 517 | { 518 | rv = [LNPropertyListNode new]; 519 | rv.key = [NSPropertyListSerialization propertyListWithData:propertyList options:0 format:nil error:NULL]; 520 | } 521 | 522 | return rv; 523 | } 524 | 525 | @end 526 | 527 | #pragma mark NSPasteboardWriting 528 | 529 | @implementation LNPropertyListNodePasteboardWriter 530 | { 531 | LNPropertyListNode* _node; 532 | NSMutableArray* _UUIDs; 533 | } 534 | 535 | - (instancetype)initWithNode:(LNPropertyListNode*)node 536 | { 537 | self = [super init]; 538 | 539 | if(self) 540 | { 541 | _UUIDs = [NSMutableArray new]; 542 | _node = node; 543 | } 544 | 545 | return self; 546 | } 547 | 548 | - (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard 549 | { 550 | return @[LNPropertyListNodePasteboardType, LNPropertyListNodeXcodeKeyType, NS(kUTTypeUTF8PlainText)]; 551 | } 552 | 553 | - (id)pasteboardPropertyListForType:(NSPasteboardType)type 554 | { 555 | if([type isEqualToString:LNPropertyListNodePasteboardType]) 556 | { 557 | NSString* UUIDString = NSUUID.UUID.UUIDString; 558 | 559 | [_UUIDs addObject:UUIDString]; 560 | [_pasteboardNodeMapping setObject:_node forKey:UUIDString]; 561 | 562 | return [NSPropertyListSerialization dataWithPropertyList:@{ 563 | @"UDID": UUIDString, 564 | @"data": [NSKeyedArchiver archivedDataWithRootObject:_node requiringSecureCoding:NO error:NULL] 565 | } format:NSPropertyListXMLFormat_v1_0 options:0 error:NULL]; 566 | } 567 | 568 | if([type isEqualToString:NS(kUTTypeUTF8PlainText)]) 569 | { 570 | NSError* error = nil; 571 | return [NSPropertyListSerialization dataWithPropertyList:_node.propertyListObject format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]; 572 | } 573 | 574 | if([type isEqualToString:LNPropertyListNodeXcodeKeyType]) 575 | { 576 | return [_node.key dataUsingEncoding:NSUTF8StringEncoding]; 577 | } 578 | 579 | return nil; 580 | } 581 | 582 | @end 583 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListOutlineView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListOutlineView.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/16/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LNPropertyListOutlineView : NSOutlineView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListOutlineView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListOutlineView.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/16/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListOutlineView.h" 10 | 11 | @implementation LNPropertyListOutlineView 12 | 13 | - (void)awakeFromNib 14 | { 15 | [super awakeFromNib]; 16 | 17 | self.enclosingScrollView.wantsLayer = YES; 18 | self.enclosingScrollView.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; 19 | } 20 | 21 | - (void)drawGridInClipRect:(NSRect)clipRect 22 | { 23 | NSRect lastRowRect = [self rectOfRow:[self numberOfRows] - 1]; 24 | NSRect myClipRect = NSMakeRect(0, 0, lastRowRect.size.width, NSMaxY(lastRowRect)); 25 | NSRect finalClipRect = NSIntersectionRect(clipRect, myClipRect); 26 | [super drawGridInClipRect:finalClipRect]; 27 | } 28 | 29 | - (void)layout 30 | { 31 | [super layout]; 32 | 33 | if((self.tableColumns.lastObject.resizingMask & NSTableColumnAutoresizingMask) == NSTableColumnAutoresizingMask) 34 | { 35 | [self sizeLastColumnToFit]; 36 | } 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListPopUpButtonCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListPopUpButtonCell.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/26/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LNPropertyListPopUpButtonCell : NSPopUpButtonCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListPopUpButtonCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListPopUpButtonCell.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/26/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListPopUpButtonCell.h" 10 | 11 | static NSColor* __enabledTextColor; 12 | static NSColor* __enabledTextColorHighlight; 13 | static NSColor* __disabledTextColor; 14 | static NSColor* __disabledTextColorHighlight; 15 | static NSAppearance* __darkAppearanceCache; 16 | 17 | @implementation LNPropertyListPopUpButtonCell 18 | 19 | + (void)load 20 | { 21 | __enabledTextColor = NSColor.controlTextColor; 22 | __enabledTextColorHighlight = NSColor.alternateSelectedControlTextColor; 23 | __disabledTextColor = NSColor.disabledControlTextColor; 24 | __disabledTextColorHighlight = [NSColor valueForKey:@"_alternateDisabledSelectedControlTextColor"]; 25 | __darkAppearanceCache = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]; 26 | } 27 | 28 | - (NSRect)drawTitle:(NSAttributedString *)title withFrame:(NSRect)frame inView:(NSView *)controlView 29 | { 30 | BOOL isHighlited = self.backgroundStyle == NSBackgroundStyleEmphasized; 31 | //All this to get the damn colors to match a text field. Ridiculous 32 | NSColor* controlColor = self.isEnabled ? (isHighlited ? __enabledTextColorHighlight : (controlView.effectiveAppearance == __darkAppearanceCache ? NSColor.whiteColor : __enabledTextColor)) : (isHighlited ? __disabledTextColorHighlight : __disabledTextColor); 33 | NSMutableAttributedString* attr = self.attributedTitle.mutableCopy; 34 | [attr addAttribute:NSForegroundColorAttributeName value:controlColor range:NSMakeRange(0, attr.length)]; 35 | 36 | [attr drawInRect:frame]; 37 | 38 | return frame; 39 | } 40 | 41 | - (BOOL)trackMouse:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag 42 | { 43 | if(NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11) 44 | { 45 | [self.controlView.window makeFirstResponder:self.controlView.superview]; 46 | } 47 | 48 | return [super trackMouse:event inRect:cellFrame ofView:controlView untilMouseUp:flag]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListRowView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListRowView.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/16/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LNPropertyListEditor-Private.h" 11 | #import "LNPropertyListNode.h" 12 | 13 | @interface LNPropertyListRowView : NSTableRowView 14 | 15 | @property (nonatomic, weak) LNPropertyListEditor* editor; 16 | @property (nonatomic, strong) LNPropertyListNode* node; 17 | 18 | - (void)updateEditButtons; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/LNPropertyListRowView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListRowView.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/16/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "LNPropertyListRowView.h" 10 | #import "LNPropertyListCellView.h" 11 | 12 | @implementation LNPropertyListRowView 13 | { 14 | BOOL _mouseIn; 15 | NSTrackingArea* _trackingArea; 16 | } 17 | 18 | - (void)awakeFromNib 19 | { 20 | [super awakeFromNib]; 21 | 22 | self.wantsLayer = YES; 23 | self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; 24 | self.canDrawSubviewsIntoLayer = YES; 25 | self.layer.borderWidth = 2.0; 26 | self.layer.borderColor = NSColor.clearColor.CGColor; 27 | } 28 | 29 | - (void)updateEditButtons; 30 | { 31 | if(self.subviews.count > 0) 32 | { 33 | LNPropertyListCellView* cellView = [self viewAtColumn:0]; 34 | 35 | BOOL addButtonEnabled = [self.editor canInsertAtNode:self.node]; 36 | BOOL deleteButtonEnabled = [self.editor canDeleteNode:self.node]; 37 | 38 | [cellView setShowsControlButtons:self.selected || _mouseIn addButtonEnabled:addButtonEnabled deleteButtonEnabled:deleteButtonEnabled]; 39 | } 40 | } 41 | 42 | - (void)setSelected:(BOOL)selected 43 | { 44 | [super setSelected:selected]; 45 | 46 | [self updateEditButtons]; 47 | } 48 | 49 | - (void)ensureTrackingArea 50 | { 51 | if (_trackingArea == nil) 52 | { 53 | _trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:NSTrackingInVisibleRect | NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited owner:self userInfo:nil]; 54 | } 55 | } 56 | 57 | - (void)updateTrackingAreas 58 | { 59 | [super updateTrackingAreas]; 60 | [self ensureTrackingArea]; 61 | 62 | if ([[self trackingAreas] containsObject:_trackingArea] == NO) 63 | { 64 | [self addTrackingArea:_trackingArea]; 65 | } 66 | } 67 | 68 | - (void)mouseEntered:(NSEvent *)event 69 | { 70 | _mouseIn = YES; 71 | 72 | [self updateEditButtons]; 73 | } 74 | 75 | - (void)mouseExited:(NSEvent *)event 76 | { 77 | _mouseIn = NO; 78 | 79 | [self updateEditButtons]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/NSObject+LNPropertyListValueSorting.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+LNPropertyListValueSorting.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 5/5/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface NSObject (LNPropertyListValueSorting) 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/NSObject+LNPropertyListValueSorting.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+LNPropertyListValueSorting.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 5/5/21. 6 | // Copyright © 2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "NSObject+LNPropertyListValueSorting.h" 10 | #import "LNPropertyListNode-Private.h" 11 | 12 | @implementation NSObject (LNPropertyListValueSorting) 13 | 14 | - (NSString*)_ln_stringValueForComparison 15 | { 16 | if([self isKindOfClass:NSString.class]) 17 | { 18 | return (NSString*)self; 19 | } 20 | else if([self isKindOfClass:NSClassFromString(@"__NSCFBoolean")]) 21 | { 22 | return [(NSNumber*)self boolValue] ? @"YES" : @"NO"; 23 | } 24 | else if([self isKindOfClass:NSNumber.class]) 25 | { 26 | return [LNPropertyListNode._numberFormatter stringFromNumber:(NSNumber*)self]; 27 | } 28 | else if([self isKindOfClass:NSData.class]) 29 | { 30 | return @""; 31 | } 32 | else if([self isKindOfClass:NSDate.class]) 33 | { 34 | return [NSDateFormatter localizedStringFromDate:(NSDate*)self dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]; 35 | } 36 | 37 | return @""; 38 | } 39 | 40 | 41 | - (NSComparisonResult)_ln_compareValue:(NSObject*)other 42 | { 43 | return [[self _ln_stringValueForComparison] localizedCaseInsensitiveCompare:[other _ln_stringValueForComparison]]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/_LNPropertyListDatePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPropertyListDatePicker.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 9/11/19. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class LNPropertyListDatePickerPanel; 12 | 13 | @interface _LNPropertyListDatePicker : NSDatePicker 14 | 15 | @property (nonatomic, strong) NSDatePicker* visualDatePicker; 16 | @property (nonatomic, strong) NSDatePicker* textDatePicker; 17 | @property (nonatomic, strong) LNPropertyListDatePickerPanel* datePickerPanel; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Implementation/_LNPropertyListDatePicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // _LNPropertyListDatePicker.m 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 9/11/19. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "_LNPropertyListDatePicker.h" 10 | #import "LNPropertyListDatePickerCell.h" 11 | #import "LNPropertyListDatePickerPanel.h" 12 | 13 | @interface NSView () 14 | 15 | - (void)geometryInWindowDidChange; 16 | 17 | @end 18 | 19 | @interface _LNForwardingDatePicker : NSDatePicker 20 | @property (nonatomic, weak) NSResponder* expectedNextResponder; 21 | @end 22 | @implementation _LNForwardingDatePicker 23 | 24 | - (NSResponder *)nextResponder 25 | { 26 | return _expectedNextResponder; 27 | } 28 | 29 | @end 30 | 31 | @interface _LNPropertyListDatePicker () @end 32 | 33 | @implementation _LNPropertyListDatePicker 34 | 35 | - (instancetype)init 36 | { 37 | self = [super init]; 38 | 39 | if(self) 40 | { 41 | _visualDatePicker = [NSDatePicker new]; 42 | _visualDatePicker.translatesAutoresizingMaskIntoConstraints = NO; 43 | _visualDatePicker.datePickerStyle = NSDatePickerStyleClockAndCalendar; 44 | _visualDatePicker.datePickerElements = NSDatePickerElementFlagTimeZone | NSDatePickerElementFlagHourMinuteSecond | NSDatePickerElementFlagYearMonthDay | NSDatePickerElementFlagEra; 45 | _visualDatePicker.bordered = NO; 46 | 47 | _LNForwardingDatePicker* forwardingPicker = [_LNForwardingDatePicker new]; 48 | forwardingPicker.expectedNextResponder = self.nextResponder; 49 | _textDatePicker = forwardingPicker; 50 | _textDatePicker.translatesAutoresizingMaskIntoConstraints = NO; 51 | _textDatePicker.cell = [LNLeadingZerosDatePickerCell new]; 52 | _textDatePicker.bordered = NO; 53 | 54 | NSViewController* vc = [NSViewController new]; 55 | LNPropertyListDatePickerPanelBackgroundView* view = [LNPropertyListDatePickerPanelBackgroundView new]; 56 | view.textDatePicker = _textDatePicker; 57 | view.visualDatePicker = _visualDatePicker; 58 | vc.view = view; 59 | [vc.view addSubview:_visualDatePicker]; 60 | [vc.view addSubview:_textDatePicker]; 61 | 62 | [NSLayoutConstraint activateConstraints:@[ 63 | [vc.view.leadingAnchor constraintEqualToAnchor:_textDatePicker.leadingAnchor], 64 | [vc.view.topAnchor constraintEqualToAnchor:_textDatePicker.topAnchor], 65 | [_textDatePicker.bottomAnchor constraintEqualToAnchor:_visualDatePicker.topAnchor], 66 | [vc.view.leadingAnchor constraintEqualToAnchor:_visualDatePicker.leadingAnchor], 67 | [vc.view.trailingAnchor constraintEqualToAnchor:_visualDatePicker.trailingAnchor], 68 | [vc.view.bottomAnchor constraintEqualToAnchor:_visualDatePicker.bottomAnchor], 69 | ]]; 70 | 71 | _datePickerPanel = [LNPropertyListDatePickerPanel new]; 72 | _datePickerPanel.contentViewController = vc; 73 | _datePickerPanel.datePickerPanelDelegate = self; 74 | } 75 | 76 | return self; 77 | } 78 | 79 | - (BOOL)becomeFirstResponder 80 | { 81 | _visualDatePicker.dateValue = self.dateValue; 82 | _visualDatePicker.target = self.target; 83 | _visualDatePicker.action = self.action; 84 | [_visualDatePicker sizeToFit]; 85 | 86 | _textDatePicker.font = self.font; 87 | _textDatePicker.datePickerStyle = self.datePickerStyle; 88 | _textDatePicker.datePickerElements = self.datePickerElements; 89 | _textDatePicker.dateValue = self.dateValue; 90 | _textDatePicker.target = self.target; 91 | _textDatePicker.action = self.action; 92 | [_textDatePicker sizeToFit]; 93 | 94 | [self.window addChildWindow:_datePickerPanel ordered:NSWindowAbove]; 95 | [self _repositionPanel]; 96 | 97 | BOOL rv = [super becomeFirstResponder]; 98 | 99 | [_datePickerPanel makeKeyWindow]; 100 | [_textDatePicker becomeFirstResponder]; 101 | if(NSApp.currentEvent.type == NSEventTypeLeftMouseDown || NSApp.currentEvent.type == NSEventTypeLeftMouseUp) 102 | { 103 | [_textDatePicker.cell _textFieldWithStepperTrackMouse:NSApp.currentEvent inRect:self.bounds ofView:self untilMouseUp:YES]; 104 | } 105 | 106 | return rv; 107 | } 108 | 109 | - (void)_repositionPanel 110 | { 111 | if(_datePickerPanel == nil) 112 | { 113 | return; 114 | } 115 | 116 | NSScrollView* scrollView = self.enclosingScrollView; 117 | NSRect selfInScrollView = [scrollView convertRect:self.bounds fromView:self]; 118 | if(selfInScrollView.origin.y < [scrollView.documentView headerView].frame.size.height || 119 | selfInScrollView.origin.y + selfInScrollView.size.height > scrollView.frame.size.height) 120 | { 121 | [_datePickerPanel close]; 122 | } 123 | 124 | NSRect positionInScreen = [self.window convertRectToScreen:[self convertRect:self.bounds toView:nil]]; 125 | NSRect frame = _datePickerPanel.frame; 126 | frame.origin = NSMakePoint(positionInScreen.origin.x, positionInScreen.origin.y - frame.size.height + self.bounds.size.height); 127 | [_datePickerPanel setFrame:frame display:YES]; 128 | } 129 | 130 | - (void)geometryInWindowDidChange 131 | { 132 | [super geometryInWindowDidChange]; 133 | 134 | [self _repositionPanel]; 135 | } 136 | 137 | - (BOOL)resignFirstResponder 138 | { 139 | [self.window removeChildWindow:_datePickerPanel]; 140 | [_datePickerPanel close]; 141 | return [super resignFirstResponder]; 142 | } 143 | 144 | - (void)propertyListDatePickerPanelDidClose:(LNPropertyListDatePickerPanel*)panel 145 | { 146 | [self.window makeKeyWindow]; 147 | [self.window makeFirstResponder:self.superview]; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.5 19 | CFBundleVersion 20 | 1 21 | NSHumanReadableCopyright 22 | Copyright © 2018-2022 Leo Natan. All rights reserved. 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/LNPropertyListEditor.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListEditor.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #define LN_DEPRECATED_API(x) __attribute__((deprecated(x))) 13 | 14 | typedef NS_ENUM(NSUInteger, LNPropertyListNodeChangeType) { 15 | /// Specifies that a node was inserted. 16 | LNPropertyListNodeChangeTypeInsert, 17 | /// Specifies that a node was deleted. 18 | LNPropertyListNodeChangeTypeDelete, 19 | /// Specifies that a node was moved. 20 | LNPropertyListNodeChangeTypeMove, 21 | /// Specifies that an object was updated. 22 | LNPropertyListNodeChangeTypeUpdate, 23 | 24 | LNPropertyListNodeChangeTypeReorderChildren LN_DEPRECATED_API("Use LNPropertyListNodeChangeType.update instead.") = LNPropertyListNodeChangeTypeUpdate, 25 | }; 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @class LNPropertyListEditor; 30 | 31 | @protocol LNPropertyListEditorDelegate 32 | 33 | @optional 34 | 35 | /// Notifies the delegate that a node is about to change. 36 | /// @param editor The property list editor. 37 | /// @param node The node that will change. 38 | /// @param changeType The change type. 39 | /// @param previousKey The previous key, in case the key property has been updated. 40 | - (void)propertyListEditor:(LNPropertyListEditor *)editor willChangeNode:(LNPropertyListNode *)node changeType:(LNPropertyListNodeChangeType)changeType previousKey:(nullable NSString *)previousKey; 41 | 42 | /// Notifies the delegate that a node has changed. 43 | /// @param editor The property list editor. 44 | /// @param node The node that has changed. 45 | /// @param changeType The change type. 46 | /// @param previousKey The previous key, in case the key property has been updated. 47 | - (void)propertyListEditor:(LNPropertyListEditor *)editor didChangeNode:(LNPropertyListNode *)node changeType:(LNPropertyListNodeChangeType)changeType previousKey:(nullable NSString *)previousKey; 48 | 49 | /// Asks the delegate if the key of the specified node can be edited. 50 | /// @param editor The property list editor. 51 | /// @param node The current node. 52 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canEditKeyOfNode:(LNPropertyListNode*)node; 53 | 54 | /// Asks the delegate if the type of the specified node can be edited. 55 | /// @param editor The property list editor. 56 | /// @param node The current node. 57 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canEditTypeOfNode:(LNPropertyListNode*)node; 58 | 59 | /// Asks the delegate if the value of the specified node can be edited. 60 | /// @param editor The property list editor. 61 | /// @param node The current node. 62 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canEditValueOfNode:(LNPropertyListNode*)node; 63 | 64 | /// Asks the delegate if the specified node can be deleted. 65 | /// @param editor The property list editor. 66 | /// @param node The current node. 67 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canDeleteNode:(LNPropertyListNode*)node; 68 | 69 | /// Asks the delegate if it is possible to add a child node in the specified node. 70 | /// @param editor The property list editor. 71 | /// @param node The current node. 72 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canAddChildNodeInNode:(LNPropertyListNode*)node; 73 | 74 | /// Asks the delegate if it is possible to reorder the children of the specified node. 75 | /// @param editor The property list editor. 76 | /// @param node The current node. 77 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canReorderChildrenOfNode:(LNPropertyListNode*)node; 78 | 79 | /// Asks the delegate if the specified pasted node can be added as a child node of the specified node. 80 | /// @param editor The property list editor. 81 | /// @param pastedNode The pasted node. 82 | /// @param node The current node. 83 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canPasteNode:(LNPropertyListNode*)pastedNode asChildOfNode:(LNPropertyListNode*)node; 84 | 85 | /// Asks the delegate if the specified node can be moved as a child node of the specified node, at the specified index. 86 | /// @param editor The property list editor. 87 | /// @param movedNode The pasted node. 88 | /// @param parentNode The current node. 89 | /// @param index The index to paste at. 90 | - (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canMoveNode:(LNPropertyListNode*)movedNode toParentNode:(LNPropertyListNode*)parentNode atIndex:(NSInteger)index; 91 | 92 | /// Asks the delegate for a default value for a child node in the specified node. 93 | /// @param editor The property list editor. 94 | /// @param node The current node. 95 | /// 96 | /// This can be either a valid property list or an LNPropertyListNode object. 97 | - (nullable id)propertyListEditor:(LNPropertyListEditor *)editor defaultPropertyListForChildInNode:(LNPropertyListNode*)node; 98 | 99 | @end 100 | 101 | @protocol LNPropertyListEditorDataTransformer 102 | 103 | @optional 104 | 105 | /// Provides a display name for the specified node. 106 | /// @param editor The property list editor. 107 | /// @param node The current node. 108 | - (nullable NSString*)propertyListEditor:(LNPropertyListEditor *)editor displayNameForNode:(LNPropertyListNode*)node; 109 | 110 | /// Provides a display value for the specified node. 111 | /// @param editor The property list editor. 112 | /// @param node The current node. 113 | /// 114 | /// This can be either a valid property list or an LNPropertyListNode object. 115 | - (nullable id)propertyListEditor:(LNPropertyListEditor *)editor displayValueForNode:(LNPropertyListNode*)node; 116 | 117 | /// Provides a storage value for the specified node and display value 118 | /// @param editor The property list editor. 119 | /// @param node The current node. 120 | /// @param displayValue The current display value of the specified node. 121 | - (nullable id)propertyListEditor:(LNPropertyListEditor *)editor storageValueForNode:(LNPropertyListNode*)node displayValue:(id)displayValue; 122 | 123 | @end 124 | 125 | IB_DESIGNABLE 126 | @interface LNPropertyListEditor : NSView 127 | 128 | /// The underlying edited property list object. 129 | /// 130 | /// Setting this property with @c allowsColumnSorting enabled will result in the model being sorted by keys on load. 131 | @property (nonatomic, copy) id propertyListObject; 132 | 133 | /// Sets the type column as hidden. 134 | @property (nonatomic, getter=isTypeColumnHidden) BOOL typeColumnHidden; 135 | 136 | /// Controls whether column sorting is enabled. 137 | /// 138 | /// Sorting a column by the user will result in nodes being sorted in the model. 139 | @property (nonatomic) BOOL allowsColumnSorting; 140 | 141 | /// The root node of the edited property list. 142 | @property (nonatomic, readonly) LNPropertyListNode* rootPropertyListNode; 143 | 144 | /// Reloads the specified node and, optionally, its children. 145 | /// @param node The node to reload, or @c nil to reload the root node. 146 | /// @param reloadChildren Pass @c true to reload the node's children as well. 147 | - (void)reloadNode:(nullable LNPropertyListNode*)node reloadChildren:(BOOL)reloadChildren; 148 | /// Expands the specified node and, optionally, its children. 149 | /// @param node The node to reload, or @c nil to expand the root node. 150 | /// @param expandChildren Pass @c true to reload the node's children as well. 151 | - (void)expandNode:(nullable LNPropertyListNode*)node expandChildren:(BOOL)expandChildren; 152 | /// Collapses the specified node and, optionally, its children. 153 | /// @param node The node to reload, or @c nil to collapse the root node. 154 | /// @param collapseChildren Pass @c true to reload the node's children as well. 155 | - (void)collapseNode:(nullable LNPropertyListNode*)node collapseChildren:(BOOL)collapseChildren; 156 | 157 | /// The currently selected node, if any. 158 | @property (nonatomic, strong, readonly, nullable) LNPropertyListNode* selectedNode; 159 | 160 | /// Selects the row for the specified node, if possible. 161 | /// @param node The node to select. 162 | - (void)selectRowForNode:(LNPropertyListNode*)node; 163 | 164 | /// Scrolls the property list editor so the specified node's row is visible. 165 | /// @param node The node whose row to scroll to 166 | - (void)scrollRowForNodeToVisible:(LNPropertyListNode*)node; 167 | 168 | /// The property list editor delegate. 169 | @property (nonatomic, weak, nullable) id delegate; 170 | /// The property list editor data transformer. 171 | @property (nonatomic, weak, nullable) id dataTransformer; 172 | 173 | /// The property list editor's undo manager. 174 | /// 175 | /// Use this property only for registering as an observer of various @c NSUndoManager notifications; do not make changes to the various properties. 176 | @property (nonatomic, strong, readonly) NSUndoManager* undoManager; 177 | 178 | /// Adds a new item. 179 | - (IBAction)add:(nullable id)sender; 180 | /// Cuts the selected item. 181 | /// 182 | /// Does nothing if there is no selection. 183 | - (IBAction)cut:(nullable id)sender; 184 | /// Copies the selected item. 185 | /// 186 | /// Does nothing if there is no selection. 187 | - (IBAction)copy:(nullable id)sender; 188 | /// Pastes an item. 189 | - (IBAction)paste:(nullable id)sender; 190 | /// Deletes the selected item. 191 | /// 192 | /// Does nothing if there is no selection. 193 | - (IBAction)delete:(nullable id)sender; 194 | /// Converts the selected item to boolean type. 195 | /// 196 | /// Does nothing if there is no selection. 197 | - (IBAction)boolean:(nullable id)sender; 198 | /// Converts the selected item to number type. 199 | /// 200 | /// Does nothing if there is no selection. 201 | - (IBAction)number:(nullable id)sender; 202 | /// Converts the selected item to string type. 203 | /// 204 | /// Does nothing if there is no selection. 205 | - (IBAction)string:(nullable id)sender; 206 | /// Converts the selected item to date type. 207 | /// 208 | /// Does nothing if there is no selection. 209 | - (IBAction)date:(nullable id)sender; 210 | /// Converts the selected item to data type. 211 | /// 212 | /// Does nothing if there is no selection. 213 | - (IBAction)data:(nullable id)sender; 214 | /// Converts the selected item to array type. 215 | /// 216 | /// Does nothing if there is no selection. 217 | - (IBAction)array:(nullable id)sender; 218 | /// Converts the selected item to dictionary type. 219 | /// 220 | /// Does nothing if there is no selection. 221 | - (IBAction)dictionary:(nullable id)sender; 222 | 223 | @end 224 | 225 | NS_ASSUME_NONNULL_END 226 | -------------------------------------------------------------------------------- /LNPropertyListEditor/LNPropertyListEditor/LNPropertyListNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // LNPropertyListNode.h 3 | // LNPropertyListEditor 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | 8 | // 9 | 10 | #import 11 | 12 | typedef NS_ENUM(NSUInteger, LNPropertyListNodeType) { 13 | LNPropertyListNodeTypeUnknown, 14 | 15 | LNPropertyListNodeTypeArray, 16 | LNPropertyListNodeTypeDictionary, 17 | LNPropertyListNodeTypeBoolean, 18 | LNPropertyListNodeTypeDate, 19 | LNPropertyListNodeTypeData, 20 | LNPropertyListNodeTypeNumber, 21 | LNPropertyListNodeTypeString, 22 | }; 23 | 24 | NS_ASSUME_NONNULL_BEGIN 25 | 26 | @interface LNPropertyListNode : NSObject 27 | 28 | /// Returns a property list node representing the specified object. 29 | /// @param obj An object to be represented by the node. 30 | - (instancetype)initWithPropertyListObject:(id)obj; 31 | 32 | /// The key of the property list node. 33 | @property (nonatomic, strong, nullable) NSString* key; 34 | /// The type of the property list node. 35 | @property (nonatomic) LNPropertyListNodeType type; 36 | /// The value of the property list object. 37 | @property (nonatomic, strong) id value; 38 | 39 | /// The children of the property list node. 40 | @property (nonatomic, strong, nullable) NSMutableArray* children; 41 | 42 | 43 | /// Returns the child node containing the specified descendant node. 44 | /// @param descendantNode The descendant node to search for. 45 | - (nullable LNPropertyListNode*)childNodeContainingDescendantNode:(LNPropertyListNode*)descendantNode; 46 | 47 | /// Returns the child node with the specified key. 48 | /// @param key The key of the child node. 49 | - (nullable LNPropertyListNode*)childNodeForKey:(NSString*)key; 50 | 51 | /// The parent of the property list node. 52 | @property (nonatomic, weak, nullable) LNPropertyListNode* parent; 53 | 54 | /// The object, represented by the property list node. 55 | @property (nonatomic, strong, readonly) id propertyListObject; 56 | 57 | @end 58 | 59 | NS_ASSUME_NONNULL_END 60 | -------------------------------------------------------------------------------- /LNPropertyListEditor/include/LNPropertyListEditor/LNPropertyListEditor.h: -------------------------------------------------------------------------------- 1 | ../../LNPropertyListEditor/LNPropertyListEditor.h -------------------------------------------------------------------------------- /LNPropertyListEditor/include/LNPropertyListEditor/LNPropertyListNode.h: -------------------------------------------------------------------------------- 1 | ../../LNPropertyListEditor/LNPropertyListNode.h -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 39255390208444D7009C33A0 /* LNPropertyListEditor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3925538F208444CE009C33A0 /* LNPropertyListEditor.framework */; }; 11 | 39255391208444D7009C33A0 /* LNPropertyListEditor.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3925538F208444CE009C33A0 /* LNPropertyListEditor.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 12 | 393E1852207F6154002E6136 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E1851207F6154002E6136 /* AppDelegate.m */; }; 13 | 393E1855207F6154002E6136 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E1854207F6154002E6136 /* ViewController.m */; }; 14 | 393E1857207F6155002E6136 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 393E1856207F6155002E6136 /* Assets.xcassets */; }; 15 | 393E185A207F6155002E6136 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 393E1858207F6155002E6136 /* Main.storyboard */; }; 16 | 393E185D207F6155002E6136 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 393E185C207F6155002E6136 /* main.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 3925538E208444CE009C33A0 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 3925538A208444CE009C33A0 /* LNPropertyListEditor.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = 393E1839207F6119002E6136; 25 | remoteInfo = LNPropertyListEditor; 26 | }; 27 | 39255392208444D7009C33A0 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 3925538A208444CE009C33A0 /* LNPropertyListEditor.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 393E1838207F6119002E6136; 32 | remoteInfo = LNPropertyListEditor; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | 393E1870207F6170002E6136 /* Embed Frameworks */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = ""; 41 | dstSubfolderSpec = 10; 42 | files = ( 43 | 39255391208444D7009C33A0 /* LNPropertyListEditor.framework in Embed Frameworks */, 44 | ); 45 | name = "Embed Frameworks"; 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXCopyFilesBuildPhase section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | 3925538A208444CE009C33A0 /* LNPropertyListEditor.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LNPropertyListEditor.xcodeproj; path = ../LNPropertyListEditor/LNPropertyListEditor.xcodeproj; sourceTree = ""; }; 52 | 393E184D207F6154002E6136 /* LNPropertyListEditorExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LNPropertyListEditorExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 393E1850207F6154002E6136 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 54 | 393E1851207F6154002E6136 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 55 | 393E1853207F6154002E6136 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 56 | 393E1854207F6154002E6136 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 57 | 393E1856207F6155002E6136 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 393E1859207F6155002E6136 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 59 | 393E185B207F6155002E6136 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 393E185C207F6155002E6136 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 393E184A207F6154002E6136 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 39255390208444D7009C33A0 /* LNPropertyListEditor.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 3925538B208444CE009C33A0 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 3925538F208444CE009C33A0 /* LNPropertyListEditor.framework */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 393E1844207F6154002E6136 = { 84 | isa = PBXGroup; 85 | children = ( 86 | 3925538A208444CE009C33A0 /* LNPropertyListEditor.xcodeproj */, 87 | 393E184F207F6154002E6136 /* LNPropertyListEditorExample */, 88 | 393E184E207F6154002E6136 /* Products */, 89 | ); 90 | sourceTree = ""; 91 | }; 92 | 393E184E207F6154002E6136 /* Products */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 393E184D207F6154002E6136 /* LNPropertyListEditorExample.app */, 96 | ); 97 | name = Products; 98 | sourceTree = ""; 99 | }; 100 | 393E184F207F6154002E6136 /* LNPropertyListEditorExample */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 393E1850207F6154002E6136 /* AppDelegate.h */, 104 | 393E1851207F6154002E6136 /* AppDelegate.m */, 105 | 393E1853207F6154002E6136 /* ViewController.h */, 106 | 393E1854207F6154002E6136 /* ViewController.m */, 107 | 393E1856207F6155002E6136 /* Assets.xcassets */, 108 | 393E1858207F6155002E6136 /* Main.storyboard */, 109 | 393E185B207F6155002E6136 /* Info.plist */, 110 | 393E185C207F6155002E6136 /* main.m */, 111 | ); 112 | path = LNPropertyListEditorExample; 113 | sourceTree = ""; 114 | }; 115 | /* End PBXGroup section */ 116 | 117 | /* Begin PBXNativeTarget section */ 118 | 393E184C207F6154002E6136 /* LNPropertyListEditorExample */ = { 119 | isa = PBXNativeTarget; 120 | buildConfigurationList = 393E1861207F6155002E6136 /* Build configuration list for PBXNativeTarget "LNPropertyListEditorExample" */; 121 | buildPhases = ( 122 | 393E1849207F6154002E6136 /* Sources */, 123 | 393E184A207F6154002E6136 /* Frameworks */, 124 | 393E184B207F6154002E6136 /* Resources */, 125 | 393E1870207F6170002E6136 /* Embed Frameworks */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | 39255393208444D7009C33A0 /* PBXTargetDependency */, 131 | ); 132 | name = LNPropertyListEditorExample; 133 | productName = LNPlistEditorViewExample; 134 | productReference = 393E184D207F6154002E6136 /* LNPropertyListEditorExample.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 393E1845207F6154002E6136 /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastUpgradeCheck = 1250; 144 | ORGANIZATIONNAME = "Leo Natan"; 145 | TargetAttributes = { 146 | 393E184C207F6154002E6136 = { 147 | CreatedOnToolsVersion = 9.4; 148 | LastSwiftMigration = 1250; 149 | SystemCapabilities = { 150 | com.apple.Sandbox = { 151 | enabled = 0; 152 | }; 153 | }; 154 | }; 155 | }; 156 | }; 157 | buildConfigurationList = 393E1848207F6154002E6136 /* Build configuration list for PBXProject "LNPropertyListEditorExample" */; 158 | compatibilityVersion = "Xcode 9.3"; 159 | developmentRegion = en; 160 | hasScannedForEncodings = 0; 161 | knownRegions = ( 162 | en, 163 | Base, 164 | ); 165 | mainGroup = 393E1844207F6154002E6136; 166 | productRefGroup = 393E184E207F6154002E6136 /* Products */; 167 | projectDirPath = ""; 168 | projectReferences = ( 169 | { 170 | ProductGroup = 3925538B208444CE009C33A0 /* Products */; 171 | ProjectRef = 3925538A208444CE009C33A0 /* LNPropertyListEditor.xcodeproj */; 172 | }, 173 | ); 174 | projectRoot = ""; 175 | targets = ( 176 | 393E184C207F6154002E6136 /* LNPropertyListEditorExample */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXReferenceProxy section */ 182 | 3925538F208444CE009C33A0 /* LNPropertyListEditor.framework */ = { 183 | isa = PBXReferenceProxy; 184 | fileType = wrapper.framework; 185 | path = LNPropertyListEditor.framework; 186 | remoteRef = 3925538E208444CE009C33A0 /* PBXContainerItemProxy */; 187 | sourceTree = BUILT_PRODUCTS_DIR; 188 | }; 189 | /* End PBXReferenceProxy section */ 190 | 191 | /* Begin PBXResourcesBuildPhase section */ 192 | 393E184B207F6154002E6136 /* Resources */ = { 193 | isa = PBXResourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 393E1857207F6155002E6136 /* Assets.xcassets in Resources */, 197 | 393E185A207F6155002E6136 /* Main.storyboard in Resources */, 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXResourcesBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | 393E1849207F6154002E6136 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 393E1855207F6154002E6136 /* ViewController.m in Sources */, 209 | 393E185D207F6155002E6136 /* main.m in Sources */, 210 | 393E1852207F6154002E6136 /* AppDelegate.m in Sources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXSourcesBuildPhase section */ 215 | 216 | /* Begin PBXTargetDependency section */ 217 | 39255393208444D7009C33A0 /* PBXTargetDependency */ = { 218 | isa = PBXTargetDependency; 219 | name = LNPropertyListEditor; 220 | targetProxy = 39255392208444D7009C33A0 /* PBXContainerItemProxy */; 221 | }; 222 | /* End PBXTargetDependency section */ 223 | 224 | /* Begin PBXVariantGroup section */ 225 | 393E1858207F6155002E6136 /* Main.storyboard */ = { 226 | isa = PBXVariantGroup; 227 | children = ( 228 | 393E1859207F6155002E6136 /* Base */, 229 | ); 230 | name = Main.storyboard; 231 | sourceTree = ""; 232 | }; 233 | /* End PBXVariantGroup section */ 234 | 235 | /* Begin XCBuildConfiguration section */ 236 | 393E185F207F6155002E6136 /* Debug */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | ALWAYS_SEARCH_USER_PATHS = NO; 240 | CLANG_ANALYZER_NONNULL = YES; 241 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_ENABLE_OBJC_WEAK = YES; 247 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 248 | CLANG_WARN_BOOL_CONVERSION = YES; 249 | CLANG_WARN_COMMA = YES; 250 | CLANG_WARN_CONSTANT_CONVERSION = YES; 251 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 254 | CLANG_WARN_EMPTY_BODY = YES; 255 | CLANG_WARN_ENUM_CONVERSION = YES; 256 | CLANG_WARN_INFINITE_RECURSION = YES; 257 | CLANG_WARN_INT_CONVERSION = YES; 258 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 259 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 260 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 261 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 262 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 263 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 264 | CLANG_WARN_STRICT_PROTOTYPES = YES; 265 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 266 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 267 | CLANG_WARN_UNREACHABLE_CODE = YES; 268 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 269 | CODE_SIGN_IDENTITY = "-"; 270 | COPY_PHASE_STRIP = NO; 271 | DEBUG_INFORMATION_FORMAT = dwarf; 272 | ENABLE_STRICT_OBJC_MSGSEND = YES; 273 | ENABLE_TESTABILITY = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu11; 275 | GCC_DYNAMIC_NO_PIC = NO; 276 | GCC_NO_COMMON_BLOCKS = YES; 277 | GCC_OPTIMIZATION_LEVEL = 0; 278 | GCC_PREPROCESSOR_DEFINITIONS = ( 279 | "DEBUG=1", 280 | "$(inherited)", 281 | ); 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | MACOSX_DEPLOYMENT_TARGET = 10.13; 289 | MTL_ENABLE_DEBUG_INFO = YES; 290 | ONLY_ACTIVE_ARCH = YES; 291 | SDKROOT = macosx; 292 | }; 293 | name = Debug; 294 | }; 295 | 393E1860207F6155002E6136 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_ANALYZER_NONNULL = YES; 300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 302 | CLANG_CXX_LIBRARY = "libc++"; 303 | CLANG_ENABLE_MODULES = YES; 304 | CLANG_ENABLE_OBJC_ARC = YES; 305 | CLANG_ENABLE_OBJC_WEAK = YES; 306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 307 | CLANG_WARN_BOOL_CONVERSION = YES; 308 | CLANG_WARN_COMMA = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 313 | CLANG_WARN_EMPTY_BODY = YES; 314 | CLANG_WARN_ENUM_CONVERSION = YES; 315 | CLANG_WARN_INFINITE_RECURSION = YES; 316 | CLANG_WARN_INT_CONVERSION = YES; 317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 323 | CLANG_WARN_STRICT_PROTOTYPES = YES; 324 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 325 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 326 | CLANG_WARN_UNREACHABLE_CODE = YES; 327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 328 | CODE_SIGN_IDENTITY = "-"; 329 | COPY_PHASE_STRIP = NO; 330 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 331 | ENABLE_NS_ASSERTIONS = NO; 332 | ENABLE_STRICT_OBJC_MSGSEND = YES; 333 | GCC_C_LANGUAGE_STANDARD = gnu11; 334 | GCC_NO_COMMON_BLOCKS = YES; 335 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 336 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 337 | GCC_WARN_UNDECLARED_SELECTOR = YES; 338 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 339 | GCC_WARN_UNUSED_FUNCTION = YES; 340 | GCC_WARN_UNUSED_VARIABLE = YES; 341 | MACOSX_DEPLOYMENT_TARGET = 10.13; 342 | MTL_ENABLE_DEBUG_INFO = NO; 343 | SDKROOT = macosx; 344 | SWIFT_COMPILATION_MODE = wholemodule; 345 | }; 346 | name = Release; 347 | }; 348 | 393E1862207F6155002E6136 /* Debug */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 352 | CLANG_ENABLE_MODULES = YES; 353 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; 354 | CODE_SIGN_IDENTITY = "-"; 355 | CODE_SIGN_STYLE = Automatic; 356 | COMBINE_HIDPI_IMAGES = YES; 357 | INFOPLIST_FILE = LNPropertyListEditorExample/Info.plist; 358 | LD_RUNPATH_SEARCH_PATHS = ( 359 | "$(inherited)", 360 | "@executable_path/../Frameworks", 361 | ); 362 | PRODUCT_BUNDLE_IDENTIFIER = com.leonatan.LNPropertyListEditorExample; 363 | PRODUCT_NAME = "$(TARGET_NAME)"; 364 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 365 | SWIFT_VERSION = 5.0; 366 | }; 367 | name = Debug; 368 | }; 369 | 393E1863207F6155002E6136 /* Release */ = { 370 | isa = XCBuildConfiguration; 371 | buildSettings = { 372 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 373 | CLANG_ENABLE_MODULES = YES; 374 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; 375 | CODE_SIGN_IDENTITY = "-"; 376 | CODE_SIGN_STYLE = Automatic; 377 | COMBINE_HIDPI_IMAGES = YES; 378 | INFOPLIST_FILE = LNPropertyListEditorExample/Info.plist; 379 | LD_RUNPATH_SEARCH_PATHS = ( 380 | "$(inherited)", 381 | "@executable_path/../Frameworks", 382 | ); 383 | PRODUCT_BUNDLE_IDENTIFIER = com.leonatan.LNPropertyListEditorExample; 384 | PRODUCT_NAME = "$(TARGET_NAME)"; 385 | SWIFT_VERSION = 5.0; 386 | }; 387 | name = Release; 388 | }; 389 | /* End XCBuildConfiguration section */ 390 | 391 | /* Begin XCConfigurationList section */ 392 | 393E1848207F6154002E6136 /* Build configuration list for PBXProject "LNPropertyListEditorExample" */ = { 393 | isa = XCConfigurationList; 394 | buildConfigurations = ( 395 | 393E185F207F6155002E6136 /* Debug */, 396 | 393E1860207F6155002E6136 /* Release */, 397 | ); 398 | defaultConfigurationIsVisible = 0; 399 | defaultConfigurationName = Release; 400 | }; 401 | 393E1861207F6155002E6136 /* Build configuration list for PBXNativeTarget "LNPropertyListEditorExample" */ = { 402 | isa = XCConfigurationList; 403 | buildConfigurations = ( 404 | 393E1862207F6155002E6136 /* Debug */, 405 | 393E1863207F6155002E6136 /* Release */, 406 | ); 407 | defaultConfigurationIsVisible = 0; 408 | defaultConfigurationName = Release; 409 | }; 410 | /* End XCConfigurationList section */ 411 | }; 412 | rootObject = 393E1845207F6154002E6136 /* Project object */; 413 | } 414 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample.xcodeproj/xcshareddata/xcschemes/LNPropertyListEditorExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // LNPropertyListEditorExample 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // LNPropertyListEditorExample 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 18 | // NSApp.windows.firstObject.appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]; 19 | } 20 | 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // LNPropertyListEditorExample 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // LNPropertyListEditorExample 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | 12 | @interface ViewController () @end 13 | 14 | @implementation ViewController 15 | { 16 | IBOutlet LNPropertyListEditor* _plistEditor; 17 | } 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | NSURL* propertyListURL = [[NSBundle mainBundle].bundleURL URLByAppendingPathComponent:@"Contents/Info.plist"]; 23 | id obj = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfURL:propertyListURL] options:0 format:nil error:NULL]; 24 | 25 | _plistEditor.delegate = self; 26 | _plistEditor.dataTransformer = self; 27 | 28 | _plistEditor.propertyListObject = obj; 29 | _plistEditor.allowsColumnSorting = YES; 30 | 31 | // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 32 | // NSLog(@"Selected: %@", _plistEditor.selectedNode); 33 | // LNPropertyListNode* node = [_plistEditor.rootPropertyListNode.children filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"key == 'yHelloNumber'"]].firstObject; 34 | // 35 | // [_plistEditor selectRowForNode:node]; 36 | // [_plistEditor scrollRowForNodeToVisible:node]; 37 | // NSLog(@"Selected: %@", _plistEditor.selectedNode); 38 | // }); 39 | } 40 | 41 | #pragma mark LNPropertyListEditorDelegate 42 | 43 | //- (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canEditValueOfNode:(LNPropertyListNode*)node 44 | //{ 45 | // return NO; 46 | //} 47 | 48 | - (void)propertyListEditor:(LNPropertyListEditor *)editor didChangeNode:(LNPropertyListNode *)node changeType:(LNPropertyListNodeChangeType)changeType previousKey:(NSString *)previousKey 49 | { 50 | switch(changeType) 51 | { 52 | case LNPropertyListNodeChangeTypeInsert: 53 | NSLog(@"🎉 Inserted %@", node); 54 | break; 55 | case LNPropertyListNodeChangeTypeDelete: 56 | NSLog(@"🗑 Deleted %@", node); 57 | break; 58 | case LNPropertyListNodeChangeTypeMove: 59 | NSLog(@"➡️ Moved %@", node); 60 | break; 61 | case LNPropertyListNodeChangeTypeUpdate: 62 | NSLog(@"🔄 Updated %@", node); 63 | break; 64 | } 65 | } 66 | 67 | #pragma mark LNPropertyListEditorDataTransformer 68 | 69 | //- (nullable id)propertyListEditor:(LNPropertyListEditor *)editor displayValueForNode:(LNPropertyListNode*)node 70 | //{ 71 | // if(node.type == LNPropertyListNodeTypeData) 72 | // { 73 | // return @"Test"; 74 | // } 75 | // 76 | // return nil; 77 | //} 78 | // 79 | //- (nullable id)propertyListEditor:(LNPropertyListEditor *)editor storageValueForNode:(LNPropertyListNode*)node displayValue:(id)displayValue 80 | //{ 81 | // if(node.type == LNPropertyListNodeTypeData) 82 | // { 83 | // return [displayValue dataUsingEncoding:NSUTF8StringEncoding]; 84 | // } 85 | // 86 | // return nil; 87 | //} 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /LNPropertyListEditorExample/LNPropertyListEditorExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LNPropertyListEditorExample 4 | // 5 | // Created by Leo Natan on 4/12/18. 6 | // Copyright © 2018-2021 Leo Natan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "LNPropertyListEditor", 7 | platforms: [ 8 | .macOS(.v10_13) 9 | ], 10 | products: [ 11 | .library( 12 | name: "LNPropertyListEditor", 13 | type: .dynamic, 14 | targets: ["LNPropertyListEditor"]), 15 | .library( 16 | name: "LNPropertyListEditor-Static", 17 | type: .static, 18 | targets: ["LNPropertyListEditor"]), 19 | ], 20 | dependencies: [], 21 | targets: [ 22 | .target( 23 | name: "LNPropertyListEditor_HexFiend", 24 | dependencies: [], 25 | path: "HexFiendFramework", 26 | exclude: [ 27 | 28 | ], 29 | resources: [], 30 | publicHeadersPath: "include", 31 | cSettings: [ 32 | .unsafeFlags(["-w"]), 33 | .define("HF_NO_PRIVILEGED_FILE_OPERATIONS", to: "1"), 34 | .headerSearchPath("include"), 35 | .headerSearchPath("src"), 36 | ]), 37 | .target( 38 | name: "LNPropertyListEditor", 39 | dependencies: [ 40 | "LNPropertyListEditor_HexFiend" 41 | ], 42 | path: "LNPropertyListEditor", 43 | exclude: [ 44 | "LNPropertyListEditor/Info.plist" 45 | ], 46 | resources: [ 47 | .process("LNPropertyListEditor/Assets.xcassets"), 48 | .process("LNPropertyListEditor/Implementation/LNPropertyListEditorOutline.xib") 49 | ], 50 | publicHeadersPath: "include", 51 | cSettings: [ 52 | .headerSearchPath("."), 53 | .headerSearchPath("LNPropertyListEditor"), 54 | ]), 55 | ] 56 | ) 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LNPropertyListEditor 2 | 3 | A property list editor for macOS, similar to the one implemented in Xcode, but with several quality of life additions, such as a visual date/time picker and a full hex editor for data objects. 4 | 5 | The framework has full support for macOS light and dark appearance. 6 | 7 | By implementing the `LNPropertyListEditorDataTransformer` protocol, you can significantly augment the way property list data is presented in the editor and represented on-disk. 8 | 9 | ![Property list editor](Supplements/Screenshot_1_Dark.png "Property list editor") 10 | 11 | ![Property list editor](Supplements/Screenshot_2_Dark.png "Property list editor") 12 | 13 | ## Adding to Your Project 14 | 15 | ### Swift Package Manager 16 | 17 | Swift Package Manager is the recommended way to integrate LNPropertyListEditor in your project. 18 | 19 | LNPropertyListEditor supports SPM versions 5.1.0 and above. To use SPM, you should use Xcode 11 to open your project. Click `File` -> `Swift Packages` -> `Add Package Dependency`, enter `https://github.com/LeoNatan/LNPropertyListEditor`. Select the version you’d like to use. 20 | 21 | You can also manually add the package to your Package.swift file: 22 | 23 | ```swift 24 | .package(url: "https://github.com/LeoNatan/LNPropertyListEditor.git", from: "1.0") 25 | ``` 26 | 27 | And the dependency in your target: 28 | 29 | ```swift 30 | .target(name: "BestExampleApp", dependencies: ["LNPropertyListEditor"]), 31 | ``` 32 | 33 | ### Carthage 34 | 35 | Add the following to your Cartfile: 36 | 37 | ```github "LeoNatan/LNPropertyListEditor"``` 38 | 39 | Make sure you follow the Carthage integration instructions [here](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos). 40 | 41 | ### Manual 42 | 43 | Drag the `LNPropertyListEditor.xcodeproj` project to your project, and add `LNPropertyListEditor.framework` to **Embedded Binaries** in your project target's **General** tab. Xcode should sort everything else on its own. 44 | 45 | ### CocoaPods 46 | 47 | CocoaPods is not supported. There are many reasons for this. Instead of CocoaPods, use Carthage. You can continue using CocoaPods for for your other dependencies and Carthage for `LNPropertyListEditor`. 48 | 49 | ## Using the Framework 50 | 51 | ### Swift 52 | 53 | While the framework is written in Objective C, it uses modern Objective C syntax, so using the framework in Swift should be very easy and intuitive. 54 | 55 | ### Project Integration 56 | 57 | Import the module in your project: 58 | 59 | ```objective-c 60 | @import LNPropertyListEditor; 61 | ``` 62 | 63 | ### Usage 64 | 65 | Either using Interface Builder or in code, add an `LNPropertyListEditor` view to your user interface. 66 | 67 | To set a represented object, set the `propertyList` property. 68 | 69 | ```swift 70 | guard let propertyListURL = Bundle.main.url(forResource: "Some", withExtension: "plist"), 71 | let propertyListData = try? Data(contentsOf: propertyListURL), 72 | let propertyListObject = try? PropertyListSerialization.propertyList(from: propertyListData, options: [], format: nil) as? [String: AnyObject] else { 73 | return 74 | } 75 | 76 | plistEditor.propertyListObject = propertyListObject 77 | ``` 78 | 79 | Supported object types: Dictionaries, arrays, strings, dates, datas, booleans and numbers (dictionaries and arrays can contains nested children of the aforementioned types). 80 | 81 | #### Delegate 82 | 83 | Implement the `LNPropertyListEditorDelegate` protocol to listen to various events, or control what aspects of the property list can be edited. 84 | 85 | ```swift 86 | plistEditor.delegate = self 87 | //... 88 | func propertyListEditor(_ editor: LNPropertyListEditor, didChange node: LNPropertyListNode, changeType: LNPropertyListNodeChangeType, previousKey: String?) { 89 | switch changeType { 90 | case .insert: 91 | print("🎉") 92 | case .move: 93 | print("➡️") 94 | case .update: 95 | print("🔄") 96 | case .delete: 97 | print("🗑") 98 | @unknown default: 99 | fatalError() 100 | } 101 | } 102 | ``` 103 | 104 | For full documentation, see the `LNPropertyListEditor.h` header. 105 | 106 | #### Data Transformer 107 | 108 | Implement the `LNPropertyListEditorDataTransformer` protocol to provide display and data transformations for your property list objects. 109 | 110 | ```swift 111 | plistEditor.dataTransformer = self 112 | //... 113 | func propertyListEditor(_ editor: LNPropertyListEditor, displayNameFor node: LNPropertyListNode) -> String? { 114 | // ... 115 | if let key = node.key, 116 | key == "CFBundleShortVersionString" { 117 | return "Bundle version string (short)" 118 | } 119 | //... 120 | } 121 | ``` 122 | 123 | For full documentation, see the `LNPropertyListEditor.h` header. 124 | 125 | ## Acknowledgements 126 | 127 | The framework uses: 128 | 129 | * [HexFiend](https://github.com/HexFiend/HexFiend) © ridiculous_fish, 2011-2020 130 | 131 | -------------------------------------------------------------------------------- /Supplements/Screenshot_1_Dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPropertyListEditor/7688237cb69ad68dd53ecf6f9f60f37a619b80e0/Supplements/Screenshot_1_Dark.png -------------------------------------------------------------------------------- /Supplements/Screenshot_2_Dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeoNatan/LNPropertyListEditor/7688237cb69ad68dd53ecf6f9f60f37a619b80e0/Supplements/Screenshot_2_Dark.png -------------------------------------------------------------------------------- /prepare_spm_support.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'fileutils' 4 | 5 | shim_header_path = File.expand_path("HexFiendShims/include/") 6 | shim_src_path = File.expand_path("HexFiendShims/src/") 7 | 8 | include_path = File.expand_path("HexFiendFramework/include/") 9 | src_path = File.expand_path("HexFiendFramework/src/") 10 | 11 | #cleanup 12 | Dir.foreach(src_path) do |f| 13 | fn = File.join(src_path, f) 14 | FileUtils.rm_rf(fn) if f != '.' && f != '..' 15 | end 16 | 17 | Dir.foreach(include_path) do |f| 18 | fn = File.join(include_path, f) 19 | FileUtils.rm_rf(fn) if f != '.' && f != '..' 20 | end 21 | 22 | Dir.mkdir(File.join(include_path, "HexFiend")) 23 | 24 | require 'xcodeproj' 25 | 26 | input_project_path = 'HexFiend/HexFiend_2.xcodeproj' 27 | input_project = Xcodeproj::Project.open(input_project_path) 28 | 29 | input_target = input_project.targets.select do |target| 30 | target.name == "HexFiend_Framework" 31 | end.first 32 | 33 | output_project_path = Pathname(File.expand_path("HexFiendFramework")) 34 | output_project = Xcodeproj::Project.new(output_project_path.join("HexFiend.xcodeproj")) 35 | output_project.build_configurations.each do |config| 36 | config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' 37 | config.build_settings['GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS'] = 'NO' 38 | end 39 | output_target = output_project.new_target(:framework, 'HexFiend', :osx, '10.14') 40 | 41 | #headers 42 | output_headers_group = output_project.new_group("Headers") 43 | 44 | files = input_target.headers_build_phase.files.to_a.map do |pbx_header_file| 45 | pbx_header_file 46 | end.select do |pbx_header_file| 47 | not(pbx_header_file.file_ref.real_path.to_s.include?("PrivilegedHelper")) 48 | end.each do |pbx_header_file| 49 | file = pbx_header_file.file_ref.real_path 50 | 51 | output_file_reference = output_headers_group.new_file(file) 52 | output_build_file = output_target.headers_build_phase.add_file_reference(output_file_reference) 53 | 54 | file2 = file.relative_path_from(src_path) 55 | File.symlink(file2, File.join(src_path, File.basename(file))) 56 | 57 | file3 = file.relative_path_from(File.join(include_path, "HexFiend")) 58 | File.symlink(file3, File.join(File.join(include_path, "HexFiend"), File.basename(file))) 59 | 60 | if pbx_header_file.settings.nil? 61 | else 62 | output_build_file.settings = pbx_header_file.settings 63 | end 64 | end 65 | 66 | Dir.each_child(shim_header_path) do |shim_header_filename| 67 | file = Pathname(File.expand_path(shim_header_filename, shim_header_path)) 68 | 69 | output_file_reference = output_headers_group.new_file(file) 70 | output_build_file = output_target.headers_build_phase.add_file_reference(output_file_reference) 71 | 72 | file2 = file.relative_path_from(src_path) 73 | File.symlink(file2, File.join(src_path, File.basename(file))) 74 | 75 | file3 = file.relative_path_from(File.join(include_path, "HexFiend")) 76 | File.symlink(file3, File.join(File.join(include_path, "HexFiend"), File.basename(file))) 77 | end 78 | 79 | #manual 80 | file = Pathname(File.expand_path("HexFiend/framework/tests/HFTest.h")) 81 | 82 | output_file_reference = output_headers_group.new_file(file) 83 | output_target.add_file_references([output_file_reference]) 84 | 85 | file2 = file.relative_path_from(src_path) 86 | File.symlink(file2, File.join(src_path, File.basename(file))) 87 | file3 = file.relative_path_from(File.join(include_path, "HexFiend")) 88 | File.symlink(file3, File.join(File.join(include_path, "HexFiend"), File.basename(file))) 89 | 90 | #sources 91 | output_sources_group = output_project.new_group("Sources") 92 | 93 | files = input_target.source_build_phase.files.to_a.map do |pbx_build_file| 94 | pbx_build_file.file_ref.real_path 95 | end.select do |path| 96 | path.to_s.end_with?(".h", ".m", ".mm") 97 | end.select do |path| 98 | not(path.to_s.include?("PrivilegedHelper")) 99 | end.select do |path| 100 | File.exists?(path) 101 | end.each do |file| 102 | output_file_reference = output_sources_group.new_file(file) 103 | output_target.add_file_references([output_file_reference]) 104 | 105 | file2 = file.relative_path_from(src_path) 106 | File.symlink(file2, File.join(src_path, File.basename(file))) 107 | end 108 | 109 | Dir.each_child(shim_src_path) do |shim_source_filename| 110 | file = Pathname(File.expand_path(shim_source_filename, shim_src_path)) 111 | 112 | output_file_reference = output_sources_group.new_file(file) 113 | output_target.add_file_references([output_file_reference]) 114 | 115 | file2 = file.relative_path_from(src_path) 116 | File.symlink(file2, File.join(src_path, File.basename(file))) 117 | end 118 | 119 | infoPlistFile = Pathname(File.expand_path("HexFiend/framework/HexFiend_Framework-Info.plist")).relative_path_from(output_project_path) 120 | infoPlistPreprocessFile = Pathname(File.expand_path("HexFiend/version.h")).relative_path_from(output_project_path) 121 | output_target.build_configurations.each do |config| 122 | config.build_settings["GCC_PREPROCESSOR_DEFINITIONS"] = ["HF_NO_PRIVILEGED_FILE_OPERATIONS=1"] 123 | config.build_settings["INFOPLIST_PREFIX_HEADER"] = infoPlistPreprocessFile.to_s 124 | config.build_settings["INFOPLIST_FILE"] = infoPlistFile.to_s 125 | config.build_settings["INFOPLIST_PREPROCESS"] = input_target.build_configurations.first.build_settings["INFOPLIST_PREPROCESS"] 126 | config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = "com.ridiculousfish.HexFiend-Framework" 127 | config.build_settings["WARNING_CFLAGS"] = "-Wno-conditional-uninitialized" 128 | end 129 | 130 | output_project.save(output_project_path.join("HexFiend.xcodeproj")) -------------------------------------------------------------------------------- /releaseVersion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ -n $(git status --porcelain) ]]; then 5 | echo -e >&2 "\033[1;31mCannot release version because there are unstaged changes:\033[0m" 6 | git status --short 7 | exit -2 8 | fi 9 | 10 | if [[ -n $(git tag --contains $(git rev-parse --verify HEAD)) ]]; then 11 | echo -e >&2 "\033[1;31mThe latest commit is already contained in the following releases:\033[0m" 12 | git tag --contains $(git rev-parse --verify HEAD) 13 | exit -3 14 | fi 15 | 16 | # if [[ -n $(git log --branches --not --remotes) ]]; then 17 | # echo -e "\033[1;34mPushing pending commits to git\033[0m" 18 | # git push 19 | # fi 20 | 21 | CURRENT_VERSION=$(/usr/libexec/PlistBuddy LNPropertyListEditor/LNPropertyListEditor/Info.plist -c "Print CFBundleShortVersionString") 22 | NEXT_VERSION=$(echo "$CURRENT_VERSION" | perl -pe 's/^((\d+\.)*)(-?\d+)(.*)$/$1.($3+1).$4/e') 23 | 24 | echo -e "\033[1;34mUsing $NEXT_VERSION as release version\033[0m" 25 | 26 | echo -e "\033[1;34mCreating release notes\033[0m" 27 | 28 | RELEASE_NOTES_FILE=_tmp_release_notes.md 29 | 30 | touch "${RELEASE_NOTES_FILE}" 31 | open -Wn "${RELEASE_NOTES_FILE}" 32 | 33 | if ! [ -s "${RELEASE_NOTES_FILE}" ]; then 34 | echo >&2 "\033[1;31mNo release notes provided, aborting.\033[0m" 35 | rm -f "${RELEASE_NOTES_FILE}" 36 | exit -1 37 | fi 38 | 39 | echo -e "\033[1;34mUpdating framework version\033[0m" 40 | 41 | /usr/libexec/PlistBuddy LNPropertyListEditor/LNPropertyListEditor/Info.plist -c "Set CFBundleShortVersionString $NEXT_VERSION" -c "Set CFBundleVersion 1" 42 | 43 | echo -e "\033[1;34mCommitting all changes to Git for release $NEXT_VERSION\033[0m" 44 | 45 | git add -A 46 | git commit -m "$NEXT_VERSION" 47 | git tag "$NEXT_VERSION" 48 | 49 | git push 50 | git push --tags 51 | 52 | echo -e "\033[1;34mCreating a GitHub release\033[0m" 53 | 54 | gh release create --repo LeoNatan/LNPropertyListEditor "$NEXT_VERSION" --title "v$NEXT_VERSION" --notes-file "${RELEASE_NOTES_FILE}" 55 | 56 | rm -f "${RELEASE_NOTES_FILE}" --------------------------------------------------------------------------------