Skip to content

Commit d1c6b2f

Browse files
committed
Automatically attempts to open last used file.
1 parent 81929c4 commit d1c6b2f

8 files changed

+111
-32
lines changed

EAGLEView/AppDelegate.h

+2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#define DROPBOX_APP_SECRET @"pgvi4d7y3gt2lx0"
1414
#define GLOBAL_TINT_COLOR 0xe25454 // 0xff8d3a //0x9b3aff
1515

16+
// Extern user defaults keys
1617
extern NSString *const kUserDefaults_lastDropboxPath;
18+
extern NSString *const kUserDefaults_lastFilePath;
1719

1820
@interface AppDelegate : UIResponder <UIApplicationDelegate, UIActionSheetDelegate>
1921

EAGLEView/AppDelegate.m

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
NSString *const kUserDefaults_lastDropboxPath = @"kUserDefaults_lastDropboxPath";
1717
NSString *const kUserDefaults_settingsKeepAlive = @"keep_awake";
18+
NSString *const kUserDefaults_lastFilePath = @"lastFilePath";
1819

1920
@implementation AppDelegate
2021
{

EAGLEView/DocumentChooserViewController.m

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ - (void)viewDidAppear:(BOOL)animated
7171
self.navigationItem.title = _path.lastPathComponent;
7272

7373
// Load from Dropbox
74-
[[Dropbox sharedInstance] loadContentsForFolder:_path completion:^(BOOL success, NSArray *contents) {
74+
[[Dropbox sharedInstance] loadContentsForFolder:_path completion:^(BOOL success, NSArray *contents, DBMetadata *metadata) {
7575

7676
// Remove HUD (whether it is there or not) and set title (possibly again)
7777
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
@@ -128,7 +128,7 @@ - (void)setItem:(DBMetadata *)item
128128
self.navigationItem.title = _item.filename;
129129

130130
// Load from Dropbox
131-
[[Dropbox sharedInstance] loadContentsForFolder:_item.path completion:^(BOOL success, NSArray *contents) {
131+
[[Dropbox sharedInstance] loadContentsForFolder:_item.path completion:^(BOOL success, NSArray *contents, DBMetadata *metadata) {
132132

133133
// Remove HUD (whether it is there or not) and set title (possibly again)
134134
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
@@ -147,7 +147,7 @@ - (void)setItem:(DBMetadata *)item
147147
else
148148
{
149149
// Error loading
150-
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Erro" message:@"Error loading contents from Dropbox" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
150+
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Error loading contents from Dropbox" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
151151
[alert show];
152152
}
153153
}];

EAGLEView/Dropbox.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
#import <Foundation/Foundation.h>
1010
#import <DropboxSDK/DropboxSDK.h>
1111

12-
typedef void(^foldercompletionBlock_t)(BOOL success, NSArray *contents);
13-
typedef void(^fileCompletionBlock_t)(BOOL success, NSString *filePath);
12+
// Extern definition of the Dropbox folder name (in case it is needed in some other file)
13+
extern NSString* const kDropboxFolderName;
14+
15+
typedef void(^foldercompletionBlock_t)(BOOL success, NSArray *contents, DBMetadata *metadata);
16+
typedef void(^fileCompletionBlock_t)(BOOL success, NSString *filePath, DBMetadata *metadata);
1417

1518

1619
@interface Dropbox : NSObject <DBRestClientDelegate>

EAGLEView/Dropbox.m

+10-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#import "Dropbox.h"
1010
#import "AppDelegate.h"
1111

12-
static NSString* const kDropboxFolderName = @"dropbox";
13-
typedef void(^genericBlock_t)(BOOL success, id contents); // This can be used for both folder and file completion blocks
12+
NSString* const kDropboxFolderName = @"dropbox";
13+
typedef void(^genericBlock_t)(BOOL success, id contents, DBMetadata *metadata); // This can be used for both folder and file completion blocks
1414

1515
@implementation Dropbox
1616
{
@@ -97,7 +97,7 @@ - (BOOL)loadContentsForFolder:(NSString*)path completion:(foldercompletionBlock_
9797
if( _contents[ [path lowercaseString] ] )
9898
{
9999
// Yes: return it immediately in the completion block
100-
completion( YES, _contents[ [path lowercaseString] ] );
100+
completion( YES, _contents[ [path lowercaseString] ], nil );
101101
return YES;
102102
}
103103

@@ -142,6 +142,8 @@ - (BOOL)loadFileAtPath:(NSString*)path completion:(fileCompletionBlock_t)complet
142142
NSAssert( error == nil, @"Error creating documents folder: %@", [error localizedDescription] );
143143
}
144144

145+
// Re-append last path component so the loaded file doesn't have the name of its parent directory.
146+
dropboxFolderPath = [dropboxFolderPath stringByAppendingPathComponent:[path lastPathComponent]];
145147
// Start loading
146148
_isBusy = YES;
147149
[[self restClient] loadFile:path intoPath:dropboxFolderPath];
@@ -153,14 +155,14 @@ - (BOOL)loadFileAtPath:(NSString*)path completion:(fileCompletionBlock_t)complet
153155
- (void)restClient:(DBRestClient*)client loadedFile:(NSString*)localPath contentType:(NSString*)contentType metadata:(DBMetadata*)metadata
154156
{
155157
DEBUG_LOG( @"File loaded into path: %@", localPath );
156-
_completionBlock( YES, localPath );
158+
_completionBlock( YES, localPath, metadata );
157159
_isBusy = NO;
158160
}
159161

160162
- (void)restClient:(DBRestClient*)client loadFileFailedWithError:(NSError*)error
161163
{
162164
DEBUG_LOG( @"There was an error loading the file - %@", [error localizedDescription] );
163-
_completionBlock( NO, nil );
165+
_completionBlock( NO, nil, nil );
164166
_isBusy = NO;
165167
}
166168

@@ -169,7 +171,7 @@ - (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata
169171
// If the folder is deleted, we'll consider it non-existing
170172
if( metadata.isDeleted )
171173
{
172-
_completionBlock( NO, nil );
174+
_completionBlock( NO, nil, nil );
173175
_isBusy = NO;
174176
return;
175177
}
@@ -178,14 +180,14 @@ - (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata
178180
_contents[ [metadata.path lowercaseString] ] = metadata.contents;
179181

180182
// Call completion block
181-
_completionBlock( YES, metadata.contents );
183+
_completionBlock( YES, metadata.contents, metadata );
182184
_isBusy = NO;
183185
}
184186

185187
- (void)restClient:(DBRestClient *)client loadMetadataFailedWithError:(NSError *)error
186188
{
187189
DEBUG_LOG( @"Error loading metadata: %@", [error localizedDescription] );
188-
_completionBlock( NO, nil );
190+
_completionBlock( NO, nil, nil );
189191
_isBusy = NO;
190192
}
191193

EAGLEView/ViewController.h

+9
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,13 @@
2121
- (void)openFile:(EAGLEFile*)file;
2222
- (IBAction)zoomToFitAction:(id)sender;
2323

24+
/**
25+
Opens a schematic or board file from the specified local path.
26+
27+
@return Returns YES if the operation was successful; NO otherwise
28+
@param filePath The full path to the file to open.
29+
@param error Error handle
30+
*/
31+
- (BOOL)openFileAtPath:(NSString*)filePath error:(NSError**)error;
32+
2433
@end

EAGLEView/ViewController.m

+79-19
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,44 @@ - (void)viewDidLoad
4848

4949
// Show placeholder image
5050
self.placeholderImageView.hidden = NO;
51-
52-
// Initialize file view. We have to initialize with a valid file. Otherwise the drawing context is messed up (for some reason).
53-
NSError *error = nil;
54-
55-
_eagleFile = [EAGLEBoard boardFromBoardFile:@"" error:&error]; // Empty board
56-
//_eagleFile = [EAGLESchematic schematicFromSchematicFile:@"" error:&error]; // Empty schematic
57-
//_eagleFile = [EAGLESchematic schematicFromSchematicFile:@"#2014-003_Powerpack" error:&error];
58-
//_eagleFile = [EAGLEBoard boardFromBoardFile:@"Gift card" error:nil];
59-
60-
_eagleFile.fileName = @"";
61-
_eagleFile.fileDate = [NSDate date];
62-
NSAssert( error == nil, @"Error loading file: %@", [error localizedDescription] );
6351
[self.fileView setRelativeZoomFactor:0.1];
64-
self.fileView.file = _eagleFile;
6552

66-
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC ), dispatch_get_main_queue(), ^{
67-
[self zoomToFitAction:nil];
68-
});
69-
70-
[self updateBackgroundAndStatusBar];
53+
// If we have a local file path saved in user defaults, attempt to open that
54+
NSError *error = nil;
55+
BOOL hasLoadedLastFile = NO;
56+
NSString *lastUsedFilePath = [[NSUserDefaults standardUserDefaults] objectForKey:kUserDefaults_lastFilePath];
57+
if( [lastUsedFilePath length] > 0 )
58+
{
59+
// Construct full path. Value in user defaults is relative to the app's dropbox folder in the documents folder.
60+
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
61+
NSString *documentsFolder = paths[0];
62+
NSString *fullPath = [[documentsFolder stringByAppendingPathComponent:kDropboxFolderName] stringByAppendingPathComponent:lastUsedFilePath];
63+
64+
DEBUG_LOG( @"Opening last used file: %@", fullPath );
65+
hasLoadedLastFile = [self openFileAtPath:fullPath error:&error];
66+
if( error )
67+
NSLog( @"Error loading last used file: %@", error );
68+
}
69+
if( !hasLoadedLastFile )
70+
{
71+
// Initialize file view. We have to initialize with a valid file. Otherwise the drawing context is messed up (for some reason).
72+
error = nil;
73+
_eagleFile = [EAGLEBoard boardFromBoardFile:@"" error:&error]; // Empty board
74+
//_eagleFile = [EAGLESchematic schematicFromSchematicFile:@"" error:&error]; // Empty schematic
75+
//_eagleFile = [EAGLESchematic schematicFromSchematicFile:@"#2014-003_Powerpack" error:&error];
76+
//_eagleFile = [EAGLEBoard boardFromBoardFile:@"Gift card" error:nil];
77+
78+
_eagleFile.fileName = @"";
79+
_eagleFile.fileDate = [NSDate date];
80+
NSAssert( error == nil, @"Error loading file: %@", [error localizedDescription] );
81+
self.fileView.file = _eagleFile;
82+
83+
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC ), dispatch_get_main_queue(), ^{
84+
[self zoomToFitAction:nil];
85+
});
86+
87+
[self updateBackgroundAndStatusBar];
88+
}
7189

7290
// Add double tap recognizer (NB: behaves differently on iPad/iPhone – see the handler method
7391
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapGesture:)];
@@ -431,6 +449,8 @@ - (IBAction)zoomToFitAction:(id)sender
431449
- (void)openFileFromURL:(NSURL*)fileURL
432450
{
433451
// Make sure it's a file URL
452+
[NSException raise:@"Possibly wrong method." format:@"This method seems to load only schematics. Are you sure that's right?"];
453+
434454
if( ![fileURL isFileURL] )
435455
[NSException raise:@"Invalid URL" format:@"Expected file URL: %@", [fileURL absoluteString]];
436456

@@ -461,6 +481,42 @@ - (void)openFile:(EAGLEFile*)file
461481
});
462482
}
463483

484+
- (BOOL)openFileAtPath:(NSString*)filePath error:(NSError**)error
485+
{
486+
NSError *err;
487+
488+
// Schematic or board?
489+
NSString *fileName = [filePath lastPathComponent];
490+
491+
if( [[[fileName pathExtension] lowercaseString] isEqualToString:@"sch"] )
492+
_eagleFile = [EAGLESchematic schematicFromSchematicAtPath:filePath error:&err];
493+
else if( [[[fileName pathExtension] lowercaseString] isEqualToString:@"brd"] )
494+
_eagleFile = [EAGLEBoard boardFromBoardFileAtPath:filePath error:&err];
495+
496+
// Pass back error and return NO if we have an error
497+
if( err != nil )
498+
{
499+
if( error )
500+
*error = err;
501+
return NO;
502+
}
503+
504+
_eagleFile.fileName = fileName;
505+
// _eagleFile.fileDate = fileDate; /// TODO: date?
506+
507+
[self updateBackgroundAndStatusBar];
508+
509+
self.fileView.file = _eagleFile;
510+
self.placeholderImageView.hidden = YES; // Hide initial placeholder
511+
512+
dispatch_async(dispatch_get_main_queue(), ^{
513+
[self.fileView zoomToFitSize:self.scrollView.bounds.size animated:YES];
514+
[MBProgressHUD hideHUDForView:self.view animated:YES];
515+
});
516+
517+
return YES;
518+
}
519+
464520
#pragma mark - Document Chooser Delegate methods
465521

466522
- (void)documentChooserPickedDropboxFile:(DBMetadata *)metadata lastPath:(NSString*)lastPath
@@ -482,7 +538,7 @@ - (void)documentChooserPickedDropboxFile:(DBMetadata *)metadata lastPath:(NSStri
482538
// Remember file data
483539
NSDate *fileDate = metadata.lastModifiedDate;
484540
NSString *fileName = [metadata.path lastPathComponent];
485-
[[Dropbox sharedInstance] loadFileAtPath:metadata.path completion:^(BOOL success, NSString *filePath) {
541+
[[Dropbox sharedInstance] loadFileAtPath:metadata.path completion:^(BOOL success, NSString *filePath, DBMetadata *metadata) {
486542

487543
if( success )
488544
{
@@ -504,6 +560,10 @@ - (void)documentChooserPickedDropboxFile:(DBMetadata *)metadata lastPath:(NSStri
504560
self.fileView.file = _eagleFile;
505561
self.placeholderImageView.hidden = YES; // Hide initial placeholder
506562

563+
// Save path in user defaults. This path is relative to the app's documents directory.
564+
[[NSUserDefaults standardUserDefaults] setObject:metadata.path forKey:kUserDefaults_lastFilePath];
565+
[[NSUserDefaults standardUserDefaults] synchronize];
566+
507567
dispatch_async(dispatch_get_main_queue(), ^{
508568
[self.fileView zoomToFitSize:self.scrollView.bounds.size animated:YES];
509569
[MBProgressHUD hideHUDForView:self.view animated:YES];

To-do.txt

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ To-do:
2828
- Fix part info popup location on iPhone
2929
- Add padding to auto-size bounding rect
3030
- Fix the goddamn zoom-to-fit!
31+
- Disable sheets picker if there is only one sheet/module or if it's a board file
3132

3233

3334
------------------------
@@ -41,6 +42,7 @@ In progress/partly done:
4142
-----
4243
Done:
4344

45+
√ Automatically open last file
4446
√ Placeholder view when no schematic/board is selected
4547
√ UI: double tap on module instance -> show module (first sheet)
4648
√ New Dropbox and zoom-to-fit icons

0 commit comments

Comments
 (0)