2
0

Improved site operations UI.

[IMPROVED]  New UI for site operations.
[ADDED]     Ability to delete a site.
This commit is contained in:
Maarten Billemont 2014-02-21 00:19:24 -05:00
parent de3f51b447
commit 3fa9843855
6 changed files with 250 additions and 170 deletions

View File

@ -22,12 +22,12 @@
@interface MPElementCollectionView : NSCollectionViewItem
@property (nonatomic) MPElementModel *representedObject;
@property (nonatomic) NSString *typeTitle;
@property (nonatomic) NSString *loginNameTitle;
@property (nonatomic) NSString *counterTitle;
@property (nonatomic) BOOL counterHidden;
@property (nonatomic) BOOL updateContentHidden;
- (IBAction)toggleType:(id)sender;
- (IBAction)setLoginName:(id)sender;
- (IBAction)incrementCounter:(id)sender;
- (IBAction)updateLoginName:(id)sender;
- (IBAction)updateContent:(id)sender;
- (IBAction)delete:(id)sender;
@end

View File

@ -23,11 +23,10 @@
#define MPAlertChangeType @"MPAlertChangeType"
#define MPAlertChangeLogin @"MPAlertChangeLogin"
#define MPAlertChangeCounter @"MPAlertChangeCounter"
#define MPAlertChangeContent @"MPAlertChangeContent"
#define MPAlertDeleteSite @"MPAlertDeleteSite"
@implementation MPElementCollectionView {
id _representedObjectObserver;
}
@dynamic representedObject;
@ -38,27 +37,16 @@
return nil;
__weak MPElementCollectionView *wSelf = self;
_representedObjectObserver = [self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
dispatch_async( dispatch_get_main_queue(), ^{
wSelf.typeTitle = PearlString( @"Type:\n%@", wSelf.representedObject.typeName );
wSelf.loginNameTitle = PearlString( @"Login Name:\n%@", wSelf.representedObject.loginName );
if (wSelf.representedObject.type & MPElementTypeClassGenerated)
wSelf.counterTitle = PearlString( @"Number:\n%@", wSelf.representedObject.counter );
else if (wSelf.representedObject.type & MPElementTypeClassStored)
wSelf.counterTitle = PearlString( @"Update Password" );
wSelf.counterHidden = !(MPElementTypeClassGenerated & wSelf.representedObject.type);
wSelf.updateContentHidden = !(MPElementTypeClassStored & wSelf.representedObject.type);
} );
} forKeyPath:@"representedObject" options:0 context:nil];
} forKeyPath:@"representedObject" options:0 context:nil];
return self;
}
- (void)dealloc {
if (_representedObjectObserver)
[self removeObserver:_representedObjectObserver forKeyPath:@"representedObject"];
}
- (IBAction)toggleType:(id)sender {
id<MPAlgorithm> algorithm = self.representedObject.algorithm;
@ -74,7 +62,7 @@
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeType];
}
- (IBAction)setLoginName:(id)sender {
- (IBAction)updateLoginName:(id)sender {
NSAlert *alert = [NSAlert alertWithMessageText:@"Update Login Name"
defaultButton:@"Update" alternateButton:@"Cancel" otherButton:nil
@ -87,29 +75,26 @@
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeLogin];
}
- (IBAction)incrementCounter:(id)sender {
- (IBAction)updateContent:(id)sender {
if (self.representedObject.type & MPElementTypeClassGenerated) {
[[NSAlert alertWithMessageText:@"Change Password Number"
defaultButton:@"New Password" alternateButton:@"Cancel" otherButton:@"Initial Password"
informativeTextWithFormat:@"Increasing the password number gives you a new password for the site.\n"
@"You will need to update your account with the new password.\n\n"
@"Changing back to the initial password will reset the password number to 1."]
beginSheetModalForWindow:self.view.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeCounter];
}
NSAlert *alert = [NSAlert alertWithMessageText:@"Update Password"
defaultButton:@"Update" alternateButton:@"Cancel" otherButton:nil
informativeTextWithFormat:@"Enter the new password for %@:", self.representedObject.site];
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert setAccessoryView:passwordField];
[alert layout];
[passwordField becomeFirstResponder];
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeContent];
}
else if (self.representedObject.type & MPElementTypeClassStored) {
NSAlert *alert = [NSAlert alertWithMessageText:@"Update Password"
defaultButton:@"Update" alternateButton:@"Cancel" otherButton:nil
informativeTextWithFormat:@"Enter the new password for %@:", self.representedObject.site];
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert setAccessoryView:passwordField];
[alert layout];
[passwordField becomeFirstResponder];
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeContent];
}
- (IBAction)delete:(id)sender {
NSAlert *alert = [NSAlert alertWithMessageText:@"Delete Site"
defaultButton:@"Delete" alternateButton:@"Cancel" otherButton:nil
informativeTextWithFormat:@"Are you sure you want to delete the site: %@?", self.representedObject.site];
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertDeleteSite];
}
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
@ -178,49 +163,6 @@
return;
}
if (contextInfo == MPAlertChangeCounter) {
switch (returnCode) {
case NSAlertDefaultReturn: {
// "New Password" button.
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *element = [self.representedObject entityInContext:context];
if ([element isKindOfClass:[MPElementGeneratedEntity class]]) {
MPElementGeneratedEntity *generatedElement = (MPElementGeneratedEntity *)element;
++generatedElement.counter;
[context saveToStore];
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
}
}];
break;
}
case NSAlertAlternateReturn: {
// "Cancel" button.
break;
}
case NSAlertOtherReturn: {
// "Initial Password" button.
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *element = [self.representedObject entityInContext:context];
if ([element isKindOfClass:[MPElementGeneratedEntity class]]) {
MPElementGeneratedEntity *generatedElement = (MPElementGeneratedEntity *)element;
generatedElement.counter = 1;
[context saveToStore];
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
}
}];
break;
}
default:
break;
}
return;
}
if (contextInfo == MPAlertChangeContent) {
switch (returnCode) {
case NSAlertDefaultReturn: {
@ -245,6 +187,29 @@
break;
}
return;
}
if (contextInfo == MPAlertDeleteSite) {
switch (returnCode) {
case NSAlertDefaultReturn: {
// "Delete" button.
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *element = [self.representedObject entityInContext:context];
[context deleteObject:element];
[context saveToStore];
}];
break;
}
case NSAlertAlternateReturn: {
// "Cancel" button.
break;
}
default:
break;
}
return;
}
}

