first add sdk
17
tools/uart_adapter/app/iOS/uartadapter/AppDelegate.h
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 8/26/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
45
tools/uart_adapter/app/iOS/uartadapter/AppDelegate.m
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// AppDelegate.m
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 8/26/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
||||
42
tools/uart_adapter/app/iOS/uartadapter/Base.lproj/LaunchScreen.xib
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 realtek. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Realtek" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
256
tools/uart_adapter/app/iOS/uartadapter/Base.lproj/Main.storyboard
Executable file
|
|
@ -0,0 +1,256 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="1Pd-eg-9KV">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="Z5v-pO-fDj">
|
||||
<objects>
|
||||
<navigationController definesPresentationContext="YES" id="1Pd-eg-9KV" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="3C6-QB-18H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="Ncl-Ly-ig6" kind="relationship" relationship="rootViewController" id="Wkd-LN-Ngo"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="vuA-ba-keF" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-150.40000000000001" y="208.26666666666665"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="MS6-5N-OFm">
|
||||
<objects>
|
||||
<collectionViewController autoresizesArchivedViewToFullSize="NO" clearsSelectionOnViewWillAppear="NO" id="Ncl-Ly-ig6" customClass="ViewController" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" dataMode="prototypes" id="e7m-gh-n99">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.79215693473815918" green="0.97254908084869385" blue="0.85098046064376831" alpha="1" colorSpace="deviceRGB"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="qjF-PG-Xfp">
|
||||
<size key="itemSize" width="155" height="149"/>
|
||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cellID" id="ZOT-Jp-0u5" customClass="Cell">
|
||||
<rect key="frame" x="0.0" y="64" width="155" height="149"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="155" height="149"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="JUJ-aT-Vg2">
|
||||
<rect key="frame" x="0.0" y="120" width="155" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="10"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" id="l8r-Fv-CoH">
|
||||
<rect key="frame" x="25" y="13" width="106" height="104"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="image" destination="l8r-Fv-CoH" id="9Cu-iE-zAT"/>
|
||||
<outlet property="label" destination="JUJ-aT-Vg2" id="h6D-S5-rXw"/>
|
||||
</connections>
|
||||
</collectionViewCell>
|
||||
</cells>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Ncl-Ly-ig6" id="CTs-Vx-EvJ"/>
|
||||
<outlet property="delegate" destination="Ncl-Ly-ig6" id="nWX-TH-lIf"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
<navigationItem key="navigationItem" id="ce6-Wp-ltA">
|
||||
<nil key="title"/>
|
||||
<barButtonItem key="rightBarButtonItem" style="done" id="2oE-Kv-sfo">
|
||||
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="Q3E-M5-mSe">
|
||||
<rect key="frame" x="269" y="7" width="35" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Scan">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="scanButton" destination="Ncl-Ly-ig6" eventType="touchUpInside" id="YyT-5V-CXa"/>
|
||||
</connections>
|
||||
</button>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<segue destination="YFM-wW-kmf" kind="push" identifier="showDetail" id="u0H-uv-HwD"/>
|
||||
<segue destination="oWX-tt-vKZ" kind="push" identifier="showSetting" id="948-TD-nhp"/>
|
||||
</connections>
|
||||
</collectionViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="OOw-UZ-8Yt" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="243" y="208"/>
|
||||
</scene>
|
||||
<!--Setting Page View Controller-->
|
||||
<scene sceneID="PDn-ND-rhY">
|
||||
<objects>
|
||||
<viewController id="oWX-tt-vKZ" customClass="SettingPageViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Dpb-L4-mnY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Serial Port Setup" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="UUa-Hs-pNl">
|
||||
<rect key="frame" x="68" y="72" width="185" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Baud Rate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Zwm-F2-aef">
|
||||
<rect key="frame" x="16" y="126" width="89" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Parity Bit" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="K3d-Js-h4x">
|
||||
<rect key="frame" x="16" y="285" width="89" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stop Bit" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="NEj-Sy-XUA">
|
||||
<rect key="frame" x="16" y="364" width="89" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Data Bit" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8Qx-J6-Ohg">
|
||||
<rect key="frame" x="16" y="207" width="89" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="EMe-Jg-qG8">
|
||||
<rect key="frame" x="182" y="501" width="66" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Apply">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="saveSettings" destination="oWX-tt-vKZ" eventType="touchUpInside" id="vNL-h1-Wla"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Flow Control" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dRn-mU-pEL">
|
||||
<rect key="frame" x="20" y="444" width="106" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="2" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" id="bFa-tH-gKE">
|
||||
<rect key="frame" x="129" y="276" width="172" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="3" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" id="qQL-8R-FG9">
|
||||
<rect key="frame" x="128" y="355" width="172" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Not Support" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" id="1xk-ab-wen">
|
||||
<rect key="frame" x="129" y="435" width="172" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" id="jzD-fD-Enl">
|
||||
<rect key="frame" x="129" y="117" width="172" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<textField opaque="NO" clipsSubviews="YES" tag="1" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" id="mpK-rA-jHO">
|
||||
<rect key="frame" x="129" y="198" width="172" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="79g-JQ-I6P">
|
||||
<rect key="frame" x="69" y="501" width="66" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Restore">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="restoreSettings" destination="oWX-tt-vKZ" eventType="touchUpInside" id="fjO-FY-ZIz"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.79215693470000004" green="0.97254908080000002" blue="0.85098046059999999" alpha="1" colorSpace="deviceRGB"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="YOa-9T-3sQ"/>
|
||||
<connections>
|
||||
<outlet property="StopBitField" destination="qQL-8R-FG9" id="cm0-Cz-z6n"/>
|
||||
<outlet property="baudRateField" destination="jzD-fD-Enl" id="7jg-ka-vX1"/>
|
||||
<outlet property="dataBitField" destination="mpK-rA-jHO" id="fbH-Mv-wCK"/>
|
||||
<outlet property="parityBitField" destination="bFa-tH-gKE" id="g4N-Js-Fmb"/>
|
||||
<outlet property="stopBitField" destination="qQL-8R-FG9" id="dRr-xb-mwx"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="c2o-dX-yNd" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="707" y="556"/>
|
||||
</scene>
|
||||
<!--Chat View Controller-->
|
||||
<scene sceneID="72O-QX-vQv">
|
||||
<objects>
|
||||
<viewController id="YFM-wW-kmf" customClass="ChatViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" id="4Lr-nv-ban">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" id="OMp-fG-Ui9">
|
||||
<rect key="frame" x="16" y="530" width="222" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="yyF-WX-t25">
|
||||
<rect key="frame" x="258" y="529" width="46" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="SEND">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="sendMessage" destination="YFM-wW-kmf" eventType="touchUpInside" id="O1x-kX-9H2"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" placeholderIntrinsicWidth="320" placeholderIntrinsicHeight="457" editable="NO" id="cNU-xq-X0W">
|
||||
<rect key="frame" x="0.0" y="64" width="320" height="457"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.79215693470000004" green="0.97254908080000002" blue="0.85098046059999999" alpha="1" colorSpace="deviceRGB"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="f0I-FI-aV5"/>
|
||||
<connections>
|
||||
<outlet property="chatMessageField" destination="cNU-xq-X0W" id="QFT-cC-FdH"/>
|
||||
<outlet property="inputMessageField" destination="OMp-fG-Ui9" id="xES-Px-tg8"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="IiU-Ky-z4A" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="706" y="-96"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
16
tools/uart_adapter/app/iOS/uartadapter/Cell.h
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
Custom collection view cell for image and its label.
|
||||
*/
|
||||
|
||||
@import UIKit;
|
||||
|
||||
@interface Cell : UICollectionViewCell
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *image;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *label;
|
||||
|
||||
@end
|
||||
27
tools/uart_adapter/app/iOS/uartadapter/Cell.m
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
Custom collection view cell for image and its label.
|
||||
*/
|
||||
|
||||
#import "Cell.h"
|
||||
#import "CustomCellBackground.h"
|
||||
|
||||
@implementation Cell
|
||||
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if (self)
|
||||
{
|
||||
// change to our custom selected background view
|
||||
CustomCellBackground *backgroundView = [[CustomCellBackground alloc] initWithFrame:CGRectZero];
|
||||
self.selectedBackgroundView = backgroundView;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
32
tools/uart_adapter/app/iOS/uartadapter/ChatViewController.h
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
The secondary detailed view controller for this app.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ChatViewController : UIViewController <NSStreamDelegate, NSNetServiceBrowserDelegate, NSNetServiceDelegate, UITextFieldDelegate>
|
||||
{
|
||||
NSNetServiceBrowser *_netServiceBrowser;
|
||||
NSMutableArray *_servicesArray;
|
||||
|
||||
NSMutableArray *messages;
|
||||
NSInputStream *inputStream;
|
||||
NSOutputStream *outputStream;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSNetService *selectedService;
|
||||
@property (nonatomic, retain) NSMutableArray *dataServicesArray;
|
||||
|
||||
|
||||
@property (nonatomic, retain) NSInputStream *inputStream;
|
||||
@property (nonatomic, retain) NSOutputStream *outputStream;
|
||||
@property (nonatomic, retain) NSMutableArray *messages;
|
||||
|
||||
- (IBAction) sendMessage;
|
||||
@property (nonatomic, retain) IBOutlet UITextView *chatMessageField;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *inputMessageField;
|
||||
@end
|
||||
348
tools/uart_adapter/app/iOS/uartadapter/ChatViewController.m
Executable file
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
The secondary detailed view controller for this app.
|
||||
*/
|
||||
|
||||
|
||||
#import "ChatViewController.h"
|
||||
#include <ifaddrs.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@interface ChatViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation ChatViewController
|
||||
|
||||
@synthesize inputStream, outputStream;
|
||||
@synthesize inputMessageField,chatMessageField;
|
||||
@synthesize selectedService = _selectedService;
|
||||
@synthesize messages;
|
||||
|
||||
NSString *UART_DATA_TYPE=@"_uart_data._tcp.local.";
|
||||
NSDateFormatter *formatter;
|
||||
NSString *timeString;
|
||||
NSMutableAttributedString *attrMessage;
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
|
||||
UIGraphicsBeginImageContext(self.view.frame.size);
|
||||
[[UIImage imageNamed:@"background.png"] drawInRect:self.view.bounds];
|
||||
UIImage *bgImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
|
||||
self.chatMessageField.contentMode = UIViewContentModeScaleToFill;
|
||||
self.chatMessageField.backgroundColor=[UIColor colorWithPatternImage:bgImage];
|
||||
|
||||
|
||||
|
||||
self.dataServicesArray = [[NSMutableArray alloc] init];
|
||||
[self startDiscover:UART_DATA_TYPE];
|
||||
|
||||
|
||||
self.inputMessageField.delegate = self;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(keyboardWillShow:)
|
||||
name:@"UIKeyboardWillShowNotification"
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(keyboardDidHide:)
|
||||
name:@"UIKeyboardWillHideNotification"
|
||||
object:nil];
|
||||
formatter = [[NSDateFormatter alloc] init];
|
||||
[formatter setDateFormat:@"HH:mm"];
|
||||
|
||||
|
||||
NSAttributedString *objectString =
|
||||
[[NSAttributedString alloc] initWithString:@""
|
||||
attributes:@{
|
||||
NSForegroundColorAttributeName : [UIColor redColor],
|
||||
NSFontAttributeName : [UIFont boldSystemFontOfSize:20]
|
||||
}];
|
||||
|
||||
attrMessage = [[NSMutableAttributedString alloc] initWithAttributedString:objectString];
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) keyboardWillShow:(NSNotification *)note {
|
||||
NSDictionary *userInfo = [note userInfo];
|
||||
CGSize kbSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
|
||||
|
||||
|
||||
|
||||
// move the view up by 30 pts
|
||||
CGRect frame = self.view.frame;
|
||||
frame.origin.y = -kbSize.height;
|
||||
|
||||
[UIView animateWithDuration:0.01 animations:^{
|
||||
self.view.frame = frame;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) keyboardDidHide:(NSNotification *)note {
|
||||
|
||||
// move the view back to the origin
|
||||
CGRect frame = self.view.frame;
|
||||
frame.origin.y = 0;
|
||||
self.view.frame = frame;
|
||||
|
||||
}
|
||||
|
||||
-(void) startDiscover:(NSString *)browseType
|
||||
{
|
||||
self->_netServiceBrowser = [[NSNetServiceBrowser alloc] init];
|
||||
self->_netServiceBrowser.delegate = self;
|
||||
|
||||
NSArray *domainNameParts = [browseType componentsSeparatedByString:@"."];
|
||||
|
||||
browseType = [NSString stringWithFormat:@"%@.%@.", [domainNameParts objectAtIndex:0], [domainNameParts objectAtIndex:1]];
|
||||
|
||||
[self->_netServiceBrowser searchForServicesOfType:browseType inDomain:@""];
|
||||
}
|
||||
|
||||
|
||||
-(void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing {
|
||||
|
||||
[self.dataServicesArray addObject:aNetService];
|
||||
|
||||
|
||||
|
||||
if (moreComing == NO) {
|
||||
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
|
||||
[self.dataServicesArray sortUsingDescriptors:[NSArray arrayWithObject:sd]];
|
||||
//[sd release];
|
||||
|
||||
self->_netServiceBrowser.delegate = nil;
|
||||
[self->_netServiceBrowser stop];
|
||||
self->_netServiceBrowser = nil;
|
||||
self.title = self.selectedService.name;
|
||||
}
|
||||
|
||||
if([self.selectedService.name isEqualToString:aNetService.name])
|
||||
{
|
||||
aNetService.delegate = self;
|
||||
[aNetService resolveWithTimeout:10.0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-(void)netServiceDidResolveAddress:(NSNetService *)service {
|
||||
|
||||
NSData *address = [service.addresses objectAtIndex:0];
|
||||
char addressString[INET6_ADDRSTRLEN];
|
||||
int inetType;
|
||||
|
||||
struct sockaddr_in6 addr6;
|
||||
memcpy(&addr6, address.bytes, address.length);
|
||||
|
||||
if (address.length == 16) { // IPv4
|
||||
inetType = AF_INET;
|
||||
struct sockaddr_in addr4;
|
||||
memcpy(&addr4, address.bytes, address.length);
|
||||
inet_ntop(AF_INET, &addr4.sin_addr, addressString, 512);
|
||||
[self initNetworkCommunication:[NSString stringWithCString:addressString encoding:NSASCIIStringEncoding] Port:(int)service.port];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didRemoveService:(NSNetService *)netService moreComing:(BOOL)moreComing {
|
||||
for (int i = 0; i < self.dataServicesArray.count; i++) {
|
||||
if ([((NSNetService *)[self.dataServicesArray objectAtIndex:i]).name isEqualToString:netService.name]) {
|
||||
[self.dataServicesArray removeObjectAtIndex:i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (moreComing == NO) {
|
||||
|
||||
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
|
||||
[self.dataServicesArray sortUsingDescriptors:[NSArray arrayWithObject:sd]];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSNetServiceDelegate methods
|
||||
-(void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict {
|
||||
NSNumber *errorCode = [errorDict valueForKey:NSNetServicesErrorCode];
|
||||
|
||||
NSString *errorMessage;
|
||||
switch ([errorCode intValue]) {
|
||||
case NSNetServicesActivityInProgress:
|
||||
errorMessage = @"Service Resolution Currently in Progress. Please Wait.";
|
||||
break;
|
||||
case NSNetServicesTimeoutError:
|
||||
errorMessage = @"Service Resolution Timeout";
|
||||
[sender stop];
|
||||
//UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Bonjour Browser" message:errorMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
|
||||
// [alert show];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//[alert release];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSNetServiceBrowserDelegate methods
|
||||
-(void)netServiceBrowser:(NSNetServiceBrowser *)browser didNotSearch:(NSDictionary *)errorDict {
|
||||
self->_netServiceBrowser.delegate = nil;
|
||||
[self->_netServiceBrowser stop];
|
||||
self->_netServiceBrowser = nil;
|
||||
}
|
||||
|
||||
-(void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)browser {
|
||||
self->_netServiceBrowser.delegate = nil;
|
||||
self->_netServiceBrowser = nil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
- (void) initNetworkCommunication:(NSString *)mIP Port:(int)mPort {
|
||||
|
||||
CFReadStreamRef readStream;
|
||||
CFWriteStreamRef writeStream;
|
||||
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)mIP, mPort, &readStream, &writeStream);
|
||||
|
||||
inputStream = (__bridge NSInputStream *)readStream;
|
||||
outputStream = (__bridge NSOutputStream *)writeStream;
|
||||
[inputStream setDelegate:self];
|
||||
[outputStream setDelegate:self];
|
||||
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
[inputStream open];
|
||||
[outputStream open];
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (IBAction) sendMessage {
|
||||
NSAttributedString *sendingString;
|
||||
|
||||
timeString = [formatter stringFromDate:[NSDate date]];
|
||||
|
||||
NSString *response = [NSString stringWithFormat:@"%@\n", inputMessageField.text];
|
||||
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
|
||||
[outputStream write:[data bytes] maxLength:[data length]];
|
||||
response = [NSString stringWithFormat:@"%@ [Me] %@\n",timeString, inputMessageField.text];
|
||||
sendingString =
|
||||
[[NSAttributedString alloc] initWithString:response
|
||||
attributes:@{
|
||||
NSForegroundColorAttributeName : [UIColor blueColor],
|
||||
NSFontAttributeName : [UIFont boldSystemFontOfSize:20]
|
||||
}];
|
||||
inputMessageField.text = @"";
|
||||
[attrMessage appendAttributedString:sendingString];
|
||||
[chatMessageField setAttributedText:attrMessage];
|
||||
[inputMessageField resignFirstResponder];
|
||||
}
|
||||
|
||||
|
||||
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
|
||||
|
||||
|
||||
|
||||
switch (streamEvent) {
|
||||
|
||||
case NSStreamEventOpenCompleted:
|
||||
NSLog(@"Stream opened");
|
||||
break;
|
||||
case NSStreamEventHasBytesAvailable:
|
||||
|
||||
if (theStream == inputStream) {
|
||||
|
||||
uint8_t buffer[1024];
|
||||
int len;
|
||||
|
||||
while ([inputStream hasBytesAvailable]) {
|
||||
len = [[NSNumber numberWithInteger:[inputStream read:buffer maxLength: sizeof(buffer)]] intValue] ;
|
||||
if (len > 0) {
|
||||
|
||||
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
|
||||
|
||||
if (nil != output) {
|
||||
|
||||
|
||||
[self messageReceived:output];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NSStreamEventErrorOccurred:
|
||||
|
||||
NSLog(@"Can not connect to the host!");
|
||||
break;
|
||||
|
||||
case NSStreamEventEndEncountered:
|
||||
|
||||
[theStream close];
|
||||
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
//[theStream release];
|
||||
theStream = nil;
|
||||
|
||||
break;
|
||||
default:
|
||||
NSLog(@"Unknown event");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void) messageReceived:(NSString *)message {
|
||||
|
||||
NSAttributedString *receivedString;
|
||||
|
||||
[self.chatMessageField setTintColor:[UIColor greenColor]];
|
||||
timeString = [formatter stringFromDate:[NSDate date]];
|
||||
receivedString =
|
||||
[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ [Ameba] %@\n", timeString ,message]
|
||||
attributes:@{
|
||||
NSForegroundColorAttributeName : [UIColor purpleColor],
|
||||
NSFontAttributeName : [UIFont boldSystemFontOfSize:20]
|
||||
}];
|
||||
|
||||
[attrMessage appendAttributedString:receivedString];
|
||||
[chatMessageField setAttributedText:attrMessage];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[super viewDidUnload];
|
||||
|
||||
self->_netServiceBrowser.delegate = nil;
|
||||
[self->_netServiceBrowser stop];
|
||||
self->_netServiceBrowser = nil;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[inputStream close];
|
||||
[outputStream close];
|
||||
self->_netServiceBrowser = nil;
|
||||
self.dataServicesArray = nil;
|
||||
self.selectedService = nil;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
13
tools/uart_adapter/app/iOS/uartadapter/CustomCellBackground.h
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
Custom UIView to draw a rounded blue box to represent a selected cell.
|
||||
*/
|
||||
|
||||
@import UIKit;
|
||||
|
||||
@interface CustomCellBackground : UIView
|
||||
|
||||
@end
|
||||
30
tools/uart_adapter/app/iOS/uartadapter/CustomCellBackground.m
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
Copyright (C) 2015 Apple Inc. All Rights Reserved.
|
||||
See LICENSE.txt for this sample’s licensing information
|
||||
|
||||
Abstract:
|
||||
Custom UIView to draw a rounded blue box to represent a selected cell.
|
||||
*/
|
||||
|
||||
#import "CustomCellBackground.h"
|
||||
|
||||
@implementation CustomCellBackground
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
// draw a rounded rect bezier path filled with blue
|
||||
CGContextRef aRef = UIGraphicsGetCurrentContext();
|
||||
CGContextSaveGState(aRef);
|
||||
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5.0f];
|
||||
bezierPath.lineWidth = 5.0f;
|
||||
[[UIColor blackColor] setStroke];
|
||||
|
||||
UIColor *fillColor = [UIColor colorWithRed:0.529 green:0.808 blue:0.922 alpha:1]; // color equivalent is #87ceeb
|
||||
[fillColor setFill];
|
||||
|
||||
[bezierPath stroke];
|
||||
[bezierPath fill];
|
||||
CGContextRestoreGState(aRef);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/action_icon.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "action_icon@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/action_icon.imageset/action_icon@2x.png
vendored
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/ameba_group.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "ameba_group.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/ameba_group.imageset/ameba_group.png
vendored
Executable file
|
After Width: | Height: | Size: 4.7 KiB |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/background.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "background.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/background.imageset/background.png
vendored
Executable file
|
After Width: | Height: | Size: 193 KiB |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/chat.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "chat.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/chat.imageset/chat.png
vendored
Executable file
|
After Width: | Height: | Size: 696 B |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/device.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "device.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/device.imageset/device.png
vendored
Executable file
|
After Width: | Height: | Size: 3.8 KiB |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/settings.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "settings.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/settings.imageset/settings.png
vendored
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
21
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/ungroup.imageset/Contents.json
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "ungroup.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/Images.xcassets/ungroup.imageset/ungroup.png
vendored
Executable file
|
After Width: | Height: | Size: 2.4 KiB |
45
tools/uart_adapter/app/iOS/uartadapter/Info.plist
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
67
tools/uart_adapter/app/iOS/uartadapter/KxMenu.h
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// KxMenu.h
|
||||
// kxmenu project
|
||||
// https://github.com/kolyvan/kxmenu/
|
||||
//
|
||||
// Created by Kolyvan on 17.05.13.
|
||||
//
|
||||
|
||||
/*
|
||||
Copyright (c) 2013 Konstantin Bukreev. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface KxMenuItem : NSObject
|
||||
|
||||
@property (readwrite, nonatomic, strong) UIImage *image;
|
||||
@property (readwrite, nonatomic, strong) NSString *title;
|
||||
@property (readwrite, nonatomic, weak) id target;
|
||||
@property (readwrite, nonatomic) SEL action;
|
||||
@property (readwrite, nonatomic, strong) UIColor *foreColor;
|
||||
@property (readwrite, nonatomic) NSTextAlignment alignment;
|
||||
|
||||
+ (instancetype) menuItem:(NSString *) title
|
||||
image:(UIImage *) image
|
||||
target:(id)target
|
||||
action:(SEL) action;
|
||||
|
||||
@end
|
||||
|
||||
@interface KxMenu : NSObject
|
||||
|
||||
+ (void) showMenuInView:(UIView *)view
|
||||
fromRect:(CGRect)rect
|
||||
menuItems:(NSArray *)menuItems;
|
||||
|
||||
+ (void) dismissMenu;
|
||||
|
||||
+ (UIColor *) tintColor;
|
||||
+ (void) setTintColor: (UIColor *) tintColor;
|
||||
|
||||
+ (UIFont *) titleFont;
|
||||
+ (void) setTitleFont: (UIFont *) titleFont;
|
||||
|
||||
@end
|
||||
889
tools/uart_adapter/app/iOS/uartadapter/KxMenu.m
Executable file
|
|
@ -0,0 +1,889 @@
|
|||
//
|
||||
// KxMenu.m
|
||||
// kxmenu project
|
||||
// https://github.com/kolyvan/kxmenu/
|
||||
//
|
||||
// Created by Kolyvan on 17.05.13.
|
||||
//
|
||||
|
||||
/*
|
||||
Copyright (c) 2013 Konstantin Bukreev. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Some ideas was taken from QBPopupMenu project by Katsuma Tanaka.
|
||||
https://github.com/questbeat/QBPopupMenu
|
||||
*/
|
||||
|
||||
#import "KxMenu.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
const CGFloat kArrowSize = 12.f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@interface KxMenuView : UIView
|
||||
- (void)dismissMenu:(BOOL) animated;
|
||||
@end
|
||||
|
||||
@interface KxMenuOverlay : UIView
|
||||
@end
|
||||
|
||||
@implementation KxMenuOverlay
|
||||
|
||||
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.opaque = NO;
|
||||
|
||||
UITapGestureRecognizer *gestureRecognizer;
|
||||
gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(singleTap:)];
|
||||
[self addGestureRecognizer:gestureRecognizer];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// thank horaceho https://github.com/horaceho
|
||||
// for his solution described in https://github.com/kolyvan/kxmenu/issues/9
|
||||
|
||||
- (void)singleTap:(UITapGestureRecognizer *)recognizer
|
||||
{
|
||||
for (UIView *v in self.subviews) {
|
||||
if ([v isKindOfClass:[KxMenuView class]] && [v respondsToSelector:@selector(dismissMenu:)]) {
|
||||
[v performSelector:@selector(dismissMenu:) withObject:@(YES)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation KxMenuItem
|
||||
|
||||
+ (instancetype) menuItem:(NSString *) title
|
||||
image:(UIImage *) image
|
||||
target:(id)target
|
||||
action:(SEL) action
|
||||
{
|
||||
return [[KxMenuItem alloc] init:title
|
||||
image:image
|
||||
target:target
|
||||
action:action];
|
||||
}
|
||||
|
||||
- (id) init:(NSString *) title
|
||||
image:(UIImage *) image
|
||||
target:(id)target
|
||||
action:(SEL) action
|
||||
{
|
||||
NSParameterAssert(title.length || image);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_title = title;
|
||||
_image = image;
|
||||
_target = target;
|
||||
_action = action;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) enabled
|
||||
{
|
||||
return _target != nil && _action != NULL;
|
||||
}
|
||||
|
||||
- (void) performAction
|
||||
{
|
||||
__strong id target = self.target;
|
||||
|
||||
if (target && [target respondsToSelector:_action]) {
|
||||
|
||||
[target performSelectorOnMainThread:_action withObject:self waitUntilDone:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@ #%p %@>", [self class], self, _title];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
|
||||
KxMenuViewArrowDirectionNone,
|
||||
KxMenuViewArrowDirectionUp,
|
||||
KxMenuViewArrowDirectionDown,
|
||||
KxMenuViewArrowDirectionLeft,
|
||||
KxMenuViewArrowDirectionRight,
|
||||
|
||||
} KxMenuViewArrowDirection;
|
||||
|
||||
@implementation KxMenuView {
|
||||
|
||||
KxMenuViewArrowDirection _arrowDirection;
|
||||
CGFloat _arrowPosition;
|
||||
UIView *_contentView;
|
||||
NSArray *_menuItems;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super initWithFrame:CGRectZero];
|
||||
if(self) {
|
||||
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.opaque = YES;
|
||||
self.alpha = 0;
|
||||
|
||||
self.layer.shadowOpacity = 0.5;
|
||||
self.layer.shadowOffset = CGSizeMake(2, 2);
|
||||
self.layer.shadowRadius = 2;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) setupFrameInView:(UIView *)view
|
||||
fromRect:(CGRect)fromRect
|
||||
{
|
||||
const CGSize contentSize = _contentView.frame.size;
|
||||
|
||||
const CGFloat outerWidth = view.bounds.size.width;
|
||||
const CGFloat outerHeight = view.bounds.size.height;
|
||||
|
||||
const CGFloat rectX0 = fromRect.origin.x;
|
||||
const CGFloat rectX1 = fromRect.origin.x + fromRect.size.width;
|
||||
const CGFloat rectXM = fromRect.origin.x + fromRect.size.width * 0.5f;
|
||||
const CGFloat rectY0 = fromRect.origin.y;
|
||||
const CGFloat rectY1 = fromRect.origin.y + fromRect.size.height;
|
||||
const CGFloat rectYM = fromRect.origin.y + fromRect.size.height * 0.5f;;
|
||||
|
||||
const CGFloat widthPlusArrow = contentSize.width + kArrowSize;
|
||||
const CGFloat heightPlusArrow = contentSize.height + kArrowSize;
|
||||
const CGFloat widthHalf = contentSize.width * 0.5f;
|
||||
const CGFloat heightHalf = contentSize.height * 0.5f;
|
||||
|
||||
const CGFloat kMargin = 5.f;
|
||||
|
||||
if (heightPlusArrow < (outerHeight - rectY1)) {
|
||||
|
||||
_arrowDirection = KxMenuViewArrowDirectionUp;
|
||||
CGPoint point = (CGPoint){
|
||||
rectXM - widthHalf,
|
||||
rectY1
|
||||
};
|
||||
|
||||
if (point.x < kMargin)
|
||||
point.x = kMargin;
|
||||
|
||||
if ((point.x + contentSize.width + kMargin) > outerWidth)
|
||||
point.x = outerWidth - contentSize.width - kMargin;
|
||||
|
||||
_arrowPosition = rectXM - point.x;
|
||||
//_arrowPosition = MAX(16, MIN(_arrowPosition, contentSize.width - 16));
|
||||
_contentView.frame = (CGRect){0, kArrowSize, contentSize};
|
||||
|
||||
self.frame = (CGRect) {
|
||||
|
||||
point,
|
||||
contentSize.width,
|
||||
contentSize.height + kArrowSize
|
||||
};
|
||||
|
||||
} else if (heightPlusArrow < rectY0) {
|
||||
|
||||
_arrowDirection = KxMenuViewArrowDirectionDown;
|
||||
CGPoint point = (CGPoint){
|
||||
rectXM - widthHalf,
|
||||
rectY0 - heightPlusArrow
|
||||
};
|
||||
|
||||
if (point.x < kMargin)
|
||||
point.x = kMargin;
|
||||
|
||||
if ((point.x + contentSize.width + kMargin) > outerWidth)
|
||||
point.x = outerWidth - contentSize.width - kMargin;
|
||||
|
||||
_arrowPosition = rectXM - point.x;
|
||||
_contentView.frame = (CGRect){CGPointZero, contentSize};
|
||||
|
||||
self.frame = (CGRect) {
|
||||
|
||||
point,
|
||||
contentSize.width,
|
||||
contentSize.height + kArrowSize
|
||||
};
|
||||
|
||||
} else if (widthPlusArrow < (outerWidth - rectX1)) {
|
||||
|
||||
_arrowDirection = KxMenuViewArrowDirectionLeft;
|
||||
CGPoint point = (CGPoint){
|
||||
rectX1,
|
||||
rectYM - heightHalf
|
||||
};
|
||||
|
||||
if (point.y < kMargin)
|
||||
point.y = kMargin;
|
||||
|
||||
if ((point.y + contentSize.height + kMargin) > outerHeight)
|
||||
point.y = outerHeight - contentSize.height - kMargin;
|
||||
|
||||
_arrowPosition = rectYM - point.y;
|
||||
_contentView.frame = (CGRect){kArrowSize, 0, contentSize};
|
||||
|
||||
self.frame = (CGRect) {
|
||||
|
||||
point,
|
||||
contentSize.width + kArrowSize,
|
||||
contentSize.height
|
||||
};
|
||||
|
||||
} else if (widthPlusArrow < rectX0) {
|
||||
|
||||
_arrowDirection = KxMenuViewArrowDirectionRight;
|
||||
CGPoint point = (CGPoint){
|
||||
rectX0 - widthPlusArrow,
|
||||
rectYM - heightHalf
|
||||
};
|
||||
|
||||
if (point.y < kMargin)
|
||||
point.y = kMargin;
|
||||
|
||||
if ((point.y + contentSize.height + 5) > outerHeight)
|
||||
point.y = outerHeight - contentSize.height - kMargin;
|
||||
|
||||
_arrowPosition = rectYM - point.y;
|
||||
_contentView.frame = (CGRect){CGPointZero, contentSize};
|
||||
|
||||
self.frame = (CGRect) {
|
||||
|
||||
point,
|
||||
contentSize.width + kArrowSize,
|
||||
contentSize.height
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
_arrowDirection = KxMenuViewArrowDirectionNone;
|
||||
|
||||
self.frame = (CGRect) {
|
||||
|
||||
(outerWidth - contentSize.width) * 0.5f,
|
||||
(outerHeight - contentSize.height) * 0.5f,
|
||||
contentSize,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showMenuInView:(UIView *)view
|
||||
fromRect:(CGRect)rect
|
||||
menuItems:(NSArray *)menuItems
|
||||
{
|
||||
_menuItems = menuItems;
|
||||
|
||||
_contentView = [self mkContentView];
|
||||
[self addSubview:_contentView];
|
||||
|
||||
[self setupFrameInView:view fromRect:rect];
|
||||
|
||||
KxMenuOverlay *overlay = [[KxMenuOverlay alloc] initWithFrame:view.bounds];
|
||||
[overlay addSubview:self];
|
||||
[view addSubview:overlay];
|
||||
|
||||
_contentView.hidden = YES;
|
||||
const CGRect toFrame = self.frame;
|
||||
self.frame = (CGRect){self.arrowPoint, 1, 1};
|
||||
|
||||
[UIView animateWithDuration:0.2
|
||||
animations:^(void) {
|
||||
|
||||
self.alpha = 1.0f;
|
||||
self.frame = toFrame;
|
||||
|
||||
} completion:^(BOOL completed) {
|
||||
_contentView.hidden = NO;
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
- (void)dismissMenu:(BOOL) animated
|
||||
{
|
||||
if (self.superview) {
|
||||
|
||||
if (animated) {
|
||||
|
||||
_contentView.hidden = YES;
|
||||
const CGRect toFrame = (CGRect){self.arrowPoint, 1, 1};
|
||||
|
||||
[UIView animateWithDuration:0.2
|
||||
animations:^(void) {
|
||||
|
||||
self.alpha = 0;
|
||||
self.frame = toFrame;
|
||||
|
||||
} completion:^(BOOL finished) {
|
||||
|
||||
if ([self.superview isKindOfClass:[KxMenuOverlay class]])
|
||||
[self.superview removeFromSuperview];
|
||||
[self removeFromSuperview];
|
||||
}];
|
||||
|
||||
} else {
|
||||
|
||||
if ([self.superview isKindOfClass:[KxMenuOverlay class]])
|
||||
[self.superview removeFromSuperview];
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)performAction:(id)sender
|
||||
{
|
||||
[self dismissMenu:YES];
|
||||
|
||||
UIButton *button = (UIButton *)sender;
|
||||
KxMenuItem *menuItem = _menuItems[button.tag];
|
||||
[menuItem performAction];
|
||||
}
|
||||
|
||||
- (UIView *) mkContentView
|
||||
{
|
||||
for (UIView *v in self.subviews) {
|
||||
[v removeFromSuperview];
|
||||
}
|
||||
|
||||
if (!_menuItems.count)
|
||||
return nil;
|
||||
|
||||
const CGFloat kMinMenuItemHeight = 32.f;
|
||||
const CGFloat kMinMenuItemWidth = 32.f;
|
||||
const CGFloat kMarginX = 10.f;
|
||||
const CGFloat kMarginY = 5.f;
|
||||
|
||||
UIFont *titleFont = [KxMenu titleFont];
|
||||
if (!titleFont) titleFont = [UIFont boldSystemFontOfSize:16];
|
||||
|
||||
CGFloat maxImageWidth = 0;
|
||||
CGFloat maxItemHeight = 0;
|
||||
CGFloat maxItemWidth = 0;
|
||||
|
||||
for (KxMenuItem *menuItem in _menuItems) {
|
||||
|
||||
const CGSize imageSize = menuItem.image.size;
|
||||
if (imageSize.width > maxImageWidth)
|
||||
maxImageWidth = imageSize.width;
|
||||
}
|
||||
|
||||
if (maxImageWidth) {
|
||||
maxImageWidth += kMarginX;
|
||||
}
|
||||
|
||||
for (KxMenuItem *menuItem in _menuItems) {
|
||||
NSDictionary *attributes = @{NSFontAttributeName:titleFont};
|
||||
const CGSize titleSize = [menuItem.title sizeWithAttributes:attributes];
|
||||
const CGSize imageSize = menuItem.image.size;
|
||||
|
||||
const CGFloat itemHeight = MAX(titleSize.height, imageSize.height) + kMarginY * 2;
|
||||
const CGFloat itemWidth = ((!menuItem.enabled && !menuItem.image) ? titleSize.width : maxImageWidth + titleSize.width) + kMarginX * 4;
|
||||
|
||||
if (itemHeight > maxItemHeight)
|
||||
maxItemHeight = itemHeight;
|
||||
|
||||
if (itemWidth > maxItemWidth)
|
||||
maxItemWidth = itemWidth;
|
||||
}
|
||||
|
||||
maxItemWidth = MAX(maxItemWidth, kMinMenuItemWidth);
|
||||
maxItemHeight = MAX(maxItemHeight, kMinMenuItemHeight);
|
||||
|
||||
const CGFloat titleX = kMarginX * 2 + maxImageWidth;
|
||||
const CGFloat titleWidth = maxItemWidth - titleX - kMarginX * 2;
|
||||
|
||||
UIImage *selectedImage = [KxMenuView selectedImage:(CGSize){maxItemWidth, maxItemHeight + 2}];
|
||||
UIImage *gradientLine = [KxMenuView gradientLine: (CGSize){maxItemWidth - kMarginX * 4, 1}];
|
||||
|
||||
UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
contentView.autoresizingMask = UIViewAutoresizingNone;
|
||||
contentView.backgroundColor = [UIColor clearColor];
|
||||
contentView.opaque = NO;
|
||||
|
||||
CGFloat itemY = kMarginY * 2;
|
||||
NSUInteger itemNum = 0;
|
||||
|
||||
for (KxMenuItem *menuItem in _menuItems) {
|
||||
|
||||
const CGRect itemFrame = (CGRect){0, itemY, maxItemWidth, maxItemHeight};
|
||||
|
||||
UIView *itemView = [[UIView alloc] initWithFrame:itemFrame];
|
||||
itemView.autoresizingMask = UIViewAutoresizingNone;
|
||||
itemView.backgroundColor = [UIColor clearColor];
|
||||
itemView.opaque = NO;
|
||||
|
||||
[contentView addSubview:itemView];
|
||||
|
||||
if (menuItem.enabled) {
|
||||
|
||||
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
button.tag = itemNum;
|
||||
button.frame = itemView.bounds;
|
||||
button.enabled = menuItem.enabled;
|
||||
button.backgroundColor = [UIColor clearColor];
|
||||
button.opaque = NO;
|
||||
button.autoresizingMask = UIViewAutoresizingNone;
|
||||
|
||||
[button addTarget:self
|
||||
action:@selector(performAction:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
[button setBackgroundImage:selectedImage forState:UIControlStateHighlighted];
|
||||
|
||||
[itemView addSubview:button];
|
||||
}
|
||||
|
||||
if (menuItem.title.length) {
|
||||
|
||||
CGRect titleFrame;
|
||||
|
||||
if (!menuItem.enabled && !menuItem.image) {
|
||||
|
||||
titleFrame = (CGRect){
|
||||
kMarginX * 2,
|
||||
kMarginY,
|
||||
maxItemWidth - kMarginX * 4,
|
||||
maxItemHeight - kMarginY * 2
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
titleFrame = (CGRect){
|
||||
titleX,
|
||||
kMarginY,
|
||||
titleWidth,
|
||||
maxItemHeight - kMarginY * 2
|
||||
};
|
||||
}
|
||||
|
||||
UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
|
||||
titleLabel.text = menuItem.title;
|
||||
titleLabel.font = titleFont;
|
||||
titleLabel.textAlignment = menuItem.alignment;
|
||||
titleLabel.textColor = menuItem.foreColor ? menuItem.foreColor : [UIColor whiteColor];
|
||||
titleLabel.backgroundColor = [UIColor clearColor];
|
||||
titleLabel.autoresizingMask = UIViewAutoresizingNone;
|
||||
//titleLabel.backgroundColor = [UIColor greenColor];
|
||||
[itemView addSubview:titleLabel];
|
||||
}
|
||||
|
||||
if (menuItem.image) {
|
||||
|
||||
const CGRect imageFrame = {kMarginX * 2, kMarginY, maxImageWidth, maxItemHeight - kMarginY * 2};
|
||||
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
|
||||
imageView.image = menuItem.image;
|
||||
imageView.clipsToBounds = YES;
|
||||
imageView.contentMode = UIViewContentModeCenter;
|
||||
imageView.autoresizingMask = UIViewAutoresizingNone;
|
||||
[itemView addSubview:imageView];
|
||||
}
|
||||
|
||||
if (itemNum < _menuItems.count - 1) {
|
||||
|
||||
UIImageView *gradientView = [[UIImageView alloc] initWithImage:gradientLine];
|
||||
gradientView.frame = (CGRect){kMarginX * 2, maxItemHeight + 1, gradientLine.size};
|
||||
gradientView.contentMode = UIViewContentModeLeft;
|
||||
[itemView addSubview:gradientView];
|
||||
|
||||
itemY += 2;
|
||||
}
|
||||
|
||||
itemY += maxItemHeight;
|
||||
++itemNum;
|
||||
}
|
||||
|
||||
contentView.frame = (CGRect){0, 0, maxItemWidth, itemY + kMarginY * 2};
|
||||
|
||||
return contentView;
|
||||
}
|
||||
|
||||
- (CGPoint) arrowPoint
|
||||
{
|
||||
CGPoint point;
|
||||
|
||||
if (_arrowDirection == KxMenuViewArrowDirectionUp) {
|
||||
|
||||
point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMinY(self.frame) };
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionDown) {
|
||||
|
||||
point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMaxY(self.frame) };
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionLeft) {
|
||||
|
||||
point = (CGPoint){ CGRectGetMinX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionRight) {
|
||||
|
||||
point = (CGPoint){ CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
|
||||
|
||||
} else {
|
||||
|
||||
point = self.center;
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
+ (UIImage *) selectedImage: (CGSize) size
|
||||
{
|
||||
const CGFloat locations[] = {0,1};
|
||||
const CGFloat components[] = {
|
||||
0.216, 0.471, 0.871, 1,
|
||||
0.059, 0.353, 0.839, 1,
|
||||
};
|
||||
|
||||
return [self gradientImageWithSize:size locations:locations components:components count:2];
|
||||
}
|
||||
|
||||
+ (UIImage *) gradientLine: (CGSize) size
|
||||
{
|
||||
const CGFloat locations[5] = {0,0.2,0.5,0.8,1};
|
||||
|
||||
const CGFloat R = 0.44f, G = 0.44f, B = 0.44f;
|
||||
|
||||
const CGFloat components[20] = {
|
||||
R,G,B,0.1,
|
||||
R,G,B,0.4,
|
||||
R,G,B,0.7,
|
||||
R,G,B,0.4,
|
||||
R,G,B,0.1
|
||||
};
|
||||
|
||||
return [self gradientImageWithSize:size locations:locations components:components count:5];
|
||||
}
|
||||
|
||||
+ (UIImage *) gradientImageWithSize:(CGSize) size
|
||||
locations:(const CGFloat []) locations
|
||||
components:(const CGFloat []) components
|
||||
count:(NSUInteger)count
|
||||
{
|
||||
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGContextDrawLinearGradient(context, colorGradient, (CGPoint){0, 0}, (CGPoint){size.width, 0}, 0);
|
||||
CGGradientRelease(colorGradient);
|
||||
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return image;
|
||||
}
|
||||
|
||||
- (void) drawRect:(CGRect)rect
|
||||
{
|
||||
[self drawBackground:self.bounds
|
||||
inContext:UIGraphicsGetCurrentContext()];
|
||||
}
|
||||
|
||||
- (void)drawBackground:(CGRect)frame
|
||||
inContext:(CGContextRef) context
|
||||
{
|
||||
CGFloat R0 = 0.267, G0 = 0.303, B0 = 0.335;
|
||||
CGFloat R1 = 0.040, G1 = 0.040, B1 = 0.040;
|
||||
|
||||
UIColor *tintColor = [KxMenu tintColor];
|
||||
if (tintColor) {
|
||||
|
||||
CGFloat a;
|
||||
[tintColor getRed:&R0 green:&G0 blue:&B0 alpha:&a];
|
||||
}
|
||||
|
||||
CGFloat X0 = frame.origin.x;
|
||||
CGFloat X1 = frame.origin.x + frame.size.width;
|
||||
CGFloat Y0 = frame.origin.y;
|
||||
CGFloat Y1 = frame.origin.y + frame.size.height;
|
||||
|
||||
// render arrow
|
||||
|
||||
UIBezierPath *arrowPath = [UIBezierPath bezierPath];
|
||||
|
||||
// fix the issue with gap of arrow's base if on the edge
|
||||
const CGFloat kEmbedFix = 3.f;
|
||||
|
||||
if (_arrowDirection == KxMenuViewArrowDirectionUp) {
|
||||
|
||||
const CGFloat arrowXM = _arrowPosition;
|
||||
const CGFloat arrowX0 = arrowXM - kArrowSize;
|
||||
const CGFloat arrowX1 = arrowXM + kArrowSize;
|
||||
const CGFloat arrowY0 = Y0;
|
||||
const CGFloat arrowY1 = Y0 + kArrowSize + kEmbedFix;
|
||||
|
||||
[arrowPath moveToPoint: (CGPoint){arrowXM, arrowY0}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY1}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY0}];
|
||||
|
||||
[[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:1] set];
|
||||
|
||||
Y0 += kArrowSize;
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionDown) {
|
||||
|
||||
const CGFloat arrowXM = _arrowPosition;
|
||||
const CGFloat arrowX0 = arrowXM - kArrowSize;
|
||||
const CGFloat arrowX1 = arrowXM + kArrowSize;
|
||||
const CGFloat arrowY0 = Y1 - kArrowSize - kEmbedFix;
|
||||
const CGFloat arrowY1 = Y1;
|
||||
|
||||
[arrowPath moveToPoint: (CGPoint){arrowXM, arrowY1}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY0}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY1}];
|
||||
|
||||
[[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:1] set];
|
||||
|
||||
Y1 -= kArrowSize;
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionLeft) {
|
||||
|
||||
const CGFloat arrowYM = _arrowPosition;
|
||||
const CGFloat arrowX0 = X0;
|
||||
const CGFloat arrowX1 = X0 + kArrowSize + kEmbedFix;
|
||||
const CGFloat arrowY0 = arrowYM - kArrowSize;;
|
||||
const CGFloat arrowY1 = arrowYM + kArrowSize;
|
||||
|
||||
[arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
|
||||
|
||||
[[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:1] set];
|
||||
|
||||
X0 += kArrowSize;
|
||||
|
||||
} else if (_arrowDirection == KxMenuViewArrowDirectionRight) {
|
||||
|
||||
const CGFloat arrowYM = _arrowPosition;
|
||||
const CGFloat arrowX0 = X1;
|
||||
const CGFloat arrowX1 = X1 - kArrowSize - kEmbedFix;
|
||||
const CGFloat arrowY0 = arrowYM - kArrowSize;;
|
||||
const CGFloat arrowY1 = arrowYM + kArrowSize;
|
||||
|
||||
[arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
|
||||
[arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
|
||||
|
||||
[[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:1] set];
|
||||
|
||||
X1 -= kArrowSize;
|
||||
}
|
||||
|
||||
[arrowPath fill];
|
||||
|
||||
// render body
|
||||
|
||||
const CGRect bodyFrame = {X0, Y0, X1 - X0, Y1 - Y0};
|
||||
|
||||
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:bodyFrame
|
||||
cornerRadius:8];
|
||||
|
||||
const CGFloat locations[] = {0, 1};
|
||||
const CGFloat components[] = {
|
||||
R0, G0, B0, 1,
|
||||
R1, G1, B1, 1,
|
||||
};
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace,
|
||||
components,
|
||||
locations,
|
||||
sizeof(locations)/sizeof(locations[0]));
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
|
||||
[borderPath addClip];
|
||||
|
||||
CGPoint start, end;
|
||||
|
||||
if (_arrowDirection == KxMenuViewArrowDirectionLeft ||
|
||||
_arrowDirection == KxMenuViewArrowDirectionRight) {
|
||||
|
||||
start = (CGPoint){X0, Y0};
|
||||
end = (CGPoint){X1, Y0};
|
||||
|
||||
} else {
|
||||
|
||||
start = (CGPoint){X0, Y0};
|
||||
end = (CGPoint){X0, Y1};
|
||||
}
|
||||
|
||||
CGContextDrawLinearGradient(context, gradient, start, end, 0);
|
||||
|
||||
CGGradientRelease(gradient);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static KxMenu *gMenu;
|
||||
static UIColor *gTintColor;
|
||||
static UIFont *gTitleFont;
|
||||
|
||||
@implementation KxMenu {
|
||||
|
||||
KxMenuView *_menuView;
|
||||
BOOL _observing;
|
||||
}
|
||||
|
||||
+ (instancetype) sharedMenu
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
gMenu = [[KxMenu alloc] init];
|
||||
});
|
||||
return gMenu;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
NSAssert(!gMenu, @"singleton object");
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (_observing) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) showMenuInView:(UIView *)view
|
||||
fromRect:(CGRect)rect
|
||||
menuItems:(NSArray *)menuItems
|
||||
{
|
||||
NSParameterAssert(view);
|
||||
NSParameterAssert(menuItems.count);
|
||||
|
||||
if (_menuView) {
|
||||
|
||||
[_menuView dismissMenu:NO];
|
||||
_menuView = nil;
|
||||
}
|
||||
|
||||
if (!_observing) {
|
||||
|
||||
_observing = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(orientationWillChange:)
|
||||
name:UIApplicationWillChangeStatusBarOrientationNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
|
||||
_menuView = [[KxMenuView alloc] init];
|
||||
[_menuView showMenuInView:view fromRect:rect menuItems:menuItems];
|
||||
}
|
||||
|
||||
- (void) dismissMenu
|
||||
{
|
||||
if (_menuView) {
|
||||
|
||||
[_menuView dismissMenu:NO];
|
||||
_menuView = nil;
|
||||
}
|
||||
|
||||
if (_observing) {
|
||||
|
||||
_observing = NO;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) orientationWillChange: (NSNotification *) n
|
||||
{
|
||||
[self dismissMenu];
|
||||
}
|
||||
|
||||
+ (void) showMenuInView:(UIView *)view
|
||||
fromRect:(CGRect)rect
|
||||
menuItems:(NSArray *)menuItems
|
||||
{
|
||||
[[self sharedMenu] showMenuInView:view fromRect:rect menuItems:menuItems];
|
||||
}
|
||||
|
||||
+ (void) dismissMenu
|
||||
{
|
||||
[[self sharedMenu] dismissMenu];
|
||||
}
|
||||
|
||||
+ (UIColor *) tintColor
|
||||
{
|
||||
return gTintColor;
|
||||
}
|
||||
|
||||
+ (void) setTintColor: (UIColor *) tintColor
|
||||
{
|
||||
if (tintColor != gTintColor) {
|
||||
gTintColor = tintColor;
|
||||
}
|
||||
}
|
||||
|
||||
+ (UIFont *) titleFont
|
||||
{
|
||||
return gTitleFont;
|
||||
}
|
||||
|
||||
+ (void) setTitleFont: (UIFont *) titleFont
|
||||
{
|
||||
if (titleFont != gTitleFont) {
|
||||
gTitleFont = titleFont;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
46
tools/uart_adapter/app/iOS/uartadapter/SettingPageViewController.h
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// SettingPageViewController.h
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 9/1/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SettingPageViewController : UIViewController<
|
||||
UIPickerViewDataSource,
|
||||
UIPickerViewDelegate,
|
||||
UITextFieldDelegate,
|
||||
NSStreamDelegate,
|
||||
NSNetServiceBrowserDelegate,
|
||||
NSNetServiceDelegate,
|
||||
UIAlertViewDelegate>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+ (void) initSettingIOTInfoArray;
|
||||
+ (void) copyIOTInfo:(NSNetService *)mService;
|
||||
|
||||
@property (nonatomic, retain) NSData *allSettings;
|
||||
@property (nonatomic, retain) NSInputStream *inputStream;
|
||||
@property (nonatomic, retain) NSOutputStream *outputStream;
|
||||
//@property (nonatomic, retain) NSMutableArray *settingIOTInfoArray;
|
||||
@property (nonatomic, retain) NSNetService *selectedService;
|
||||
@property (nonatomic, assign) NSInteger selectedGroupID;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *baudRateField;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *dataBitField;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *parityBitField;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *stopBitField;
|
||||
//@property (nonatomic, retain) IBOutlet UIPickerView *datapicker;
|
||||
|
||||
- (IBAction) saveSettings;
|
||||
- (IBAction) restoreSettings;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
580
tools/uart_adapter/app/iOS/uartadapter/SettingPageViewController.m
Executable file
|
|
@ -0,0 +1,580 @@
|
|||
//
|
||||
// SettingPageViewController.m
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 9/1/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
//#import <Foundation/Foundation.h>
|
||||
#import "ViewController.h"
|
||||
#import "SettingPageViewController.h"
|
||||
#include <ifaddrs.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
uint8_t const cmdPrefix[] = { 0x41, 0x4D, 0x45, 0x42, 0x41, 0x5F, 0x55, 0x41, 0x52, 0x54 };;
|
||||
uint8_t const cmdGetAllSetting[] = { 0x02, 0x00, 0x0f };
|
||||
|
||||
NSMutableArray *settingIOTInfoArray;
|
||||
|
||||
@interface SettingPageViewController ()
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation SettingPageViewController
|
||||
|
||||
|
||||
@synthesize inputStream, outputStream;
|
||||
@synthesize selectedService = _selectedService;
|
||||
@synthesize baudRateField, dataBitField, parityBitField, stopBitField;
|
||||
@synthesize allSettings = _allSettings;
|
||||
//@synthesize datapicker;
|
||||
|
||||
|
||||
//UIAlertView *alert;
|
||||
|
||||
NSArray * baurateData ;
|
||||
NSArray * bitData;
|
||||
NSArray * parityBitData;
|
||||
NSArray * stopBitdata;
|
||||
|
||||
int mBardRate = 0;
|
||||
int mDataBit = 0;
|
||||
int mParityBit = 0;
|
||||
int mStopBit = 0;
|
||||
|
||||
|
||||
UIPickerView *datapicker;
|
||||
int mTextFieldTag = -1;
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]];
|
||||
|
||||
|
||||
baurateData = [[NSArray alloc] initWithObjects:@"1200", @"9600", @"14400", @"19200", @"28800", @"38400", @"57600", @"76800", @"115200", @"128000", @"153600", @"230400", @"460800", @"500000", @"921600", nil];
|
||||
bitData = [[NSArray alloc] initWithObjects:@"7", @"8", nil];
|
||||
parityBitData = [[NSArray alloc] initWithObjects:@"none", @"odd", @"even", nil];
|
||||
stopBitdata = [[NSArray alloc] initWithObjects:@"none", @"1", nil];
|
||||
|
||||
datapicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 50, 100, 150)];
|
||||
[datapicker setDataSource: self];
|
||||
[datapicker setDelegate: self];
|
||||
[baudRateField setDelegate:self];
|
||||
[dataBitField setDelegate:self];
|
||||
[parityBitField setDelegate:self];
|
||||
[stopBitField setDelegate:self];
|
||||
|
||||
datapicker.showsSelectionIndicator = YES;
|
||||
|
||||
self.baudRateField.inputView = datapicker;
|
||||
self.dataBitField.inputView = datapicker;
|
||||
self.parityBitField.inputView = datapicker;
|
||||
self.stopBitField.inputView = datapicker;
|
||||
|
||||
if([self inputStreamReceivedParser:self.allSettings] == 1)//update ui
|
||||
{
|
||||
self.baudRateField.text = [NSString stringWithFormat:@"%d",mBardRate];
|
||||
|
||||
self.dataBitField.text = [NSString stringWithFormat:@"%d",mDataBit];
|
||||
|
||||
if (mParityBit == 0)
|
||||
self.parityBitField.text = @"none";
|
||||
else if (mParityBit == 1)
|
||||
self.parityBitField.text = @"odd";
|
||||
else if (mParityBit == 2)
|
||||
self.parityBitField.text = @"even";
|
||||
|
||||
if (mStopBit == 0)
|
||||
self.stopBitField.text = @"none";
|
||||
else if (mStopBit == 1)
|
||||
self.stopBitField.text = @"1";
|
||||
|
||||
// [alert dismissWithClickedButtonIndex:0 animated:YES];
|
||||
|
||||
}
|
||||
|
||||
//[self prepareForInitNetworkCommunication];
|
||||
/*
|
||||
alert = [[UIAlertView alloc] initWithTitle:@"UART Adapter" message:@"Connecting" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
|
||||
UIActivityIndicatorView * alertIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125.0, 00.0, 30.0, 30.0) ];
|
||||
alertIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
|
||||
//alertIndicator.center = CGPointMake(alert.bounds.size.width/2 , (alert.bounds.size.height/2) + 10);
|
||||
|
||||
[alertIndicator startAnimating];
|
||||
|
||||
if ([[[UIDevice currentDevice] systemVersion]compare:@"7.0"] != NSOrderedAscending)
|
||||
[alert setValue:alertIndicator forKey:@"accessoryView"];
|
||||
else
|
||||
[alert addSubview:alertIndicator];
|
||||
// [alert show];
|
||||
*/
|
||||
/*
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[self queryAllSettings];
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (IBAction) restoreSettings
|
||||
{
|
||||
self.baudRateField.text = [NSString stringWithFormat:@"%d",mBardRate];
|
||||
self.dataBitField.text = [NSString stringWithFormat:@"%d",mDataBit];
|
||||
|
||||
if (mParityBit == 0)
|
||||
self.parityBitField.text = @"none";
|
||||
else if (mParityBit == 1)
|
||||
self.parityBitField.text = @"odd";
|
||||
else if (mParityBit == 2)
|
||||
self.parityBitField.text = @"even";
|
||||
|
||||
if (mStopBit == 0)
|
||||
self.stopBitField.text = @"none";
|
||||
else if (mStopBit == 1)
|
||||
self.stopBitField.text = @"1";
|
||||
[datapicker reloadAllComponents];
|
||||
}
|
||||
|
||||
- (IBAction) saveSettings{
|
||||
|
||||
NSString * stringTxtField;
|
||||
uint8_t cmdReq[] = {0x00};
|
||||
uint8_t *cmdBaudrate = NULL;
|
||||
uint8_t *cmdDatabit = NULL;
|
||||
uint8_t *cmdParity = NULL;
|
||||
uint8_t *cmdStopbit = NULL;
|
||||
|
||||
|
||||
stringTxtField = self.baudRateField.text;
|
||||
|
||||
if([stringTxtField isEqualToString:@"1200"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0xB0, 0x04, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"9600"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x80, 0x25, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"14400"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x40, 0x38, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"19200"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x4B, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"28800"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x80, 0x70, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"38400"]){
|
||||
cmdBaudrate = (uint8_t []){ 0x00, 0x01, 0x04, 0x00, 0x96, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"57600"]){
|
||||
cmdBaudrate = (uint8_t []){ 0x00, 0x01, 0x04, 0x00, 0xE1, 0x00, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"76800"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x2C, 0x01, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"115200"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0xC2, 0x01, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"128000"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0xF4, 0x01, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"153600"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x58, 0x02, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"230400"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x84, 0x03, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"460800"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x08, 0x07, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"500000"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x20, 0xA1, 0x07, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"921600"]){
|
||||
cmdBaudrate = (uint8_t []) { 0x00, 0x01, 0x04, 0x00, 0x10, 0x0E, 0x00 };
|
||||
}
|
||||
|
||||
stringTxtField = self.dataBitField.text;
|
||||
if([stringTxtField isEqualToString:@"8"]){
|
||||
cmdDatabit = (uint8_t []) { 0x00, 0x02, 0x01, 0x08 };
|
||||
}else{
|
||||
cmdDatabit = (uint8_t []) { 0x00, 0x02, 0x01, 0x07 };
|
||||
}
|
||||
|
||||
stringTxtField = self.parityBitField.text;
|
||||
if([stringTxtField isEqualToString:@"none"]){
|
||||
cmdParity = (uint8_t []) { 0x00, 0x04, 0x01, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"odd"]){
|
||||
cmdParity = (uint8_t []) { 0x00, 0x04, 0x01, 0x01 };
|
||||
}else if([stringTxtField isEqualToString:@"even"]){
|
||||
cmdParity = (uint8_t []) { 0x00, 0x04, 0x01, 0x02 };
|
||||
}
|
||||
|
||||
stringTxtField = self.stopBitField.text;
|
||||
if([stringTxtField isEqualToString:@"none"]){
|
||||
cmdStopbit = (uint8_t []) { 0x00, 0x08, 0x01, 0x00 };
|
||||
}else if([stringTxtField isEqualToString:@"1"]){
|
||||
cmdStopbit = (uint8_t []) { 0x00, 0x08, 0x01, 0x01 };
|
||||
}
|
||||
|
||||
|
||||
NSMutableData *cmdSetSettings = [[NSMutableData alloc] initWithBytes:cmdPrefix length:sizeof(cmdPrefix)];
|
||||
[cmdSetSettings appendBytes:cmdReq length:1];
|
||||
[cmdSetSettings appendBytes:cmdBaudrate length:7];
|
||||
[cmdSetSettings appendBytes:cmdDatabit length:4];
|
||||
[cmdSetSettings appendBytes:cmdParity length:4];
|
||||
[cmdSetSettings appendBytes:cmdStopbit length:4];
|
||||
|
||||
|
||||
|
||||
|
||||
if (self.selectedGroupID != 0) {
|
||||
|
||||
for (int i=0 ; i < settingIOTInfoArray.count; i++) {
|
||||
NSNetService * groupIOTDevice = [settingIOTInfoArray objectAtIndex:i];
|
||||
|
||||
|
||||
|
||||
[self prepareForInitNetworkCommunication:[groupIOTDevice.addresses objectAtIndex:0 ] Port:(int)groupIOTDevice.port];
|
||||
[outputStream write:[cmdSetSettings bytes] maxLength:[cmdSetSettings length]];
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
[self prepareForInitNetworkCommunication:[self.selectedService.addresses objectAtIndex:0 ] Port:(int)self.selectedService.port];
|
||||
[outputStream write:[cmdSetSettings bytes] maxLength:[cmdSetSettings length]];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ (void) initSettingIOTInfoArray
|
||||
{
|
||||
settingIOTInfoArray = [[NSMutableArray alloc] init];
|
||||
}
|
||||
|
||||
+ (void) copyIOTInfo:(NSNetService *)mService
|
||||
{
|
||||
|
||||
|
||||
[settingIOTInfoArray addObject:mService];
|
||||
// struct _IOTInfo IOTInfo;
|
||||
//settingIOTInfoArray = [[NSMutableArray alloc] init];
|
||||
|
||||
// for (int i = 0; i < mIOTInfoArray.count; i++) {
|
||||
// [[mIOTInfoArray objectAtIndex:i] getValue:&IOTInfo];
|
||||
|
||||
// [settingIOTInfoArray addObject:[NSValue valueWithBytes:&IOTInfo objCType:@encode(struct _IOTInfo)]];
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
- (void) queryAllSettings {
|
||||
|
||||
NSMutableData *cmd = [[NSMutableData alloc] initWithBytes:cmdPrefix length:sizeof(cmdPrefix)];
|
||||
[cmd appendBytes:cmdGetAllSetting length:sizeof(cmdGetAllSetting)];
|
||||
[outputStream write:[cmd bytes] maxLength:[cmd length]];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
|
||||
|
||||
|
||||
|
||||
switch (streamEvent) {
|
||||
|
||||
case NSStreamEventOpenCompleted:
|
||||
NSLog(@"Stream opened");
|
||||
break;
|
||||
case NSStreamEventHasBytesAvailable:
|
||||
|
||||
if (theStream == inputStream) {
|
||||
|
||||
uint8_t buffer[64] = {0};
|
||||
int len;
|
||||
|
||||
while ([inputStream hasBytesAvailable]) {
|
||||
len = [[NSNumber numberWithInteger:[inputStream read:buffer maxLength: sizeof(buffer)]] intValue] ;
|
||||
if (len > 0) {
|
||||
|
||||
NSData *output = [[NSData alloc] initWithBytes:buffer length:len];
|
||||
|
||||
|
||||
if (nil != output) {
|
||||
|
||||
|
||||
if([self inputStreamReceivedParser:output] == 1)//update ui
|
||||
{
|
||||
self.baudRateField.text = [NSString stringWithFormat:@"%d",mBardRate];
|
||||
|
||||
self.dataBitField.text = [NSString stringWithFormat:@"%d",mDataBit];
|
||||
|
||||
if (mParityBit == 0)
|
||||
self.parityBitField.text = @"none";
|
||||
else if (mParityBit == 1)
|
||||
self.parityBitField.text = @"odd";
|
||||
else if (mParityBit == 2)
|
||||
self.parityBitField.text = @"even";
|
||||
|
||||
if (mStopBit == 0)
|
||||
self.stopBitField.text = @"none";
|
||||
else if (mStopBit == 1)
|
||||
self.stopBitField.text = @"1";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Serial Port Setup" message:@"Success!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
|
||||
[alert show];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case NSStreamEventErrorOccurred:
|
||||
|
||||
NSLog(@"Can not connect to the host!");
|
||||
break;
|
||||
|
||||
case NSStreamEventEndEncountered:
|
||||
|
||||
[theStream close];
|
||||
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
//[theStream release];
|
||||
theStream = nil;
|
||||
|
||||
break;
|
||||
default:
|
||||
NSLog(@"Unknown event");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (int) inputStreamReceivedParser:(NSData *)message {
|
||||
|
||||
uint8_t *recvCmd = (uint8_t *)[message bytes] ;
|
||||
|
||||
if ([self checkPrefix:recvCmd]){
|
||||
int readbit = 10;
|
||||
|
||||
if (recvCmd[readbit] == 0x01) { //response for ack
|
||||
return 0;//ok
|
||||
}else if (recvCmd[readbit] == 0x03) { //response for getting
|
||||
mBardRate = 0;
|
||||
mDataBit = 0;
|
||||
mParityBit = 0;
|
||||
mStopBit = 0;
|
||||
|
||||
readbit+=2;
|
||||
do{
|
||||
|
||||
if (recvCmd[readbit] == 0x01) { //baudrate
|
||||
int bit = 0;
|
||||
int tmp = 0;
|
||||
|
||||
int byteLen = recvCmd[++readbit];
|
||||
readbit++;
|
||||
|
||||
for (int i=readbit; i < (readbit+byteLen); i++) {
|
||||
|
||||
tmp = (recvCmd[i] & 0xFF) << (8*bit);
|
||||
mBardRate += tmp;
|
||||
bit++;
|
||||
}
|
||||
readbit+=(byteLen+1);
|
||||
|
||||
|
||||
}else if (recvCmd[readbit] == 0x02) { //data
|
||||
int byteLen = recvCmd[++readbit];
|
||||
readbit++;
|
||||
|
||||
if (byteLen == 1)
|
||||
mDataBit = recvCmd[readbit];
|
||||
else{
|
||||
|
||||
return -1;
|
||||
}
|
||||
readbit+=(byteLen+1);
|
||||
|
||||
}else if (recvCmd[readbit] == 0x04) { //parity
|
||||
int byteLen = recvCmd[++readbit];
|
||||
readbit++;
|
||||
|
||||
if (byteLen == 1)
|
||||
mParityBit = recvCmd[readbit];
|
||||
else{
|
||||
|
||||
return -1;
|
||||
}
|
||||
readbit+=(byteLen+1);
|
||||
|
||||
}else if (recvCmd[readbit] == 0x08) { //stopbit
|
||||
int byteLen = recvCmd[++readbit];
|
||||
readbit++;
|
||||
|
||||
if (byteLen == 1)
|
||||
mStopBit = recvCmd[readbit];
|
||||
else{
|
||||
|
||||
return -1;
|
||||
}
|
||||
readbit+=(byteLen+1);
|
||||
|
||||
}else
|
||||
readbit++;
|
||||
}while (readbit < [message length]);
|
||||
return 1;//update UI
|
||||
}//if (recvCmd[readbit] == 0x01)
|
||||
|
||||
|
||||
|
||||
}
|
||||
return 2;//other
|
||||
}
|
||||
|
||||
- (Boolean) checkPrefix:(uint8_t *) recvPrefix
|
||||
{
|
||||
for (int i = 0; i < sizeof(cmdPrefix); i++) {
|
||||
if(recvPrefix[i] != cmdPrefix[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
-(void)prepareForInitNetworkCommunication:(NSData *)mAddress Port:(int)mPort {
|
||||
|
||||
NSData *address = mAddress;
|
||||
char addressString[INET6_ADDRSTRLEN];
|
||||
int inetType;
|
||||
|
||||
struct sockaddr_in6 addr6;
|
||||
memcpy(&addr6, address.bytes, address.length);
|
||||
|
||||
if (address.length == 16) { // IPv4
|
||||
inetType = AF_INET;
|
||||
struct sockaddr_in addr4;
|
||||
memcpy(&addr4, address.bytes, address.length);
|
||||
inet_ntop(AF_INET, &addr4.sin_addr, addressString, 512);
|
||||
[self initNetworkCommunication:[NSString stringWithCString:addressString encoding:NSASCIIStringEncoding] Port:mPort];
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void) initNetworkCommunication:(NSString *)mIP Port:(int)mPort {
|
||||
|
||||
CFReadStreamRef readStream;
|
||||
CFWriteStreamRef writeStream;
|
||||
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)mIP, mPort, &readStream, &writeStream);
|
||||
|
||||
inputStream = (__bridge NSInputStream *)readStream;
|
||||
outputStream = (__bridge NSOutputStream *)writeStream;
|
||||
[inputStream setDelegate:self];
|
||||
[outputStream setDelegate:self];
|
||||
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
[inputStream open];
|
||||
[outputStream open];
|
||||
|
||||
}
|
||||
|
||||
- (void)textFieldDidBeginEditing:(UITextField *)textField
|
||||
{
|
||||
mTextFieldTag = (int)textField.tag;
|
||||
|
||||
[datapicker reloadAllComponents];
|
||||
|
||||
}
|
||||
|
||||
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
|
||||
{
|
||||
switch (mTextFieldTag) {
|
||||
case 0:
|
||||
self.baudRateField.text = baurateData[row];
|
||||
break;
|
||||
case 1:
|
||||
self.dataBitField.text = bitData[row];
|
||||
break;
|
||||
case 2:
|
||||
self.parityBitField.text = parityBitData[row];
|
||||
break;
|
||||
case 3:
|
||||
self.stopBitField.text = stopBitdata[row];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
[[self view] endEditing:YES];
|
||||
}
|
||||
|
||||
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
|
||||
{
|
||||
|
||||
switch (mTextFieldTag) {
|
||||
case 0:
|
||||
return baurateData[row];
|
||||
break;
|
||||
case 1:
|
||||
return bitData[row];
|
||||
break;
|
||||
case 2:
|
||||
return parityBitData[row];
|
||||
break;
|
||||
case 3:
|
||||
return stopBitdata[row];
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
|
||||
{
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
|
||||
{
|
||||
switch (mTextFieldTag) {
|
||||
case 0:
|
||||
return baurateData.count;
|
||||
break;
|
||||
case 1:
|
||||
return bitData.count;
|
||||
break;
|
||||
case 2:
|
||||
return parityBitData.count;
|
||||
break;
|
||||
case 3:
|
||||
return stopBitdata.count;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[super viewDidUnload];
|
||||
settingIOTInfoArray = nil;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[inputStream close];
|
||||
[outputStream close];
|
||||
self.selectedService = nil;
|
||||
settingIOTInfoArray = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
40
tools/uart_adapter/app/iOS/uartadapter/ViewController.h
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// ViewController.h
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 8/26/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
struct _IOTInfo {
|
||||
__unsafe_unretained NSNetService *service;
|
||||
__unsafe_unretained NSString *groupName;
|
||||
NSInteger groupID;
|
||||
|
||||
};
|
||||
|
||||
@interface ViewController : UICollectionViewController < /*UICollectionViewDelegateFlowLayout*/ NSNetServiceBrowserDelegate,
|
||||
NSNetServiceDelegate,
|
||||
UIAlertViewDelegate,
|
||||
NSStreamDelegate,
|
||||
NSNetServiceBrowserDelegate,
|
||||
NSNetServiceDelegate,
|
||||
UIGestureRecognizerDelegate> {
|
||||
NSNetServiceBrowser *_netServiceBrowser;
|
||||
NSMutableArray *_servicesArray;
|
||||
NSNetService *_selectedService;
|
||||
}
|
||||
|
||||
|
||||
@property (nonatomic, retain) NSMutableArray *IOTInfoArray;
|
||||
@property (nonatomic, retain) NSNetServiceBrowser *netServiceBrowser;
|
||||
@property (nonatomic, retain) NSMutableArray *controlServicesArray;
|
||||
@property (nonatomic, retain) NSMutableArray *dataServicesArray;
|
||||
@property (nonatomic, retain) NSNetService *selectedService;
|
||||
|
||||
- (IBAction) scanButton;
|
||||
|
||||
@end
|
||||
|
||||
1033
tools/uart_adapter/app/iOS/uartadapter/ViewController.m
Executable file
16
tools/uart_adapter/app/iOS/uartadapter/main.m
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// main.m
|
||||
// uartadapter
|
||||
//
|
||||
// Created by isaiah on 8/26/15.
|
||||
// Copyright (c) 2015 realtek. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
BIN
tools/uart_adapter/app/iOS/uartadapter/settings.png
Executable file
|
After Width: | Height: | Size: 1.1 KiB |
14
tools/uart_adapter/app/iOS/uartadapter/uartadapter-Prefix.pch
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Prefix header for all source files of the 'KxMenuExample' target in the 'KxMenuExample' project
|
||||
//
|
||||
|
||||
#import <Availability.h>
|
||||
|
||||
#ifndef __IPHONE_4_0
|
||||
#warning "This project uses features only available in iOS SDK 4.0 and later."
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||