Frequncy Window and loading implemented

This commit is contained in:
Kilian Hofmann 2017-06-20 21:14:17 +02:00
parent ef111ee997
commit 086c8a0f94
8 changed files with 367 additions and 5 deletions

View File

@ -41,6 +41,8 @@
E26246451EF5E64900EAA4A6 /* PDFDraw.xib in Resources */ = {isa = PBXBuildFile; fileRef = E26246431EF5E64900EAA4A6 /* PDFDraw.xib */; };
E26246471EF6684B00EAA4A6 /* PDFItemViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E26246461EF6684B00EAA4A6 /* PDFItemViewController.xib */; };
E26246491EF6688400EAA4A6 /* PDFItemViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26246481EF6688400EAA4A6 /* PDFItemViewController.swift */; };
E27A9DB51EF995C1000BC7A3 /* FrequencyGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27A9DB41EF995C1000BC7A3 /* FrequencyGraph.swift */; };
E27A9DB91EF99C20000BC7A3 /* FlippedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27A9DB81EF99C20000BC7A3 /* FlippedView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -103,6 +105,8 @@
E26246431EF5E64900EAA4A6 /* PDFDraw.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PDFDraw.xib; sourceTree = "<group>"; };
E26246461EF6684B00EAA4A6 /* PDFItemViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PDFItemViewController.xib; sourceTree = "<group>"; };
E26246481EF6688400EAA4A6 /* PDFItemViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFItemViewController.swift; sourceTree = "<group>"; };
E27A9DB41EF995C1000BC7A3 /* FrequencyGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FrequencyGraph.swift; sourceTree = "<group>"; };
E27A9DB81EF99C20000BC7A3 /* FlippedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlippedView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -347,6 +351,8 @@
E2268DFA1EF712D300C97726 /* Graph View */ = {
isa = PBXGroup;
children = (
E27A9DB81EF99C20000BC7A3 /* FlippedView.swift */,
E27A9DB41EF995C1000BC7A3 /* FrequencyGraph.swift */,
E2218D511EF32AC6004298F6 /* GraphDetailsController.swift */,
E262463C1EF55BCE00EAA4A6 /* GraphWindow.swift */,
);
@ -571,6 +577,8 @@
E262463E1EF55BCE00EAA4A6 /* GraphWindow.swift in Sources */,
E26246491EF6688400EAA4A6 /* PDFItemViewController.swift in Sources */,
E2218D641EF45F37004298F6 /* LossDistributionPie.swift in Sources */,
E27A9DB51EF995C1000BC7A3 /* FrequencyGraph.swift in Sources */,
E27A9DB91EF99C20000BC7A3 /* FlippedView.swift in Sources */,
E2218D571EF335E6004298F6 /* CollectionViewItemYear.swift in Sources */,
E2218D521EF32AC6004298F6 /* GraphDetailsController.swift in Sources */,
E2218D5D1EF3DD6F004298F6 /* CollectionViewItemMonth.swift in Sources */,

View File

@ -87,8 +87,7 @@ extension CollectionViewMonth: NSCollectionViewDataSource {
/*
guard var logA = String(data: log.regularFileContents!, encoding: .utf8)?.components(separatedBy: "\n") else { return }
*/
guard var logA = FileOperations.load(log: log.regularFileContents! as NSData) else { return }
logA.removeLast()
guard let logA = FileOperations.load(log: log.regularFileContents! as NSData) else { return }
item2.distribution = logA
OperationQueue.main.addOperation {
item2.loss.stringValue = "\(logA.count)"

View File

@ -0,0 +1,24 @@
//
// FlippedView.swift
// Logger2
//
// Created by Kilian Hofmann on 03.08.16.
// Copyright © 2016 Kilian Hofmann. All rights reserved.
//
import Cocoa
class FlippedView: NSView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
}
override var isFlipped: Bool {
get {
return true
}
}
}

View File

@ -0,0 +1,263 @@
//
// GraphView.swift
// Docsis Toolkit
//
// Created by Kilian Hofmann on 20.06.17.
// Copyright © 2017 Kilian Hofmann. All rights reserved.
//
import Cocoa
class FrequencyGraph: NSView {
let opQueue: OperationQueue = OperationQueue()
// Constants
static let graphSizeWithSeparator: Int = 109
static let graphSize: Int = 108
static let maxGraphSize: Int = 17300
let zeroOffset: Double = 37
// Path related
var path: NSBezierPath = NSBezierPath.init()
var threshold: NSBezierPath = NSBezierPath.init()
var upstream: Bool = false
var lastTime: Int = 0
var lastTimeThreshold: Int = 0
var timePaths: [NSBezierPath] = []
var lossPaths: [NSBezierPath] = []
var offset: Int = 0
// Popover
let popover: NSPopover = NSPopover()
// Data
var data: [String] = []
var dataLoss: [String] = []
var frequency: Double = 0.0
// Cursor
var cursor: NSBezierPath = NSBezierPath.init()
// Superview
var content: FlippedView!
init(upstream: Bool, frame: CGRect, superview: FlippedView) {
super.init(frame: frame)
self.upstream = upstream
let tracking: NSTrackingArea = NSTrackingArea(rect: self.bounds, options: [.mouseEnteredAndExited, .mouseMoved, .activeInActiveApp, .inVisibleRect], owner: self, userInfo: nil)
self.addTrackingArea(tracking)
popover.contentViewController = GraphDetailsController()
self.content = superview
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func draw(_ dirtyRect: NSRect) {
NSColor.white.setFill()
NSRectFill(dirtyRect)
threshold.lineWidth = 0.5
if upstream {
NSColor.red.set()
threshold.stroke()
} else {
NSColor.blue.set()
threshold.stroke()
}
NSColor.black.set()
path.lineWidth = 1
path.stroke()
NSColor(red: 0, green: 0, blue: 0, alpha: 0.3).set()
cursor.lineWidth = 2
cursor.stroke()
for index in 0..<timePaths.count {
timePaths[index].lineWidth = 0.5
timePaths[index].stroke()
}
for index in 0..<lossPaths.count {
NSColor(red: 1, green: 0, blue: 0, alpha: 0.2).set()
lossPaths[index].lineWidth = 2
lossPaths[index].stroke()
}
}
override var isFlipped:Bool {
get {
return false
}
}
func initView() {
// Setup Indicator
// Zero line
let zero: NSBezierPath = NSBezierPath()
zero.move(to: NSPoint(x: 5, y: zeroOffset))
zero.line(to: NSPoint(x: Int(FrequencyGraph.maxGraphSize-5), y: Int(zeroOffset)))
self.timePaths.append(zero)
// Add data points
var lastWasSkipped: Bool = false
for point in 0..<data.count {
// Get values
let level: Double? = Double(data[point].components(separatedBy: ";")[1])
let threshold: Double? = Double(data[point].components(separatedBy: ";")[2])
// Set path, skip if empty values (-)
if level == nil || threshold == nil {
skipPath()
lastWasSkipped = true
} else {
if lastWasSkipped {
restartPath(level!, threshold_level: threshold!)
lastWasSkipped = false
} else if point == 0 {
// Get offset
offset = 0
let time: String = data[point].components(separatedBy: ";")[0]
let hour: Int = Int(time.substring(to: time.index(time.startIndex, offsetBy: 2)))!
let tensSeconds: Int = Int((time as NSString).substring(with: NSMakeRange(6, 1)))!
offset = ((hour*60 + Int((time as NSString).substring(with: NSMakeRange(3, 2)))!) * 6 + tensSeconds) * 2
// Set offset
lastTime = offset
lastTimeThreshold = offset
addPath(level!, threshold_level: threshold!)
} else {
addPath(level!, threshold_level: threshold!)
}
}
// Set connection loss zones
for loss in 0..<dataLoss.count {
if dataLoss[loss].substring(to: dataLoss[loss].index(dataLoss[loss].startIndex, offsetBy: 5)) == data[point].components(separatedBy: ";")[0].substring(to: data[point].components(separatedBy: ";")[0].index(data[point].components(separatedBy: ";")[0].startIndex, offsetBy: 5)) {
let lossPath: NSBezierPath = NSBezierPath()
lossPath.move(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(17)))
lossPath.line(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(FrequencyGraph.graphSize)))
lossPaths.append(lossPath)
}
}
// Set time scale
if (point+offset/2) % 60 == 0 {
// Time label
let time: NSTextField = NSTextField(frame: NSMakeRect(CGFloat(10 + point*2 + offset), 0, 57, 17))
time.drawsBackground = false
time.isBezeled = false
time.isBordered = false
time.isSelectable = false
time.stringValue = data[point].components(separatedBy: ";")[0]
addSubview(time)
// Time line
let timePath: NSBezierPath = NSBezierPath()
timePath.move(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(5)))
timePath.line(to: NSPoint(x: CGFloat(10 + point*2 + offset), y: CGFloat(107)))
timePaths.append(timePath)
}
if (point+offset/2) % 100 == 0 {
OperationQueue.main.addOperation {
//self.indicator.increment(by: 100)
}
}
}
// Put view in display
OperationQueue.main.addOperation {
//self.indicator.isHidden = true
self.content.addSubview(self)
self.setNeedsDisplay(self.bounds)
}
OperationQueue.main.waitUntilAllOperationsAreFinished()
}
// MARK: - Path related
func addPath(_ level: Double, threshold_level: Double) {
if path.elementCount == 0 {
path.move(to: NSMakePoint(CGFloat(10 + lastTime), CGFloat(level + zeroOffset)))
} else {
path.line(to: NSMakePoint(CGFloat(10 + lastTime), CGFloat(level + zeroOffset)))
}
lastTime += 2
if threshold.elementCount == 0 {
threshold.move(to: NSMakePoint(CGFloat(10 + lastTimeThreshold), CGFloat(threshold_level + zeroOffset)))
} else {
threshold.line(to: NSMakePoint(CGFloat(10 + lastTimeThreshold), CGFloat(threshold_level + zeroOffset)))
}
lastTimeThreshold += 2
}
func skipPath() {
path.move(to: NSMakePoint(CGFloat(10 + lastTime), CGFloat(zeroOffset)))
lastTime += 2
threshold.move(to: NSMakePoint(CGFloat(10 + lastTimeThreshold), CGFloat(zeroOffset)))
lastTimeThreshold += 2
}
func restartPath(_ level: Double, threshold_level: Double) {
path.move(to: NSMakePoint(CGFloat(10 + lastTime), CGFloat(level + 37)))
lastTime += 2
threshold.move(to: NSMakePoint(CGFloat(10 + lastTimeThreshold), CGFloat(threshold_level + zeroOffset)))
lastTimeThreshold += 2
}
// MARK: - Mouse Events
override func mouseMoved(with event: NSEvent) {
cursor.removeAllPoints()
popover.performClose(self)
let x: Int = Int(event.locationInWindow.x - 20 + (self.superview!.superview!.superview! as! NSScrollView).documentVisibleRect.origin.x)
cursor.move(to: NSPoint(x: x - x%2, y: 0))
cursor.line(to: NSPoint(x: x - x%2, y: FrequencyGraph.graphSize))
setNeedsDisplay(self.bounds)
}
override func mouseExited(with event: NSEvent) {
cursor.removeAllPoints()
popover.performClose(self)
setNeedsDisplay(self.bounds)
}
override func mouseDown(with event: NSEvent) {
let x: Int = Int(event.locationInWindow.x - 20 + (self.superview!.superview!.superview! as! NSScrollView).documentVisibleRect.origin.x)
if 10 <= x && (x-10)/2 - offset/2 < data.count && (x-10)/2 - offset/2 >= 0 {
(popover.contentViewController! as! GraphDetailsController).freq_str = "\(roundToPlaces(1, input: frequency)) MHz"
(popover.contentViewController! as! GraphDetailsController).time_str = "\(data[(x-10) / 2 - offset / 2].components(separatedBy: ";")[0])"
(popover.contentViewController! as! GraphDetailsController).power_str = "\(data[(x-10) / 2 - offset / 2].components(separatedBy: ";")[1]) dBmV"
if upstream {
(popover.contentViewController! as! GraphDetailsController).snr_str = "\(data[(x-10) / 2 - offset / 2].components(separatedBy: ";")[2]) dBmV"
(popover.contentViewController! as! GraphDetailsController).ranging_str = "\(data[(x-10) / 2 - offset / 2].components(separatedBy: ";")[3])"
} else {
(popover.contentViewController! as! GraphDetailsController).snr_str = "\(data[(x-10) / 2 - offset / 2].components(separatedBy: ";")[2]) dB"
}
popover.show(relativeTo: NSMakeRect(CGFloat(x), 0, 2, CGFloat(FrequencyGraph.graphSize)), of: self, preferredEdge: .minY)
}
}
override func scrollWheel(with event: NSEvent) {
super.scrollWheel(with: event)
cursor.removeAllPoints()
popover.performClose(self)
setNeedsDisplay(self.bounds)
}
// MARK: - Helper
func roundToPlaces(_ places:Int, input: Double) -> Double {
let divisor = pow(10.0, Double(places))
return round(input * divisor) / divisor
}
}

