Implement upload monitor, fix caterina timings
This commit is contained in:
parent
de93b9e2a9
commit
533471fba8
|
@ -3,7 +3,7 @@
|
||||||
// AVRsack
|
// AVRsack
|
||||||
//
|
//
|
||||||
// Created by Matthias Neeracher on 11/24/14.
|
// Created by Matthias Neeracher on 11/24/14.
|
||||||
// Copyright © 2014 Aere Perennius. All rights reserved.
|
// Copyright © 2014-2015 Aere Perennius. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
@ -99,18 +99,29 @@ class ASBuilder {
|
||||||
task!.launch()
|
task!.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadProject(board: String, programmer: String, port: String) {
|
func uploadProject(board: String, programmer: String, port: String, terminal: Bool = false) {
|
||||||
|
let portPath = ASSerial.fileNameForPort(port)
|
||||||
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
|
let toolChain = (NSApplication.sharedApplication().delegate as ASApplication).preferences.toolchainPath
|
||||||
task = NSTask()
|
task = NSTask()
|
||||||
task!.currentDirectoryPath = dir.path!
|
task!.currentDirectoryPath = dir.path!
|
||||||
task!.launchPath = toolChain+"/bin/avrdude"
|
task!.launchPath = toolChain+"/bin/avrdude"
|
||||||
|
|
||||||
let fileManager = NSFileManager.defaultManager()
|
let fileManager = NSFileManager.defaultManager()
|
||||||
let logURL = dir.URLByAppendingPathComponent("build/upload.log")
|
var logOut : NSFileHandle
|
||||||
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
|
if terminal {
|
||||||
let logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
|
let inputPipe = NSPipe()
|
||||||
task!.standardOutput = logOut
|
let outputPipe = NSPipe()
|
||||||
task!.standardError = logOut
|
logOut = outputPipe.fileHandleForWriting
|
||||||
|
task!.standardInput = inputPipe
|
||||||
|
task!.standardOutput = outputPipe
|
||||||
|
task!.standardError = outputPipe
|
||||||
|
} else {
|
||||||
|
let logURL = dir.URLByAppendingPathComponent("build/upload.log")
|
||||||
|
fileManager.createFileAtPath(logURL.path!, contents: NSData(), attributes: nil)
|
||||||
|
logOut = NSFileHandle(forWritingAtPath: logURL.path!)!
|
||||||
|
task!.standardOutput = logOut
|
||||||
|
task!.standardError = logOut
|
||||||
|
}
|
||||||
|
|
||||||
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
let libPath = (ASLibraries.instance().directories as NSArray).componentsJoinedByString(":")
|
||||||
let boardProp = ASHardware.instance().boards[board]!
|
let boardProp = ASHardware.instance().boards[board]!
|
||||||
|
@ -123,8 +134,12 @@ class ASBuilder {
|
||||||
var args = Array<String>(count: verbosity, repeatedValue: "-v")
|
var args = Array<String>(count: verbosity, repeatedValue: "-v")
|
||||||
args += [
|
args += [
|
||||||
"-C", toolChain+"/etc/avrdude.conf",
|
"-C", toolChain+"/etc/avrdude.conf",
|
||||||
"-p", boardProp["build.mcu"]!, "-c", proto!, "-P", port,
|
"-p", boardProp["build.mcu"]!, "-c", proto!, "-P", portPath]
|
||||||
"-U", "flash:w:build/"+board+"/"+dir.lastPathComponent+".hex:i"]
|
if terminal {
|
||||||
|
args += ["-t"]
|
||||||
|
} else {
|
||||||
|
args += ["-U", "flash:w:build/"+board+"/"+dir.lastPathComponent+".hex:i"]
|
||||||
|
}
|
||||||
if speed != nil {
|
if speed != nil {
|
||||||
args.append("-b")
|
args.append("-b")
|
||||||
args.append(speed!)
|
args.append(speed!)
|
||||||
|
@ -135,13 +150,15 @@ class ASBuilder {
|
||||||
//
|
//
|
||||||
if leonardish {
|
if leonardish {
|
||||||
if verbosity > 0 {
|
if verbosity > 0 {
|
||||||
logOut.writeData("Opening \(port) at 1200 baud\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
logOut.writeData("Opening port \(port) at 1200 baud\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
||||||
}
|
}
|
||||||
if let dummyConnection = ASSerial.openPort(port, withSpeed: 1200) {
|
if let dummyConnection = ASSerial.openPort(portPath, withSpeed: 1200) {
|
||||||
close(dummyConnection.fileDescriptor)
|
usleep(50000)
|
||||||
|
ASSerial.closePort(dummyConnection.fileDescriptor)
|
||||||
|
sleep(1)
|
||||||
for (var retry=0; retry < 40; ++retry) {
|
for (var retry=0; retry < 40; ++retry) {
|
||||||
usleep(250000)
|
usleep(250000)
|
||||||
if (NSFileManager.defaultManager().fileExistsAtPath(port)) {
|
if (fileManager.fileExistsAtPath(portPath)) {
|
||||||
if verbosity > 0 {
|
if verbosity > 0 {
|
||||||
logOut.writeData("Found port \(port) after \(retry) attempts.\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
logOut.writeData("Found port \(port) after \(retry) attempts.\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
||||||
}
|
}
|
||||||
|
@ -154,6 +171,11 @@ class ASBuilder {
|
||||||
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
logOut.writeData(cmdLine.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
|
||||||
task!.arguments = args;
|
task!.arguments = args;
|
||||||
task!.launch()
|
task!.launch()
|
||||||
|
if terminal {
|
||||||
|
let intSpeed = speed?.toInt() ?? 19200
|
||||||
|
ASSerialWin.showWindowWithPort(port, task:task!, speed:intSpeed)
|
||||||
|
task = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func disassembleProject(board: String) {
|
func disassembleProject(board: String) {
|
||||||
|
|
|
@ -475,12 +475,16 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
dispatch_async(dispatch_get_main_queue(), {
|
dispatch_async(dispatch_get_main_queue(), {
|
||||||
self.builder.uploadProject(self.board, programmer:self.programmer, port:ASSerial.fileNameForPort(self.port))
|
self.builder.uploadProject(self.board, programmer:self.programmer, port:self.port)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
buildProject(sender)
|
buildProject(sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func uploadTerminal(sender: AnyObject) {
|
||||||
|
builder.uploadProject(board, programmer:programmer, port:port, terminal:true)
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func disassembleProject(sender: AnyObject) {
|
@IBAction func disassembleProject(sender: AnyObject) {
|
||||||
builder.continuation = {
|
builder.continuation = {
|
||||||
self.selectNodeInOutline(self.files.disassembly)
|
self.selectNodeInOutline(self.files.disassembly)
|
||||||
|
|
|
@ -22,5 +22,6 @@ extern NSString * kASSerialPortsChanged;
|
||||||
+ (NSArray *) ports;
|
+ (NSArray *) ports;
|
||||||
+ (NSFileHandle *)openPort:(NSString *) port withSpeed:(int)speed;
|
+ (NSFileHandle *)openPort:(NSString *) port withSpeed:(int)speed;
|
||||||
+ (void)restorePort:(int)fileDescriptor;
|
+ (void)restorePort:(int)fileDescriptor;
|
||||||
|
+ (void)closePort:(int)fileDescriptor;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -79,7 +79,6 @@ NSString * kASSerialPortsChanged = @"PortsChanged";
|
||||||
savedAttrs = [NSMutableDictionary dictionary];
|
savedAttrs = [NSMutableDictionary dictionary];
|
||||||
}
|
}
|
||||||
[savedAttrs setObject:[NSData dataWithBytes:&origAttr length:sizeof(origAttr)] forKey:[NSNumber numberWithInt:fd]];
|
[savedAttrs setObject:[NSData dataWithBytes:&origAttr length:sizeof(origAttr)] forKey:[NSNumber numberWithInt:fd]];
|
||||||
|
|
||||||
return [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:NO];
|
return [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:NO];
|
||||||
failed:
|
failed:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -95,4 +94,9 @@ failed:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)closePort:(int)fileDescriptor {
|
||||||
|
NSNumber * fd = [NSNumber numberWithInt:fileDescriptor];
|
||||||
|
close(fileDescriptor);
|
||||||
|
[savedAttrs removeObjectForKey:fd];
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -37,12 +37,14 @@ class ASSerialWin: NSWindowController {
|
||||||
var port = ""
|
var port = ""
|
||||||
var serialData = ""
|
var serialData = ""
|
||||||
var serialObserver : AnyObject!
|
var serialObserver : AnyObject!
|
||||||
|
var termination : AnyObject!
|
||||||
dynamic var portHandle : NSFileHandle?
|
dynamic var portHandle : NSFileHandle?
|
||||||
var currentTheme : UInt = 0
|
var currentTheme : UInt = 0
|
||||||
var fontSize : UInt = 12
|
var fontSize : UInt = 12
|
||||||
var portDefaults = [String: AnyObject]()
|
var portDefaults = [String: AnyObject]()
|
||||||
var shouldReconnect = false
|
var shouldReconnect = false
|
||||||
|
dynamic var task : NSTask?
|
||||||
|
|
||||||
class func showWindowWithPort(port: String) {
|
class func showWindowWithPort(port: String) {
|
||||||
if let existing = serialInstances[port] {
|
if let existing = serialInstances[port] {
|
||||||
existing.showWindow(self)
|
existing.showWindow(self)
|
||||||
|
@ -52,6 +54,15 @@ class ASSerialWin: NSWindowController {
|
||||||
newInstance.showWindow(self)
|
newInstance.showWindow(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class func showWindowWithPort(port: String, task: NSTask, speed: Int) {
|
||||||
|
if let existing = serialInstances[port] {
|
||||||
|
existing.showWindowWithTask(task, speed:speed)
|
||||||
|
} else {
|
||||||
|
let newInstance = ASSerialWin(port:port)
|
||||||
|
serialInstances[port] = newInstance
|
||||||
|
newInstance.showWindowWithTask(task, speed:speed)
|
||||||
|
}
|
||||||
|
}
|
||||||
class func portNeededForUpload(port: String) {
|
class func portNeededForUpload(port: String) {
|
||||||
if let existing = serialInstances[port] {
|
if let existing = serialInstances[port] {
|
||||||
existing.disconnectTemporarily()
|
existing.disconnectTemporarily()
|
||||||
|
@ -97,18 +108,38 @@ class ASSerialWin: NSWindowController {
|
||||||
self.willChangeValueForKey("hasValidPort")
|
self.willChangeValueForKey("hasValidPort")
|
||||||
self.didChangeValueForKey("hasValidPort")
|
self.didChangeValueForKey("hasValidPort")
|
||||||
|
|
||||||
if self.hasValidPort {
|
if self.task == nil {
|
||||||
self.reconnect()
|
if self.hasValidPort {
|
||||||
} else {
|
self.reconnect()
|
||||||
self.disconnectTemporarily()
|
} else {
|
||||||
|
self.disconnectTemporarily()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
termination = NSNotificationCenter.defaultCenter().addObserverForName(NSTaskDidTerminateNotification,
|
||||||
|
object: nil, queue: nil, usingBlock:
|
||||||
|
{ (notification: NSNotification!) in
|
||||||
|
if notification.object as? NSTask == self.task {
|
||||||
|
self.task = nil
|
||||||
|
self.portHandle = nil
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override func finalize() {
|
override func finalize() {
|
||||||
|
if portHandle != nil {
|
||||||
|
connect(self)
|
||||||
|
}
|
||||||
NSNotificationCenter.defaultCenter().removeObserver(serialObserver)
|
NSNotificationCenter.defaultCenter().removeObserver(serialObserver)
|
||||||
|
NSNotificationCenter.defaultCenter().removeObserver(termination)
|
||||||
serialInstances.removeValueForKey(port)
|
serialInstances.removeValueForKey(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func windowWillClose(notification: NSNotification) {
|
||||||
|
if portHandle != nil {
|
||||||
|
connect(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func windowDidLoad() {
|
override func windowDidLoad() {
|
||||||
logView.setReadOnly(true)
|
logView.setReadOnly(true)
|
||||||
|
@ -119,13 +150,28 @@ class ASSerialWin: NSWindowController {
|
||||||
logView.setMode(UInt(ACEModeText))
|
logView.setMode(UInt(ACEModeText))
|
||||||
logView.alphaValue = 0.8
|
logView.alphaValue = 0.8
|
||||||
window?.title = port
|
window?.title = port
|
||||||
connect(self)
|
if task == nil {
|
||||||
|
connect(self)
|
||||||
|
}
|
||||||
super.windowDidLoad()
|
super.windowDidLoad()
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func selectPort(item: AnyObject) {
|
func installReader(handle: NSFileHandle?) {
|
||||||
port = (item as NSPopUpButton).titleOfSelectedItem!
|
if let readHandle = handle {
|
||||||
window?.title = port
|
serialData = ""
|
||||||
|
logView.setString(serialData)
|
||||||
|
readHandle.readabilityHandler = {(handle) in
|
||||||
|
let newData = handle.availableDataIgnoringExceptions()
|
||||||
|
let newString = NSString(data: newData, encoding: NSASCIIStringEncoding)!
|
||||||
|
self.serialData += newString
|
||||||
|
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
||||||
|
self.logView.setString(self.serialData)
|
||||||
|
if self.scrollToBottom {
|
||||||
|
self.logView.gotoLine(1000000000, column: 0, animated: true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func sendInput(AnyObject) {
|
@IBAction func sendInput(AnyObject) {
|
||||||
|
@ -134,29 +180,29 @@ class ASSerialWin: NSWindowController {
|
||||||
portHandle?.writeData(data)
|
portHandle?.writeData(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showWindowWithTask(task: NSTask, speed:Int) {
|
||||||
|
if portHandle != nil {
|
||||||
|
connect(self)
|
||||||
|
}
|
||||||
|
baudRate = speed
|
||||||
|
self.task = task
|
||||||
|
portHandle = (task.standardInput as NSPipe).fileHandleForWriting
|
||||||
|
showWindow(self)
|
||||||
|
installReader((task.standardOutput as? NSPipe)?.fileHandleForReading)
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func connect(AnyObject) {
|
@IBAction func connect(AnyObject) {
|
||||||
shouldReconnect = false
|
shouldReconnect = false
|
||||||
if portHandle != nil {
|
if task != nil {
|
||||||
ASSerial.restorePort(portHandle!.fileDescriptor)
|
task!.interrupt()
|
||||||
portHandle!.closeFile()
|
} else if portHandle != nil {
|
||||||
|
let fd = portHandle!.fileDescriptor
|
||||||
|
ASSerial.restorePort(fd)
|
||||||
|
ASSerial.closePort(fd)
|
||||||
portHandle = nil
|
portHandle = nil
|
||||||
} else {
|
} else {
|
||||||
portHandle = ASSerial.openPort(port, withSpeed: Int32(baudRate))
|
portHandle = ASSerial.openPort(port, withSpeed: Int32(baudRate))
|
||||||
if portHandle != nil {
|
installReader(portHandle)
|
||||||
serialData = ""
|
|
||||||
logView.setString(serialData)
|
|
||||||
portHandle!.readabilityHandler = {(handle) in
|
|
||||||
let newData = handle.availableDataIgnoringExceptions()
|
|
||||||
let newString = NSString(data: newData, encoding: NSASCIIStringEncoding)!
|
|
||||||
self.serialData += newString
|
|
||||||
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
|
||||||
self.logView.setString(self.serialData)
|
|
||||||
if self.scrollToBottom {
|
|
||||||
self.logView.gotoLine(1000000000, column: 0, animated: true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func disconnectTemporarily() {
|
func disconnectTemporarily() {
|
||||||
|
@ -234,7 +280,7 @@ class ASSerialWin: NSWindowController {
|
||||||
func updatePortDefaults() {
|
func updatePortDefaults() {
|
||||||
let userDefaults = NSUserDefaults.standardUserDefaults()
|
let userDefaults = NSUserDefaults.standardUserDefaults()
|
||||||
let serialDefaults = NSMutableDictionary(dictionary:userDefaults.objectForKey("SerialDefaults") as NSDictionary)
|
let serialDefaults = NSMutableDictionary(dictionary:userDefaults.objectForKey("SerialDefaults") as NSDictionary)
|
||||||
serialDefaults.setValue(portDefaults, forKey:port)
|
serialDefaults.setValue(NSDictionary(dictionary:portDefaults), forKey:port)
|
||||||
userDefaults.setObject(serialDefaults, forKey:"SerialDefaults")
|
userDefaults.setObject(serialDefaults, forKey:"SerialDefaults")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,17 @@
|
||||||
</customObject>
|
</customObject>
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="F0z-JX-Cv5">
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||||
<rect key="contentRect" x="196" y="240" width="751" height="403"/>
|
<rect key="contentRect" x="196" y="240" width="751" height="403"/>
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||||
<view key="contentView" id="se5-gp-TjO">
|
<view key="contentView" id="se5-gp-TjO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="751" height="403"/>
|
<rect key="frame" x="0.0" y="0.0" width="751" height="403"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rIR-2b-lAh">
|
<textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rIR-2b-lAh">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="651" height="22"/>
|
<rect key="frame" x="0.0" y="0.0" width="651" height="22"/>
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="height" constant="22" id="Y1V-fL-RCq"/>
|
|
||||||
</constraints>
|
|
||||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="EBj-i4-UsA">
|
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="EBj-i4-UsA">
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
@ -42,12 +39,12 @@
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MOe-eO-fyb">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MOe-eO-fyb">
|
||||||
<rect key="frame" x="651" y="-1" width="50" height="22"/>
|
<rect key="frame" x="651" y="0.0" width="50" height="20"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="20" id="eLx-yy-gCn"/>
|
<constraint firstAttribute="height" constant="20" id="eLx-yy-gCn"/>
|
||||||
<constraint firstAttribute="width" constant="50" id="vaT-Kd-3pn"/>
|
<constraint firstAttribute="width" constant="50" id="vaT-Kd-3pn"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<buttonCell key="cell" type="smallSquare" title="Send" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Xt6-lT-b4z">
|
<buttonCell key="cell" type="square" title="Send" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Xt6-lT-b4z">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
|
@ -61,18 +58,15 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H05-Rp-UzR">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H05-Rp-UzR">
|
||||||
<rect key="frame" x="701" y="-1" width="50" height="22"/>
|
<rect key="frame" x="701" y="0.0" width="50" height="20"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="50" id="FWw-BQ-WKa"/>
|
<constraint firstAttribute="width" constant="50" id="FWw-BQ-WKa"/>
|
||||||
<constraint firstAttribute="height" constant="20" id="s7i-ZT-S7W"/>
|
<constraint firstAttribute="height" constant="20" id="s7i-ZT-S7W"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<buttonCell key="cell" type="smallSquare" title="Now" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vZ4-fd-aE8">
|
<buttonCell key="cell" type="square" title="Now" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vZ4-fd-aE8">
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
<font key="font" metaFont="system"/>
|
<font key="font" metaFont="system"/>
|
||||||
</buttonCell>
|
</buttonCell>
|
||||||
<connections>
|
|
||||||
<binding destination="-2" name="value" keyPath="scrollToBottom" id="xlw-TM-qoV"/>
|
|
||||||
</connections>
|
|
||||||
</button>
|
</button>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YB5-mV-vY7">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YB5-mV-vY7">
|
||||||
<rect key="frame" x="128" y="374" width="35" height="19"/>
|
<rect key="frame" x="128" y="374" width="35" height="19"/>
|
||||||
|
@ -132,6 +126,11 @@
|
||||||
</popUpButtonCell>
|
</popUpButtonCell>
|
||||||
<connections>
|
<connections>
|
||||||
<binding destination="-2" name="selectedTag" keyPath="baudRate" id="pDO-CA-0VU"/>
|
<binding destination="-2" name="selectedTag" keyPath="baudRate" id="pDO-CA-0VU"/>
|
||||||
|
<binding destination="-2" name="enabled" keyPath="task" id="plM-ZJ-GjO">
|
||||||
|
<dictionary key="options">
|
||||||
|
<string key="NSValueTransformerName">NSIsNil</string>
|
||||||
|
</dictionary>
|
||||||
|
</binding>
|
||||||
</connections>
|
</connections>
|
||||||
</popUpButton>
|
</popUpButton>
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="r6K-Jm-mZe">
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="r6K-Jm-mZe">
|
||||||
|
@ -191,6 +190,7 @@
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
||||||
|
<outlet property="initialFirstResponder" destination="rIR-2b-lAh" id="NJo-kw-Ewt"/>
|
||||||
</connections>
|
</connections>
|
||||||
<point key="canvasLocation" x="271.5" y="416.5"/>
|
<point key="canvasLocation" x="271.5" y="416.5"/>
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -395,6 +395,11 @@
|
||||||
<action selector="uploadProject:" target="-1" id="Un4-q1-nWg"/>
|
<action selector="uploadProject:" target="-1" id="Un4-q1-nWg"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Upload Terminal" keyEquivalent="U" id="jAF-od-ZFb">
|
||||||
|
<connections>
|
||||||
|
<action selector="uploadTerminal:" target="-1" id="hth-ZZ-S3I"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
<menuItem title="Serial Monitor" id="GxC-cS-qvx">
|
<menuItem title="Serial Monitor" id="GxC-cS-qvx">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
<menu key="submenu" title="Serial Monitor" id="i2j-Ds-oRH">
|
<menu key="submenu" title="Serial Monitor" id="i2j-Ds-oRH">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user