Overhaul silica document parsing
Also adds layer count to the info sheet
This commit is contained in:
parent
1a9e952f37
commit
d997ee38d2
6 changed files with 151 additions and 23 deletions
|
@ -24,6 +24,7 @@
|
||||||
036AFC16241800350075400A /* Thumbnail.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 036AFC0B241800350075400A /* Thumbnail.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
036AFC16241800350075400A /* Thumbnail.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 036AFC0B241800350075400A /* Thumbnail.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
036AFC1B241800850075400A /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 036AFC1A241800850075400A /* ZIPFoundation */; };
|
036AFC1B241800850075400A /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 036AFC1A241800850075400A /* ZIPFoundation */; };
|
||||||
037B4042241821D200392452 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037B4041241821D200392452 /* InfoViewController.swift */; };
|
037B4042241821D200392452 /* InfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 037B4041241821D200392452 /* InfoViewController.swift */; };
|
||||||
|
03CB382424191F620078B3E5 /* cbridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 03CB382324191F620078B3E5 /* cbridge.c */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -79,6 +80,8 @@
|
||||||
036AFC12241800350075400A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
036AFC12241800350075400A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
036AFC13241800350075400A /* Thumbnail.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Thumbnail.entitlements; sourceTree = "<group>"; };
|
036AFC13241800350075400A /* Thumbnail.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Thumbnail.entitlements; sourceTree = "<group>"; };
|
||||||
037B4041241821D200392452 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = "<group>"; };
|
037B4041241821D200392452 /* InfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoViewController.swift; sourceTree = "<group>"; };
|
||||||
|
03CB382224191F610078B3E5 /* ProcreateViewer-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ProcreateViewer-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
03CB382324191F620078B3E5 /* cbridge.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cbridge.c; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -144,6 +147,8 @@
|
||||||
030F6FFE2415C5E400A43F01 /* ProcreateViewer.entitlements */,
|
030F6FFE2415C5E400A43F01 /* ProcreateViewer.entitlements */,
|
||||||
036AFBB924168C030075400A /* ViewController.swift */,
|
036AFBB924168C030075400A /* ViewController.swift */,
|
||||||
037B4041241821D200392452 /* InfoViewController.swift */,
|
037B4041241821D200392452 /* InfoViewController.swift */,
|
||||||
|
03CB382324191F620078B3E5 /* cbridge.c */,
|
||||||
|
03CB382224191F610078B3E5 /* ProcreateViewer-Bridging-Header.h */,
|
||||||
);
|
);
|
||||||
path = ProcreateViewer;
|
path = ProcreateViewer;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -256,6 +261,7 @@
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
030F6FED2415C5E300A43F01 = {
|
030F6FED2415C5E300A43F01 = {
|
||||||
CreatedOnToolsVersion = 11.3.1;
|
CreatedOnToolsVersion = 11.3.1;
|
||||||
|
LastSwiftMigration = 1130;
|
||||||
};
|
};
|
||||||
030F70072415C6B500A43F01 = {
|
030F70072415C6B500A43F01 = {
|
||||||
CreatedOnToolsVersion = 11.3.1;
|
CreatedOnToolsVersion = 11.3.1;
|
||||||
|
@ -321,6 +327,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
036AFBBA24168C030075400A /* ViewController.swift in Sources */,
|
036AFBBA24168C030075400A /* ViewController.swift in Sources */,
|
||||||
|
03CB382424191F620078B3E5 /* cbridge.c in Sources */,
|
||||||
030F6FF42415C5E300A43F01 /* Document.swift in Sources */,
|
030F6FF42415C5E300A43F01 /* Document.swift in Sources */,
|
||||||
037B4042241821D200392452 /* InfoViewController.swift in Sources */,
|
037B4042241821D200392452 /* InfoViewController.swift in Sources */,
|
||||||
030F6FF22415C5E300A43F01 /* AppDelegate.swift in Sources */,
|
030F6FF22415C5E300A43F01 /* AppDelegate.swift in Sources */,
|
||||||
|
@ -496,6 +503,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = ProcreateViewer/ProcreateViewer.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ProcreateViewer/ProcreateViewer.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
@ -507,6 +515,8 @@
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.github.redstrate.ProcreateViewer;
|
PRODUCT_BUNDLE_IDENTIFIER = com.github.redstrate.ProcreateViewer;
|
||||||
PRODUCT_NAME = "Procreate Viewer";
|
PRODUCT_NAME = "Procreate Viewer";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "ProcreateViewer/ProcreateViewer-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -516,6 +526,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = ProcreateViewer/ProcreateViewer.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ProcreateViewer/ProcreateViewer.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
@ -527,6 +538,7 @@
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.github.redstrate.ProcreateViewer;
|
PRODUCT_BUNDLE_IDENTIFIER = com.github.redstrate.ProcreateViewer;
|
||||||
PRODUCT_NAME = "Procreate Viewer";
|
PRODUCT_NAME = "Procreate Viewer";
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "ProcreateViewer/ProcreateViewer-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||||
</connections>
|
</connections>
|
||||||
</application>
|
</application>
|
||||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="ProcreateViewer" customModuleProvider="target"/>
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Procreate_Viewer" customModuleProvider="target"/>
|
||||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||||
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
<userDefaultsController representsSharedInstance="YES" id="JdS-Pg-8N9"/>
|
<userDefaultsController representsSharedInstance="YES" id="JdS-Pg-8N9"/>
|
||||||
|
@ -159,19 +159,30 @@
|
||||||
<!--Info View Controller-->
|
<!--Info View Controller-->
|
||||||
<scene sceneID="nJy-a4-E0d">
|
<scene sceneID="nJy-a4-E0d">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController showSeguePresentationStyle="single" id="wda-Mt-beD" customClass="InfoViewController" customModule="ProcreateViewer" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController showSeguePresentationStyle="single" id="wda-Mt-beD" customClass="InfoViewController" customModule="Procreate_Viewer" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" id="3vu-Kd-l73">
|
<view key="view" id="3vu-Kd-l73">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="480" height="85"/>
|
<rect key="frame" x="0.0" y="0.0" width="480" height="109"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="u9u-el-oA4">
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="u9u-el-oA4">
|
||||||
<rect key="frame" x="18" y="49" width="444" height="16"/>
|
<rect key="frame" x="18" y="73" width="444" height="16"/>
|
||||||
<textFieldCell key="cell" lineBreakMode="clipping" placeholderString="Time Spent" id="UBd-vS-gNL">
|
<textFieldCell key="cell" lineBreakMode="clipping" placeholderString="Time Spent" id="UBd-vS-gNL">
|
||||||
<font key="font" usesAppearanceFont="YES"/>
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
</textFieldCell>
|
</textFieldCell>
|
||||||
</textField>
|
</textField>
|
||||||
|
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8HM-na-o1E">
|
||||||
|
<rect key="frame" x="18" y="49" width="444" height="16"/>
|
||||||
|
<textFieldCell key="cell" lineBreakMode="clipping" id="cl0-u1-l9k">
|
||||||
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
|
<string key="placeholderString" base64-UTF8="YES">
|
||||||
|
Dk51bWJlciBvZiBMYXllcnM6A
|
||||||
|
</string>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2oe-to-Rcz">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2oe-to-Rcz">
|
||||||
<rect key="frame" x="407" y="13" width="59" height="32"/>
|
<rect key="frame" x="407" y="13" width="59" height="32"/>
|
||||||
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BnS-yc-3ej">
|
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BnS-yc-3ej">
|
||||||
|
@ -187,20 +198,24 @@ DQ
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="2oe-to-Rcz" firstAttribute="top" secondItem="u9u-el-oA4" secondAttribute="bottom" constant="8" symbolic="YES" id="BYm-qe-WxD"/>
|
<constraint firstItem="2oe-to-Rcz" firstAttribute="top" secondItem="8HM-na-o1E" secondAttribute="bottom" constant="8" symbolic="YES" id="85g-Dp-ezi"/>
|
||||||
<constraint firstItem="u9u-el-oA4" firstAttribute="top" secondItem="3vu-Kd-l73" secondAttribute="top" constant="20" symbolic="YES" id="HaC-Tk-Y3y"/>
|
<constraint firstItem="8HM-na-o1E" firstAttribute="top" secondItem="u9u-el-oA4" secondAttribute="bottom" constant="8" symbolic="YES" id="CA1-bq-4Dc"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="u9u-el-oA4" secondAttribute="trailing" constant="20" symbolic="YES" id="Qfn-KK-5Ya"/>
|
<constraint firstItem="u9u-el-oA4" firstAttribute="trailing" secondItem="8HM-na-o1E" secondAttribute="trailing" id="ILX-8S-pOI"/>
|
||||||
<constraint firstItem="u9u-el-oA4" firstAttribute="leading" secondItem="3vu-Kd-l73" secondAttribute="leading" constant="20" symbolic="YES" id="TpT-D9-UgA"/>
|
<constraint firstItem="u9u-el-oA4" firstAttribute="top" secondItem="3vu-Kd-l73" secondAttribute="top" constant="20" symbolic="YES" id="IQj-on-T5L"/>
|
||||||
<constraint firstItem="2oe-to-Rcz" firstAttribute="trailing" secondItem="u9u-el-oA4" secondAttribute="trailing" id="ZND-Qt-9wv"/>
|
<constraint firstItem="u9u-el-oA4" firstAttribute="leading" secondItem="8HM-na-o1E" secondAttribute="leading" id="KJd-X5-kxh"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="u9u-el-oA4" secondAttribute="trailing" constant="20" symbolic="YES" id="PlA-zS-FpK"/>
|
||||||
|
<constraint firstItem="2oe-to-Rcz" firstAttribute="trailing" secondItem="8HM-na-o1E" secondAttribute="trailing" id="Whu-Lh-znF"/>
|
||||||
|
<constraint firstItem="u9u-el-oA4" firstAttribute="leading" secondItem="3vu-Kd-l73" secondAttribute="leading" constant="20" symbolic="YES" id="Xzy-ZR-1ha"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="layerCountLabel" destination="8HM-na-o1E" id="Vnq-ev-JGx"/>
|
||||||
<outlet property="timeSpentLabel" destination="u9u-el-oA4" id="LeI-31-Z8r"/>
|
<outlet property="timeSpentLabel" destination="u9u-el-oA4" id="LeI-31-Z8r"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<customObject id="Tam-yi-Bux" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
<customObject id="Tam-yi-Bux" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="786" y="286.5"/>
|
<point key="canvasLocation" x="786" y="298.5"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Window Controller-->
|
<!--Window Controller-->
|
||||||
<scene sceneID="R2V-B0-nI4">
|
<scene sceneID="R2V-B0-nI4">
|
||||||
|
@ -226,7 +241,7 @@ DQ
|
||||||
<!--View Controller-->
|
<!--View Controller-->
|
||||||
<scene sceneID="hIz-AP-VOD">
|
<scene sceneID="hIz-AP-VOD">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="5gI-5U-AMq" customClass="ViewController" customModule="ProcreateViewer" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController id="5gI-5U-AMq" customClass="ViewController" customModule="Procreate_Viewer" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<view key="view" id="ERx-hH-rdd">
|
<view key="view" id="ERx-hH-rdd">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
|
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
|
|
@ -1,12 +1,32 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import ZIPFoundation
|
import ZIPFoundation
|
||||||
|
import CoreFoundation
|
||||||
|
|
||||||
struct DocumentInfo {
|
struct SilicaLayer {
|
||||||
var tracked_time: Int = 0
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SilicaDocument {
|
||||||
|
var trackedTime: Int = 0
|
||||||
|
|
||||||
|
var layers: [SilicaLayer] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since this is a C-function we have to unsafe cast...
|
||||||
|
func objectRefGetValue(_ objectRef : CFTypeRef) -> UInt32 {
|
||||||
|
return _CFKeyedArchiverUIDGetValue(unsafeBitCast(objectRef, to: CFKeyedArchiverUIDRef.self))
|
||||||
}
|
}
|
||||||
|
|
||||||
class Document: NSDocument {
|
class Document: NSDocument {
|
||||||
var info = DocumentInfo()
|
var dict: NSDictionary?
|
||||||
|
|
||||||
|
let DocumentClassName = "SilicaDocument"
|
||||||
|
let TrackedTimeKey = "SilicaDocumentTrackedTimeKey"
|
||||||
|
let LayersKey = "layers"
|
||||||
|
|
||||||
|
let LayerClassName = "SilicaLayer"
|
||||||
|
|
||||||
|
var info = SilicaDocument()
|
||||||
|
|
||||||
var thumbnail: NSImage? = nil
|
var thumbnail: NSImage? = nil
|
||||||
|
|
||||||
|
@ -19,6 +39,72 @@ class Document: NSDocument {
|
||||||
let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
|
let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
|
||||||
self.addWindowController(windowController)
|
self.addWindowController(windowController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pass in an object from the $object array, which always contains a $class key.
|
||||||
|
*/
|
||||||
|
func getDocumentClassName(dict: NSDictionary) -> String? {
|
||||||
|
let objectsArray = self.dict?["$objects"] as! NSArray
|
||||||
|
|
||||||
|
if let value = dict["$class"] {
|
||||||
|
let classObjectId = objectRefGetValue(value as CFTypeRef)
|
||||||
|
let classObject = objectsArray[Int(classObjectId)] as! NSDictionary
|
||||||
|
|
||||||
|
return classObject["$classname"] as? String
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSilicaLayer(dict: NSDictionary) {
|
||||||
|
if getDocumentClassName(dict: dict) == LayerClassName {
|
||||||
|
let layer = SilicaLayer()
|
||||||
|
// TODO: fill in layer information
|
||||||
|
|
||||||
|
info.layers.append(layer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSilicaDocument(dict: NSDictionary) {
|
||||||
|
let objectsArray = self.dict?["$objects"] as! NSArray
|
||||||
|
|
||||||
|
if getDocumentClassName(dict: dict) == DocumentClassName {
|
||||||
|
info.trackedTime = (dict[TrackedTimeKey] as! NSNumber).intValue
|
||||||
|
|
||||||
|
let layersClassKey = dict[LayersKey]
|
||||||
|
let layersClassID = objectRefGetValue(layersClassKey as CFTypeRef)
|
||||||
|
let layersClass = objectsArray[Int(layersClassID)] as! NSDictionary
|
||||||
|
|
||||||
|
let array = layersClass["NS.objects"] as! NSArray
|
||||||
|
|
||||||
|
for object in array {
|
||||||
|
let layerClassID = objectRefGetValue(object as CFTypeRef)
|
||||||
|
let layerClass = objectsArray[Int(layerClassID)] as! NSDictionary
|
||||||
|
|
||||||
|
parseSilicaLayer(dict: layerClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDocument(dict: NSDictionary) {
|
||||||
|
// double check if this archive is really correct
|
||||||
|
if let value = dict["$version"] {
|
||||||
|
if (value as! Int) != 100000 {
|
||||||
|
Swift.print("This is not a valid document!")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dict = dict
|
||||||
|
|
||||||
|
let objectsArray = dict["$objects"] as! NSArray
|
||||||
|
|
||||||
|
// let's read the $top class, which is always going to be SilicaDocument type.
|
||||||
|
let topObject = dict["$top"] as! NSDictionary
|
||||||
|
let topClassID = objectRefGetValue(topObject["root"] as CFTypeRef)
|
||||||
|
let topObjectClass = objectsArray[Int(topClassID)] as! NSDictionary
|
||||||
|
|
||||||
|
parseSilicaDocument(dict: topObjectClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func read(from data: Data, ofType typeName: String) throws {
|
override func read(from data: Data, ofType typeName: String) throws {
|
||||||
guard let archive = Archive(data: data, accessMode: Archive.AccessMode.read) else {
|
guard let archive = Archive(data: data, accessMode: Archive.AccessMode.read) else {
|
||||||
|
@ -65,14 +151,9 @@ class Document: NSDocument {
|
||||||
fatalError("failed to deserialize")
|
fatalError("failed to deserialize")
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is temporary, as we're just hoping that the keyed archive fits our requirements...
|
|
||||||
let dict = (propertyList as! NSDictionary);
|
let dict = (propertyList as! NSDictionary);
|
||||||
|
|
||||||
let objects = dict["$objects"] as! NSArray
|
parseDocument(dict: dict)
|
||||||
|
|
||||||
let tracked_time = (objects[1] as! NSDictionary)["SilicaDocumentTrackedTimeKey"]
|
|
||||||
|
|
||||||
info.tracked_time = (tracked_time as! NSNumber).intValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,19 @@ class InfoViewController: NSViewController {
|
||||||
var document: Document?
|
var document: Document?
|
||||||
|
|
||||||
@IBOutlet weak var timeSpentLabel: NSTextField!
|
@IBOutlet weak var timeSpentLabel: NSTextField!
|
||||||
|
@IBOutlet weak var layerCountLabel: NSTextField!
|
||||||
override func viewDidAppear() {
|
|
||||||
|
override func viewWillAppear() {
|
||||||
super.viewDidAppear()
|
super.viewDidAppear()
|
||||||
|
|
||||||
let formatter = DateComponentsFormatter()
|
let formatter = DateComponentsFormatter()
|
||||||
formatter.allowedUnits = [.hour, .minute, .second]
|
formatter.allowedUnits = [.hour, .minute, .second]
|
||||||
formatter.unitsStyle = .full
|
formatter.unitsStyle = .full
|
||||||
|
|
||||||
let formattedString = formatter.string(from: TimeInterval(document!.info.tracked_time))!
|
let formattedString = formatter.string(from: TimeInterval(document!.info.trackedTime))!
|
||||||
|
|
||||||
timeSpentLabel.stringValue = "Time Spent: " + formattedString
|
timeSpentLabel.stringValue = "Time Spent: " + formattedString
|
||||||
|
|
||||||
|
layerCountLabel.stringValue = "Number of layers: " + String(document!.info.layers.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
ProcreateViewer/ProcreateViewer-Bridging-Header.h
Normal file
8
ProcreateViewer/ProcreateViewer-Bridging-Header.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
Here we import Apple's functions to decode __CFKeyedArchiverUID types.
|
||||||
|
*/
|
||||||
|
#include <CoreFoundation/CFBase.h>
|
||||||
|
|
||||||
|
typedef const struct __CFKeyedArchiverUID * CFKeyedArchiverUIDRef;
|
||||||
|
|
||||||
|
extern uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid);
|
9
ProcreateViewer/cbridge.c
Normal file
9
ProcreateViewer/cbridge.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
//
|
||||||
|
// cbridge.c
|
||||||
|
// ProcreateViewer
|
||||||
|
//
|
||||||
|
// Created by Josh on 3/11/20.
|
||||||
|
// Copyright © 2020 Josh. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
Reference in a new issue