View File

@ -20,18 +20,19 @@
@class MPElementEntity;
@interface MPElementModel : NSObject
@property (nonatomic) NSString *site;
@property (nonatomic) MPElementType type;
@property (nonatomic) NSString *typeName;
@property (nonatomic) NSString *content;
@property (nonatomic) NSString *loginName;
@property (nonatomic) NSNumber *uses;
@property (nonatomic) NSNumber *counter;
@property (nonatomic) NSDate *lastUsed;
@property (nonatomic, strong) id<MPAlgorithm> algorithm;
- (MPElementEntity *)entityForMainThread;
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc;
@property (nonatomic, readonly) NSString *site;
@property (nonatomic, readonly) MPElementType type;
@property (nonatomic, readonly) NSString *typeName;
@property (nonatomic, readonly) NSString *content;
@property (nonatomic, readonly) NSString *loginName;
@property (nonatomic, readonly) NSNumber *uses;
@property (nonatomic) NSUInteger counter;
@property (nonatomic, readonly) NSDate *lastUsed;
@property (nonatomic, readonly) id<MPAlgorithm> algorithm;
@property (nonatomic, readonly) NSArray *types;
@property (nonatomic) NSUInteger typeIndex;
- (id)initWithEntity:(MPElementEntity *)entity;
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc;
@end

View File