View File

@ -10,7 +10,8 @@ import Cocoa
class GraphWindow: NSWindowController {
var collectionViewItem: CollectionViewItemMonth?
var collectionViewItem: CollectionViewItemMonth!
@IBOutlet var scrollView: NSScrollView!
override var windowNibName: String! {
return "GraphWindow"
@ -28,6 +29,47 @@ class GraphWindow: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
var upstreamFiles: [FileWrapper] = []
var downstreamFiles: [FileWrapper] = []
guard collectionViewItem.dayFW != nil else { return }
for file in (collectionViewItem.dayFW?.fileWrappers)! {
if file.key.contains("Upstream") {
upstreamFiles.append(file.value)
} else if file.key.contains("Downstream") {
downstreamFiles.append(file.value)
}
}
let content: FlippedView = FlippedView(frame: NSMakeRect(0, 0, CGFloat(FrequencyGraph.maxGraphSize), CGFloat(((upstreamFiles.count + downstreamFiles.count) * FrequencyGraph.graphSizeWithSeparator)-1)))
scrollView.documentView = content
var numGraphs: Int = 0
for item in upstreamFiles {
let graph: FrequencyGraph = FrequencyGraph(upstream: true, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content)
graph.dataLoss = collectionViewItem.distribution
graph.data = FileOperations.loadUpstream(log: item.regularFileContents! as NSData)!
let keyString: String = item.filename!.components(separatedBy: " ")[1]
graph.frequency = Double(keyString.substring(to: keyString.index(keyString.endIndex, offsetBy: -4)))! / 1000000
let opQueue: OperationQueue = OperationQueue()
opQueue.addOperation {
graph.initView()
}
numGraphs += 1
}
for item in downstreamFiles {
let graph: FrequencyGraph = FrequencyGraph(upstream: false, frame: NSMakeRect(0, CGFloat(numGraphs * FrequencyGraph.graphSizeWithSeparator), CGFloat(FrequencyGraph.maxGraphSize), CGFloat(FrequencyGraph.graphSize)), superview: content)
graph.dataLoss = collectionViewItem.distribution
graph.data = FileOperations.loadDownstream(log: item.regularFileContents! as NSData)!
let keyString: String = item.filename!.components(separatedBy: " ")[1]
graph.frequency = Double(keyString.substring(to: keyString.index(keyString.endIndex, offsetBy: -4)))! / 1000000
let opQueue: OperationQueue = OperationQueue()
opQueue.addOperation {
graph.initView()
}
numGraphs += 1
}
}
}

