diff --git a/Evergreen/Base.lproj/MainWindow.storyboard b/Evergreen/Base.lproj/MainWindow.storyboard
index b546d2748..628211a7e 100644
--- a/Evergreen/Base.lproj/MainWindow.storyboard
+++ b/Evergreen/Base.lproj/MainWindow.storyboard
@@ -310,6 +310,19 @@
+
+
+
+
+
+
+
+
@@ -317,11 +330,14 @@
+
+
+
diff --git a/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj b/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj
index 35572be15..79633dbb7 100755
--- a/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj
+++ b/Frameworks/RSCore/RSCore.xcodeproj/project.pbxproj
@@ -96,6 +96,12 @@
84B99C9A1FAE650100ECDEDB /* OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B99C991FAE650100ECDEDB /* OPMLRepresentable.swift */; };
84B99C9B1FAE650100ECDEDB /* OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B99C991FAE650100ECDEDB /* OPMLRepresentable.swift */; };
84BB45431D6909C700B48537 /* NSMutableDictionary-Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */; };
+ 84C687301FBAA30800345C9E /* LogWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84C6872F1FBAA30800345C9E /* LogWindow.xib */; };
+ 84C687321FBAA3DF00345C9E /* LogWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C687311FBAA3DF00345C9E /* LogWindowController.swift */; };
+ 84C687351FBC025600345C9E /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C687341FBC025600345C9E /* Logger.swift */; };
+ 84C687361FBC025600345C9E /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C687341FBC025600345C9E /* Logger.swift */; };
+ 84C687381FBC028900345C9E /* LogItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C687371FBC028900345C9E /* LogItem.swift */; };
+ 84C687391FBC028900345C9E /* LogItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C687371FBC028900345C9E /* LogItem.swift */; };
84CFF4FA1AC3C69700CEA6C8 /* RSCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 84CFF4F91AC3C69700CEA6C8 /* RSCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
84CFF5001AC3C69700CEA6C8 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */; };
84CFF5071AC3C69700CEA6C8 /* RSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84CFF5061AC3C69700CEA6C8 /* RSCoreTests.m */; };
@@ -198,6 +204,10 @@
84B99C931FAE64D400ECDEDB /* DisplayNameProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DisplayNameProvider.swift; path = RSCore/DisplayNameProvider.swift; sourceTree = ""; };
84B99C991FAE650100ECDEDB /* OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OPMLRepresentable.swift; path = RSCore/OPMLRepresentable.swift; sourceTree = ""; };
84BB45421D6909C700B48537 /* NSMutableDictionary-Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSMutableDictionary-Extensions.swift"; sourceTree = ""; };
+ 84C6872F1FBAA30800345C9E /* LogWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = LogWindow.xib; path = AppKit/LogWindow.xib; sourceTree = ""; };
+ 84C687311FBAA3DF00345C9E /* LogWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LogWindowController.swift; path = AppKit/LogWindowController.swift; sourceTree = ""; };
+ 84C687341FBC025600345C9E /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; };
+ 84C687371FBC028900345C9E /* LogItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogItem.swift; sourceTree = ""; };
84CFF4F41AC3C69700CEA6C8 /* RSCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RSCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84CFF4F81AC3C69700CEA6C8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = RSCore/Info.plist; sourceTree = ""; };
84CFF4F91AC3C69700CEA6C8 /* RSCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RSCore.h; path = RSCore/RSCore.h; sourceTree = ""; };
@@ -426,6 +436,10 @@
8461387E1DB3F5BE00048B83 /* RSToolbarItem.swift */,
8479213B1FBA426B004AD08C /* WebViewWindow.xib */,
8479213D1FBA4285004AD08C /* WebViewWindowController.swift */,
+ 84C6872F1FBAA30800345C9E /* LogWindow.xib */,
+ 84C687311FBAA3DF00345C9E /* LogWindowController.swift */,
+ 84C687341FBC025600345C9E /* Logger.swift */,
+ 84C687371FBC028900345C9E /* LogItem.swift */,
842DD7F91E1499FA00E061EB /* Views */,
);
name = AppKit;
@@ -632,6 +646,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 84C687301FBAA30800345C9E /* LogWindow.xib in Resources */,
8479213C1FBA426B004AD08C /* WebViewWindow.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -661,6 +676,7 @@
842DD7F31E14996B00E061EB /* NSMutableDictionary-Extensions.swift in Sources */,
842DD7DF1E14996300E061EB /* NSDictionary+RSCore.m in Sources */,
842DD7C81E14995C00E061EB /* RSConstants.m in Sources */,
+ 84C687391FBC028900345C9E /* LogItem.swift in Sources */,
842DD7D41E14995C00E061EB /* DiskSaver.swift in Sources */,
842DD7E11E14996300E061EB /* NSFileManager+RSCore.m in Sources */,
842DD7C61E14995C00E061EB /* RSBlocks.m in Sources */,
@@ -675,6 +691,7 @@
842DD7EF1E14996300E061EB /* NSString+RSCore.m in Sources */,
842DD7F21E14996B00E061EB /* Date+Extensions.swift in Sources */,
842DD7ED1E14996300E061EB /* NSSet+RSCore.m in Sources */,
+ 84C687361FBC025600345C9E /* Logger.swift in Sources */,
842DD7CA1E14995C00E061EB /* RSPlatform.m in Sources */,
842DD7D91E14996300E061EB /* NSCalendar+RSCore.m in Sources */,
842DD7F11E14996300E061EB /* NSTimer+RSCore.m in Sources */,
@@ -706,10 +723,13 @@
84CFF5441AC3CD3500CEA6C8 /* NSNotificationCenter+RSCore.m in Sources */,
84CFF55D1AC3D01F00CEA6C8 /* RSBackgroundColorView.m in Sources */,
84CFF5131AC3C6D800CEA6C8 /* RSBlocks.m in Sources */,
+ 84C687321FBAA3DF00345C9E /* LogWindowController.swift in Sources */,
+ 84C687381FBC028900345C9E /* LogItem.swift in Sources */,
8432B1861DACA0E90057D6DF /* NSResponder-Extensions.swift in Sources */,
849B08981BF7BCE30090CEE4 /* NSPasteboard+RSCore.m in Sources */,
842635571D7FA1C800196285 /* NSTableView+Extensions.swift in Sources */,
84F20F831F16BA6200D8E682 /* PropertyList.swift in Sources */,
+ 84C687351FBC025600345C9E /* Logger.swift in Sources */,
84CFF5611AC3D0CE00CEA6C8 /* RSBinaryCache.m in Sources */,
84CFF5301AC3CB1900CEA6C8 /* NSDate+RSCore.m in Sources */,
84CFF5281AC3C9A200CEA6C8 /* NSArray+RSCore.m in Sources */,
diff --git a/Frameworks/RSCore/RSCore/AppKit/LogWindow.xib b/Frameworks/RSCore/RSCore/AppKit/LogWindow.xib
new file mode 100644
index 000000000..73c7a34da
--- /dev/null
+++ b/Frameworks/RSCore/RSCore/AppKit/LogWindow.xib
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Frameworks/RSCore/RSCore/AppKit/LogWindowController.swift b/Frameworks/RSCore/RSCore/AppKit/LogWindowController.swift
new file mode 100644
index 000000000..617721fec
--- /dev/null
+++ b/Frameworks/RSCore/RSCore/AppKit/LogWindowController.swift
@@ -0,0 +1,62 @@
+//
+// LogWindowController.swift
+// RSCore
+//
+// Created by Brent Simmons on 11/13/17.
+// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
+//
+
+import Cocoa
+
+class LogWindowController: NSWindowController {
+
+ @IBOutlet private var textView: NSTextView!
+ private var title: String!
+// private let attributes = [NSFont.Att
+ public convenience init(title: String) {
+
+ self.init(windowNibName: NSNib.Name(rawValue: "LogWindow"))
+ self.title = title
+ }
+
+ override func windowDidLoad() {
+
+ window!.title = title
+ }
+
+ public func appendLine(_ s: String) {
+
+ // Adds two line feeds before the text.
+
+
+ }
+
+ public func setTextViewText(_ s: String) {
+
+ let attributedString = NSAttributedString(string: s)
+ textView.textStorage?.setAttributedString(attributedString)
+
+ validateButtons()
+ }
+
+ // MARK: - Actions
+
+ @IBAction func clearContents(_ sender: Any?) {
+
+ setTextViewText("")
+ }
+
+ @IBAction func saveToFile(_ sender: Any?) {
+
+ }
+
+}
+
+private extension LogWindowController {
+
+ func validateButtons() {
+
+ }
+
+
+}
diff --git a/Frameworks/RSCore/RSCore/LogItem.swift b/Frameworks/RSCore/RSCore/LogItem.swift
new file mode 100644
index 000000000..501964688
--- /dev/null
+++ b/Frameworks/RSCore/RSCore/LogItem.swift
@@ -0,0 +1,34 @@
+//
+// LogItem.swift
+// RSCore
+//
+// Created by Brent Simmons on 11/14/17.
+// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
+//
+
+import Foundation
+
+public struct LogItem: Hashable {
+
+ public enum ItemType {
+ case notification, warning, error
+ }
+
+ public let type: ItemType
+ public let message: String
+ public let date: Date
+ public let hashValue: Int
+
+ public init(type: ItemType, message: String) {
+
+ self.type = type
+ self.message = message
+ self.date = Date()
+ self.hashValue = message.hashValue + self.date.hashValue
+ }
+
+ static public func ==(lhs: LogItem, rhs: LogItem) -> Bool {
+
+ return lhs.type == rhs.type && lhs.message == rhs.message && lhs.date == rhs.date
+ }
+}
diff --git a/Frameworks/RSCore/RSCore/Logger.swift b/Frameworks/RSCore/RSCore/Logger.swift
new file mode 100644
index 000000000..a0865e295
--- /dev/null
+++ b/Frameworks/RSCore/RSCore/Logger.swift
@@ -0,0 +1,19 @@
+//
+// Logger.swift
+// RSCore
+//
+// Created by Brent Simmons on 11/14/17.
+// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
+//
+
+import Foundation
+
+public class Logger {
+
+ var logItems = [LogItem]()
+
+ public func addLogItem(_ logItem: LogItem) {
+
+ logItems += [logItem]
+ }
+}