@ -26,9 +26,13 @@
@interface MPElementModel()
@property(nonatomic, strong) NSManagedObjectID *entityOID;
@property(nonatomic, readwrite) NSString *content;
@property(nonatomic, readwrite) MPElementType type;
@property(nonatomic, readwrite) NSString *typeName;
@end
@implementation MPElementModel {
NSMutableDictionary *_typesByName;
}
- (id)initWithEntity:(MPElementEntity *)entity {
@ -36,25 +40,29 @@
if (!(self = [super init]))
return nil;
self.site = entity.name;
self.lastUsed = entity.lastUsed;
self.loginName = entity.loginName;
self.type = entity.type;
self.typeName = entity.typeName;
self.uses = entity.uses_;
self.counter = @([entity isKindOfClass:[MPElementGeneratedEntity class]]? [(MPElementGeneratedEntity *)entity counter]: 0);
self.content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
self.algorithm = entity.algorithm;
self.entityOID = entity.objectID;
_site = entity.name;
_lastUsed = entity.lastUsed;
_loginName = entity.loginName;
_type = entity.type;
_typeName = entity.typeName;
_uses = entity.uses_;
_counter = [entity isKindOfClass:[MPElementGeneratedEntity class]]? [(MPElementGeneratedEntity *)entity counter]: 0;
_content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
_algorithm = entity.algorithm;
_entityOID = entity.objectID;
// Find all password types and the index of the current type amongst them.
_typesByName = [NSMutableDictionary dictionary];
MPElementType type = _type;
do {
[_typesByName setObject:@(type) forKey:[_algorithm shortNameOfType:type]];
} while (_type != (type = [_algorithm nextType:type]));
_types = [_typesByName keysSortedByValueUsingSelector:@selector(compare:)];
_typeIndex = [[[_typesByName allValues] sortedArrayUsingSelector:@selector(compare:)] indexOfObject:@(_type)];
return self;
}
- (MPElementEntity *)entityForMainThread {
return [self entityInContext:[MPMacAppDelegate managedObjectContextForMainThreadIfReady]];
}
- (MPElementEntity *)entityInContext:(NSManagedObjectContext *)moc {
if (!_entityOID)
@ -68,4 +76,38 @@
return entity;
}
- (void)setCounter:(NSUInteger)counter {
if (counter == _counter)
return;
_counter = counter;
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *entity = [self entityInContext:context];
if ([entity isKindOfClass:[MPElementGeneratedEntity class]]) {
((MPElementGeneratedEntity *)entity).counter = counter;
[context saveToStore];
self.content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
}
}];
}
- (void)setTypeIndex:(NSUInteger)typeIndex {
if (typeIndex == _typeIndex)
return;
_typeIndex = typeIndex;
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPElementEntity *entity = [self entityInContext:context];
entity.type_ = _typesByName[_types[typeIndex]];
[context saveToStore];
self.type = entity.type;
self.typeName = entity.typeName;
self.content = [entity.algorithm resolveContentForElement:entity usingKey:[MPAppDelegate_Shared get].key];
}];
}
@end

View File