View File

@ -8,6 +8,7 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="GraphWindow" customModule="Graphic_Analysis_2" customModuleProvider="target">
<connections>
<outlet property="scrollView" destination="N7f-tq-7VU" id="e94-84-TFe"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
@ -21,6 +22,31 @@
<view key="contentView" wantsLayer="YES" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" translatesAutoresizingMaskIntoConstraints="NO" id="N7f-tq-7VU">
<rect key="frame" x="20" y="20" width="440" height="251"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<clipView key="contentView" ambiguous="YES" id="cR7-yI-MsB">
<rect key="frame" x="1" y="1" width="438" height="249"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Aer-4J-rbN">
<rect key="frame" x="0.0" y="0.0" width="423" height="234"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
</subviews>
<color key="backgroundColor" name="disabledControlTextColor" catalog="System" colorSpace="catalog"/>
</clipView>
<scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="zjd-Nw-zvr">
<rect key="frame" x="1" y="234" width="438" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="Aon-x3-aqt">
<rect key="frame" x="423" y="1" width="16" height="249"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>

View File

@ -44,7 +44,7 @@
<key>CFBundleShortVersionString</key>
<string>2.1</string>
<key>CFBundleVersion</key>
<string>424</string>
<string>454</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>

View File

@ -1,2 +1,2 @@
version 2.1
build 424
build 454