@ -197,34 +197,24 @@
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
if (commandSelector == @selector(cancel:)) {
if (commandSelector == @selector(cancel:))
[self close];
return YES;
}
if (commandSelector == @selector(moveUp:)) {
if (commandSelector == @selector(moveUp:))
self.elementSelectionIndexes =
[NSIndexSet indexSetWithIndex:MAX(self.elementSelectionIndexes.firstIndex, (NSUInteger)1) - 1];
return YES;
}
if (commandSelector == @selector(moveDown:)) {
if (commandSelector == @selector(moveDown:))
self.elementSelectionIndexes =
[NSIndexSet indexSetWithIndex:MIN(self.elementSelectionIndexes.firstIndex + 1, self.elements.count - 1)];
return YES;
}
if (commandSelector == @selector(moveLeft:)) {
if (commandSelector == @selector(moveLeft:))
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
return YES;
}
if (commandSelector == @selector(moveRight:)) {
if (commandSelector == @selector(moveRight:))
[[self selectedView].animator setBoundsOrigin:NSMakePoint( self.siteCollectionView.frame.size.width / 2, 0 )];
return YES;
}
if (commandSelector == @selector(insertNewline:)) {
if (commandSelector == @selector(insertNewline:))
[self useSite];
return YES;
}
else
return NO;
return NO;
return YES;
}
- (void)controlTextDidChange:(NSNotification *)note {

View File

@ -19,7 +19,7 @@
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="22" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" texturedBackground="YES"/>
<rect key="contentRect" x="600" y="530" width="480" height="320"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
<value key="minSize" type="size" width="480" height="320"/>
<value key="maxSize" type="size" width="480" height="320"/>
<view key="contentView" wantsLayer="YES" id="23">
@ -39,7 +39,7 @@
<shadow key="shadow" blurRadius="2">
<color key="color" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
</shadow>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" title="apple.com" placeholderString="Site name" usesSingleLineMode="YES" bezelStyle="round" id="185">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" placeholderString="Site name" usesSingleLineMode="YES" bezelStyle="round" id="185">
<font key="font" metaFont="cellTitle"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -88,11 +88,21 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tLu-3k-QiL">
<rect key="frame" x="449" y="288" width="25" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="51o-8V-9eq">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
<constraints>
<constraint firstItem="216" firstAttribute="top" secondItem="143" secondAttribute="top" constant="20" symbolic="YES" id="218"/>
<constraint firstItem="182" firstAttribute="top" secondItem="216" secondAttribute="bottom" constant="8" symbolic="YES" id="221"/>
<constraint firstAttribute="bottom" secondItem="tjI-mV-s8H" secondAttribute="bottom" id="6y8-tJ-1sX"/>
<constraint firstItem="tLu-3k-QiL" firstAttribute="top" secondItem="143" secondAttribute="top" constant="8" id="9h7-dN-MqZ"/>
<constraint firstAttribute="trailing" secondItem="tLu-3k-QiL" secondAttribute="trailing" constant="8" id="UQN-Ab-fIg"/>
<constraint firstAttribute="centerX" secondItem="182" secondAttribute="centerX" id="W6t-BO-Njn"/>
<constraint firstAttribute="trailing" secondItem="tjI-mV-s8H" secondAttribute="trailing" id="aKe-a9-Br8"/>
<constraint firstItem="tjI-mV-s8H" firstAttribute="leading" secondItem="143" secondAttribute="leading" id="d8F-JD-EhR"/>
@ -200,77 +210,149 @@
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<font key="titleFont" metaFont="system"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="oC2-zu-Voi">
<rect key="frame" x="480" y="-1" width="160" height="63"/>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vEl-aL-Qd4">
<rect key="frame" x="791" y="27" width="167" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="61" id="228-Aw-hiL"/>
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="5ZG-4S-zov">
<buttonCell key="cell" type="push" title="lhunath@lyndir.com" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sl3-bH-Hh2">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<string key="title">Type:
Long Password</string>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleType:" target="QBZ-sO-HQn" id="pdJ-Uz-fac"/>
<binding destination="QBZ-sO-HQn" name="title" keyPath="typeTitle" id="Ric-aa-82E"/>
<action selector="updateLoginName:" target="QBZ-sO-HQn" id="pJI-k8-LRl"/>
<binding destination="QBZ-sO-HQn" name="title" keyPath="representedObject.loginName" id="uaP-Y1-bz6">
<dictionary key="options">
<string key="NSNullPlaceholder">Click to set login name</string>
</dictionary>
</binding>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sEM-ko-UxJ">
<rect key="frame" x="640" y="-1" width="160" height="63"/>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d2a-pG-7CW">
<rect key="frame" x="528" y="31" width="127" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ymB-jq-V5d">
<popUpButtonCell key="cell" type="push" title="Long Password" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" selectedItem="7Bj-S7-WSd" id="RZo-c7-kqA">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" title="OtherViews" id="mQN-XZ-YKz">
<items>
<menuItem title="Long Password" state="on" id="7Bj-S7-WSd"/>
<menuItem title="Item 2" id="WUd-69-IBV"/>
<menuItem title="Item 3" id="pgH-yZ-G0J"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<binding destination="QBZ-sO-HQn" name="contentValues" keyPath="representedObject.types" id="bT1-aF-gww"/>
<binding destination="QBZ-sO-HQn" name="selectedIndex" keyPath="representedObject.typeIndex" previousBinding="bT1-aF-gww" id="U2t-Oc-k46"/>
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="npg-mh-AfY">
<rect key="frame" x="486" y="36" width="38" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type:" id="U2E-DE-2j4">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hqw-ZP-4c1">
<rect key="frame" x="486" y="11" width="59" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Number:" id="CDU-Ah-QDj">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="xlz-gk-Gwc"/>
</connections>
</textField>
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JPX-xQ-VKZ">
<rect key="frame" x="565" y="6" width="19" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<stepperCell key="cell" alignment="left" minValue="1" maxValue="100" doubleValue="1" autorepeat="NO" id="ELG-fy-nVF"/>
<connections>
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="3FO-ks-R7U"/>
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="awJ-Vg-RUn"/>
</connections>
</stepper>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kZI-sG-dEn">
<rect key="frame" x="549" y="11" width="13" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1" id="EUB-gJ-7Db">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="ZFX-79-eAY"/>
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="20y-tn-B5k"/>
</connections>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qOt-Rp-G9T">
<rect key="frame" x="877" y="2" width="81" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Delete" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QCU-VC-W0u">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<string key="title">Login Name:
lhunath@lyndir.com</string>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="setLoginName:" target="QBZ-sO-HQn" id="xMV-pi-ofl"/>
<binding destination="QBZ-sO-HQn" name="title" keyPath="loginNameTitle" id="4Bw-5R-OCr"/>
<action selector="delete:" target="QBZ-sO-HQn" id="mLJ-JY-5fz"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SA7-eS-Kal" userLabel="Square - Number: 1">
<rect key="frame" x="800" y="-1" width="160" height="63"/>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5YU-4W-4gz">
<rect key="frame" x="727" y="2" width="150" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7b3-Hz-grn">
<buttonCell key="cell" type="push" title="Change Password" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NQY-Oo-Eid">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<string key="title">Number:
1</string>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="incrementCounter:" target="QBZ-sO-HQn" id="dZP-Rc-LHA"/>
<binding destination="QBZ-sO-HQn" name="title" keyPath="counterTitle" id="cGQ-ec-Yyy"/>
<action selector="updateContent:" target="QBZ-sO-HQn" id="J8f-vx-10A"/>
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="updateContentHidden" id="UwG-p5-kH4"/>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bzg-90-kmh">
<rect key="frame" x="748" y="36" width="43" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Login:" id="uxE-6c-RjC">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<constraints>
<constraint firstAttribute="centerY" secondItem="SA7-eS-Kal" secondAttribute="centerY" id="72p-MU-EeL"/>
<constraint firstItem="SA7-eS-Kal" firstAttribute="height" secondItem="oC2-zu-Voi" secondAttribute="height" id="8ev-ss-Omh"/>
<constraint firstAttribute="trailing" secondItem="SA7-eS-Kal" secondAttribute="trailing" id="BDj-TF-YFN"/>
<constraint firstAttribute="centerY" secondItem="sEM-ko-UxJ" secondAttribute="centerY" id="F2A-cH-miL"/>
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="qOt-Rp-G9T" secondAttribute="centerY" id="6xp-tI-BkX"/>
<constraint firstItem="npg-mh-AfY" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="7kp-OB-3BI"/>
<constraint firstItem="kZI-sG-dEn" firstAttribute="leading" secondItem="hqw-ZP-4c1" secondAttribute="trailing" constant="8" symbolic="YES" id="8qK-Et-c1F"/>
<constraint firstItem="d2a-pG-7CW" firstAttribute="leading" secondItem="npg-mh-AfY" secondAttribute="trailing" constant="8" symbolic="YES" id="F6X-FD-kEX"/>
<constraint firstItem="Cn5-nt-e6X" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="FWS-tY-KkM"/>
<constraint firstItem="SA7-eS-Kal" firstAttribute="width" secondItem="sEM-ko-UxJ" secondAttribute="width" id="HKZ-ha-UXa"/>
<constraint firstItem="hqw-ZP-4c1" firstAttribute="top" secondItem="npg-mh-AfY" secondAttribute="bottom" constant="8" symbolic="YES" id="GuG-5I-quA"/>
<constraint firstItem="hqw-ZP-4c1" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="Hzf-XZ-auZ"/>
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="Cn5-nt-e6X" secondAttribute="trailing" constant="8" id="LjD-10-tVU"/>
<constraint firstItem="SA7-eS-Kal" firstAttribute="leading" secondItem="sEM-ko-UxJ" secondAttribute="trailing" id="Maf-za-cvg"/>
<constraint firstItem="oC2-zu-Voi" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" id="NJd-Us-uj8"/>
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" id="ODH-Nx-QdY"/>
<constraint firstAttribute="centerY" secondItem="oC2-zu-Voi" secondAttribute="centerY" id="ODK-IE-HEh"/>
<constraint firstItem="qOt-Rp-G9T" firstAttribute="centerY" secondItem="5YU-4W-4gz" secondAttribute="centerY" id="PdB-X5-eqF"/>
<constraint firstItem="xwJ-Pu-glP" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="QAM-jm-t0y"/>
<constraint firstAttribute="centerY" secondItem="tsT-Xh-Nxb" secondAttribute="centerY" id="Rpi-lc-dZ1"/>
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="mp4-r1-7Xg" secondAttribute="trailing" constant="8" id="Xfc-Jq-2Rb"/>
<constraint firstItem="SA7-eS-Kal" firstAttribute="width" secondItem="oC2-zu-Voi" secondAttribute="width" id="akL-8k-gbu"/>
<constraint firstAttribute="trailing" secondItem="vEl-aL-Qd4" secondAttribute="trailing" constant="8" id="ZZu-AS-C07"/>
<constraint firstAttribute="bottom" secondItem="tsT-Xh-Nxb" secondAttribute="bottom" id="ds1-7i-B7I"/>
<constraint firstItem="a1n-Sf-Mw6" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="e3g-2s-yee"/>
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="ftr-2Z-9J0"/>
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="d2a-pG-7CW" secondAttribute="centerY" id="g9a-r0-EOo"/>
<constraint firstAttribute="bottom" secondItem="mp4-r1-7Xg" secondAttribute="bottom" constant="8" id="jCW-5H-6pT"/>
<constraint firstAttribute="centerX" secondItem="tsT-Xh-Nxb" secondAttribute="centerX" id="kx6-g0-jUW"/>
<constraint firstAttribute="bottom" secondItem="a1n-Sf-Mw6" secondAttribute="bottom" constant="8" id="mWW-rt-kl2"/>
<constraint firstItem="SA7-eS-Kal" firstAttribute="height" secondItem="sEM-ko-UxJ" secondAttribute="height" id="mpf-ND-lSa"/>
<constraint firstItem="sEM-ko-UxJ" firstAttribute="leading" secondItem="oC2-zu-Voi" secondAttribute="trailing" id="tmV-ZM-J1I"/>
<constraint firstItem="npg-mh-AfY" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="n7Z-EF-Dcm"/>
<constraint firstItem="qOt-Rp-G9T" firstAttribute="leading" secondItem="5YU-4W-4gz" secondAttribute="trailing" constant="12" symbolic="YES" id="uWm-hE-itO"/>
<constraint firstAttribute="trailing" secondItem="qOt-Rp-G9T" secondAttribute="trailing" constant="8" id="x6J-1l-rU4"/>
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="xZ7-Mc-9dq"/>
<constraint firstItem="vEl-aL-Qd4" firstAttribute="leading" secondItem="bzg-90-kmh" secondAttribute="trailing" constant="8" symbolic="YES" id="z7h-om-WAV"/>
<constraint firstItem="xwJ-Pu-glP" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="z8k-ot-NjU"/>
<constraint firstItem="bzg-90-kmh" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="zbz-Qg-uHO"/>
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="zcO-M3-gyr"/>
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="leading" secondItem="kZI-sG-dEn" secondAttribute="trailing" constant="8" symbolic="YES" id="zvB-Vk-IL2"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" name="selectedControlColor" catalog="System" colorSpace="catalog"/>