mirror of
https://github.com/libretro/RetroArch
synced 2025-01-30 03:32:46 +00:00
(Cocoa) Remove unused cocoa_settings.m and cocoatouch_browser.m
This commit is contained in:
parent
f373527856
commit
4ae73d2a1b
@ -1,386 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013-2014 - Jason Fetters
|
||||
* Copyright (C) 2011-2015 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#include <compat/apple_compat.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#include "cocoa_common.h"
|
||||
#include "../../../menu/menu_setting.h"
|
||||
#include "../../../input/drivers/cocoa_input.h"
|
||||
|
||||
#include "../../../driver.h"
|
||||
#include "../../../input/input_common.h"
|
||||
#include "../../../input/input_keymaps.h"
|
||||
|
||||
static void* const associated_name_tag = (void*)&associated_name_tag;
|
||||
|
||||
@interface RAInputBinder : NSWindow
|
||||
{
|
||||
#if !__OBJC2__
|
||||
NSTimer* _timer;
|
||||
const rarch_setting_t *_setting;
|
||||
#endif
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSTimer* timer;
|
||||
@property (nonatomic, assign) const rarch_setting_t* setting;
|
||||
@end
|
||||
|
||||
@implementation RAInputBinder
|
||||
|
||||
@synthesize timer = _timer;
|
||||
@synthesize setting = _setting;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_timer release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)runForSetting:(const rarch_setting_t*)setting onWindow:(NSWindow*)window
|
||||
{
|
||||
self.setting = setting;
|
||||
self.timer = [NSTimer timerWithTimeInterval:.1f target:self selector:@selector(checkBind:) userInfo:nil repeats:YES];
|
||||
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSModalPanelRunLoopMode];
|
||||
|
||||
[NSApp beginSheet:self modalForWindow:window modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
||||
}
|
||||
|
||||
- (IBAction)goAway:(id)sender
|
||||
{
|
||||
[self.timer invalidate];
|
||||
self.timer = nil;
|
||||
|
||||
[NSApp endSheet:self];
|
||||
[self orderOut:nil];
|
||||
}
|
||||
|
||||
- (void)checkBind:(NSTimer*)send
|
||||
{
|
||||
int32_t value = 0;
|
||||
int32_t idx = 0;
|
||||
|
||||
if (self.setting->index)
|
||||
idx = self.setting->index - 1;
|
||||
|
||||
if ((value = cocoa_input_find_any_key()))
|
||||
BINDFOR(*[self setting]).key = input_keymaps_translate_keysym_to_rk(value);
|
||||
else if ((value = cocoa_input_find_any_button(idx)) >= 0)
|
||||
BINDFOR(*[self setting]).joykey = value;
|
||||
else if ((value = cocoa_input_find_any_axis(idx)))
|
||||
BINDFOR(*[self setting]).joyaxis = (value > 0) ? AXIS_POS(value - 1) : AXIS_NEG(abs(value) - 1);
|
||||
else
|
||||
return;
|
||||
|
||||
[self goAway:self];
|
||||
}
|
||||
|
||||
// Stop the annoying sound when pressing a key
|
||||
- (void)keyDown:(NSEvent*)theEvent
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface RASettingsDelegate : NSObject
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
<NSTableViewDataSource, NSTableViewDelegate,
|
||||
NSOutlineViewDataSource, NSOutlineViewDelegate,
|
||||
NSWindowDelegate>
|
||||
#endif
|
||||
{
|
||||
#if !__OBJC2__
|
||||
RAInputBinder* _binderWindow;
|
||||
NSButtonCell* _booleanCell;
|
||||
NSTextFieldCell* _binderCell;
|
||||
NSTableView* _table;
|
||||
NSOutlineView* _outline;
|
||||
NSMutableArray* _settings;
|
||||
NSMutableArray* _currentGroup;
|
||||
#endif
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) RAInputBinder IBOutlet* binderWindow;
|
||||
@property (nonatomic, retain) NSButtonCell IBOutlet* booleanCell;
|
||||
@property (nonatomic, retain) NSTextFieldCell IBOutlet* binderCell;
|
||||
@property (nonatomic, retain) NSTableView IBOutlet* table;
|
||||
@property (nonatomic, retain) NSOutlineView IBOutlet* outline;
|
||||
@property (nonatomic, retain) NSMutableArray* settings;
|
||||
@property (nonatomic, retain) NSMutableArray* currentGroup;
|
||||
@end
|
||||
|
||||
@implementation RASettingsDelegate
|
||||
|
||||
@synthesize binderWindow = _binderWindow;
|
||||
@synthesize booleanCell = _booleanCell;
|
||||
@synthesize binderCell = _binderCell;
|
||||
@synthesize table = _table;
|
||||
@synthesize outline = _outline;
|
||||
@synthesize settings = _settings;
|
||||
@synthesize currentGroup = _currentGroup;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_binderWindow release];
|
||||
[_booleanCell release];
|
||||
[_binderCell release];
|
||||
[_table release];
|
||||
[_outline release];
|
||||
[_settings release];
|
||||
[_currentGroup release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
int i;
|
||||
NSMutableArray* thisGroup = nil;
|
||||
NSMutableArray* thisSubGroup = nil;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
const rarch_setting_t *setting_data = (const rarch_setting_t *)driver->menu->list_settings;
|
||||
|
||||
self.settings = [NSMutableArray array];
|
||||
|
||||
for (i = 0; setting_data[i].type; i ++)
|
||||
{
|
||||
switch (setting_data[i].type)
|
||||
{
|
||||
case ST_GROUP:
|
||||
{
|
||||
thisGroup = [NSMutableArray array];
|
||||
#if defined(MAC_OS_X_VERSION_10_6)
|
||||
/* FIXME - Rewrite this so that this is no longer an associated object - requires ObjC 2.0 runtime */
|
||||
objc_setAssociatedObject(thisGroup, associated_name_tag, BOXSTRING(setting_data[i].name), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case ST_END_GROUP:
|
||||
{
|
||||
if (thisGroup)
|
||||
[self.settings addObject:thisGroup];
|
||||
thisGroup = nil;
|
||||
break;
|
||||
}
|
||||
|
||||
case ST_SUB_GROUP:
|
||||
{
|
||||
thisSubGroup = [NSMutableArray array];
|
||||
#if defined(MAC_OS_X_VERSION_10_6)
|
||||
/* FIXME - Rewrite this so that this is no longer an associated object - requires ObjC 2.0 runtime */
|
||||
objc_setAssociatedObject(thisSubGroup, associated_name_tag, BOXSTRING(setting_data[i].name), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case ST_END_SUB_GROUP:
|
||||
{
|
||||
if (thisSubGroup)
|
||||
[thisGroup addObject:thisSubGroup];
|
||||
thisSubGroup = nil;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
[thisSubGroup addObject:[NSNumber numberWithInt:i]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
[NSApp stopModal];
|
||||
}
|
||||
|
||||
#pragma mark Section Table
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView*)view
|
||||
{
|
||||
return self.settings.count;
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
{
|
||||
#if defined(MAC_OS_X_VERSION_10_6)
|
||||
return objc_getAssociatedObject([self.settings objectAtIndex:row], associated_name_tag);
|
||||
#else
|
||||
/* FIXME - Rewrite this so that this is no longer an associated object - requires ObjC 2.0 runtime */
|
||||
return 0; /* stub */
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
|
||||
{
|
||||
self.currentGroup = [self.settings objectAtIndex:[self.table selectedRow]];
|
||||
[self.outline reloadData];
|
||||
}
|
||||
|
||||
#pragma mark Setting Outline
|
||||
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
return (item == nil) ? [self.currentGroup count] : [item count];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)idx ofItem:(id)item
|
||||
{
|
||||
return (item == nil) ? [self.currentGroup objectAtIndex:idx] : [item objectAtIndex:idx];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
|
||||
{
|
||||
return [item isKindOfClass:[NSArray class]];
|
||||
}
|
||||
|
||||
- (BOOL)validateProposedFirstResponder:(NSResponder*)responder forEvent:(NSEvent*)event
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
driver_t *driver = driver_get_ptr();
|
||||
|
||||
if (!tableColumn)
|
||||
return nil;
|
||||
|
||||
if ([item isKindOfClass:[NSArray class]])
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
/* FIXME - Rewrite this so that this is no longer an associated object - requires ObjC 2.0 runtime */
|
||||
if ([[tableColumn identifier] isEqualToString:BOXSTRING("left")])
|
||||
return objc_getAssociatedObject(item, associated_name_tag);
|
||||
#endif
|
||||
return BOXSTRING("");
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[PATH_MAX_LENGTH];
|
||||
rarch_setting_t *setting_data = (rarch_setting_t*)driver->menu->list_settings;
|
||||
rarch_setting_t *setting = (rarch_setting_t*)&setting_data[[item intValue]];
|
||||
|
||||
if ([[tableColumn identifier] isEqualToString:BOXSTRING("left")])
|
||||
return BOXSTRING(setting->short_description);
|
||||
|
||||
switch (setting->type)
|
||||
{
|
||||
case ST_BOOL:
|
||||
return BOXINT(*setting->value.boolean);
|
||||
default:
|
||||
{
|
||||
setting_get_string_representation(setting, buffer, sizeof(buffer));
|
||||
if (buffer[0] == '\0')
|
||||
strlcpy(buffer, "N/A", sizeof(buffer));
|
||||
return BOXSTRING(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSCell*)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
const rarch_setting_t *setting_data, *setting;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
|
||||
if (!tableColumn)
|
||||
return nil;
|
||||
|
||||
if ([item isKindOfClass:[NSArray class]])
|
||||
return [tableColumn dataCell];
|
||||
|
||||
if ([[tableColumn identifier] isEqualToString:BOXSTRING("left")])
|
||||
return [tableColumn dataCell];
|
||||
|
||||
setting_data = (const rarch_setting_t *)driver->menu->list_settings;
|
||||
setting = (const rarch_setting_t *)&setting_data[[item intValue]];
|
||||
|
||||
switch (setting->type)
|
||||
{
|
||||
case ST_BOOL:
|
||||
return self.booleanCell;
|
||||
case ST_BIND:
|
||||
return self.binderCell;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return tableColumn.dataCell;
|
||||
}
|
||||
|
||||
- (IBAction)outlineViewClicked:(id)sender
|
||||
{
|
||||
id item;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
|
||||
if ([self.outline clickedColumn] != 1)
|
||||
return;
|
||||
|
||||
item = [self.outline itemAtRow:[self.outline clickedRow]];
|
||||
|
||||
if (![item isKindOfClass:[NSNumber class]])
|
||||
return;
|
||||
|
||||
{
|
||||
rarch_setting_t *setting_data = (rarch_setting_t*)driver->menu->list_settings;
|
||||
rarch_setting_t *setting = (rarch_setting_t*)&setting_data[[item intValue]];
|
||||
|
||||
switch (setting->type)
|
||||
{
|
||||
case ST_BOOL:
|
||||
*setting->value.boolean = !*setting->value.boolean;
|
||||
break;
|
||||
case ST_BIND:
|
||||
[self.binderWindow runForSetting:setting onWindow:[self.outline window]];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (setting->change_handler)
|
||||
setting->change_handler(setting);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)controlTextDidEndEditing:(NSNotification*)notification
|
||||
{
|
||||
id item;
|
||||
NSText* editor = NULL;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
|
||||
if ([notification object] != self.outline)
|
||||
return;
|
||||
|
||||
editor = [[notification userInfo] objectForKey:BOXSTRING("NSFieldEditor")];
|
||||
item = [self.outline itemAtRow:[self.outline selectedRow]];
|
||||
|
||||
if (![item isKindOfClass:[NSNumber class]])
|
||||
return;
|
||||
|
||||
{
|
||||
rarch_setting_t *setting_data = (rarch_setting_t *)driver->menu->list_settings;
|
||||
rarch_setting_t *setting = (rarch_setting_t*)&setting_data[[item intValue]];
|
||||
NSString *editor_string = (NSString*)editor.string;
|
||||
|
||||
setting_set_with_string_representation(setting, editor_string.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -1,583 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013-2014 - Jason Fetters
|
||||
* Copyright (C) 2014-2015 - Jay McCarthy
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <file/file_extract.h>
|
||||
#include <file/dir_list.h>
|
||||
#include <file/file_path.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <rhash.h>
|
||||
|
||||
#include "cocoa_common.h"
|
||||
#include "../../../content.h"
|
||||
#include "../../../general.h"
|
||||
|
||||
enum file_action
|
||||
{
|
||||
FA_DELETE = 10000,
|
||||
FA_CREATE,
|
||||
FA_MOVE,
|
||||
FA_UNZIP
|
||||
};
|
||||
|
||||
static const void* const associated_module_key = &associated_module_key;
|
||||
|
||||
static int zlib_extract_callback(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata)
|
||||
{
|
||||
char path[PATH_MAX_LENGTH];
|
||||
|
||||
/* Make directory */
|
||||
fill_pathname_join(path, (const char*)userdata, name, sizeof(path));
|
||||
path_basedir(path);
|
||||
|
||||
if (!path_mkdir(path))
|
||||
{
|
||||
RARCH_ERR("Failed to create dir: %s.\n", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Ignore directories */
|
||||
if (name[strlen(name) - 1] == '/')
|
||||
return 1;
|
||||
|
||||
fill_pathname_join(path, (const char*)userdata, name, sizeof(path));
|
||||
|
||||
if (!zlib_perform_mode(path, valid_exts,
|
||||
cdata, cmode, csize, size, crc32, userdata))
|
||||
{
|
||||
if (cmode == 0)
|
||||
{
|
||||
RARCH_ERR("Failed to write file: %s.\n", path);
|
||||
return 0;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
RARCH_ERR("Failed to deflate to: %s.\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void unzip_file(const char* path, const char* output_directory)
|
||||
{
|
||||
if (!path_file_exists(path))
|
||||
apple_display_alert("Could not locate zip file.", "Action Failed");
|
||||
else if (path_is_directory(output_directory))
|
||||
apple_display_alert("Output directory for zip must not already exist.", "Action Failed");
|
||||
else if (!path_mkdir(output_directory))
|
||||
apple_display_alert("Could not create output directory to extract zip.", "Action Failed");
|
||||
else if (!zlib_parse_file(path, NULL, zlib_extract_callback, (void*)output_directory))
|
||||
apple_display_alert("Could not process zip file.", "Action Failed");
|
||||
}
|
||||
|
||||
static void file_action(enum file_action action, NSString* source, NSString* target)
|
||||
{
|
||||
NSError* error = nil;
|
||||
bool result = false;
|
||||
NSFileManager* manager = [NSFileManager defaultManager];
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case FA_DELETE:
|
||||
result = [manager removeItemAtPath:target error:&error];
|
||||
break;
|
||||
case FA_CREATE:
|
||||
result = [manager createDirectoryAtPath:target withIntermediateDirectories:YES
|
||||
attributes:nil error:&error];
|
||||
break;
|
||||
case FA_MOVE:
|
||||
result = [manager moveItemAtPath:source toPath:target error:&error];
|
||||
break;
|
||||
case FA_UNZIP:
|
||||
unzip_file(source.UTF8String, target.UTF8String);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result && error)
|
||||
apple_display_alert(error.localizedDescription.UTF8String, "Action failed");
|
||||
}
|
||||
|
||||
@implementation RADirectoryItem
|
||||
+ (RADirectoryItem*)directoryItemFromPath:(NSString*)path
|
||||
{
|
||||
RADirectoryItem* item = [RADirectoryItem new];
|
||||
|
||||
if (!item)
|
||||
return NULL;
|
||||
|
||||
item.path = path;
|
||||
item.isDirectory = path_is_directory(path.UTF8String);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
+ (RADirectoryItem*)directoryItemFromElement:(struct string_list_elem*)element
|
||||
{
|
||||
RADirectoryItem* item = [RADirectoryItem new];
|
||||
|
||||
if (!item)
|
||||
return NULL;
|
||||
|
||||
item.path = BOXSTRING(element->data);
|
||||
item.isDirectory = (element->attr.i == RARCH_DIRECTORY);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)cellForTableView:(UITableView *)tableView
|
||||
{
|
||||
static NSString* const cell_id = @"path_item";
|
||||
static NSString* const icon_types[2] = { @"ic_file", @"ic_dir" };
|
||||
uint32_t type_id = self.isDirectory ? 1 : 0;
|
||||
UITableViewCell *result = [tableView dequeueReusableCellWithIdentifier:cell_id];
|
||||
|
||||
if (!result)
|
||||
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
|
||||
|
||||
result.textLabel.text = [self.path lastPathComponent];
|
||||
result.imageView.image = [UIImage imageNamed:icon_types[type_id]];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)wasSelectedOnTableView:(UITableView *)tableView ofController:(UIViewController *)controller
|
||||
{
|
||||
if (self.isDirectory)
|
||||
[(id)controller browseTo:self.path];
|
||||
else
|
||||
[(id)controller chooseAction]((id)controller, self);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*********************************************/
|
||||
/* RAMenuItemBasic */
|
||||
/* A simple menu item that displays a text */
|
||||
/* description and calls a block object when */
|
||||
/* selected. */
|
||||
/*********************************************/
|
||||
@interface RAMenuItemBasic : NSObject
|
||||
@property (nonatomic) NSString* description;
|
||||
@property (nonatomic) id userdata;
|
||||
@property (copy) void (^action)(id userdata);
|
||||
@property (copy) NSString* (^detail)(id userdata);
|
||||
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action;
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action detail:(NSString* (^)())detail;
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description association:(id)userdata action:(void (^)())action detail:(NSString* (^)())detail;
|
||||
|
||||
@end
|
||||
|
||||
/*********************************************/
|
||||
/* RAMenuItemBasic */
|
||||
/* A simple menu item that displays a text */
|
||||
/* description and calls a block object when */
|
||||
/* selected. */
|
||||
/*********************************************/
|
||||
@implementation RAMenuItemBasic
|
||||
@synthesize description;
|
||||
@synthesize userdata;
|
||||
@synthesize action;
|
||||
@synthesize detail;
|
||||
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action
|
||||
{
|
||||
return [self itemWithDescription:description action:action detail:Nil];
|
||||
}
|
||||
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action detail:(NSString* (^)())detail
|
||||
{
|
||||
return [self itemWithDescription:description association:nil action:action detail:detail];
|
||||
}
|
||||
|
||||
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description association:(id)userdata action:(void (^)())action detail:(NSString* (^)())detail
|
||||
{
|
||||
RAMenuItemBasic* item = [RAMenuItemBasic new];
|
||||
item.description = description;
|
||||
item.userdata = userdata;
|
||||
item.action = action;
|
||||
item.detail = detail;
|
||||
return item;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
|
||||
{
|
||||
static NSString* const cell_id = @"text";
|
||||
|
||||
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
|
||||
if (!result)
|
||||
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
|
||||
|
||||
result.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
result.textLabel.text = self.description;
|
||||
result.detailTextLabel.text = self.detail ? self.detail(self.userdata) : nil;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
||||
{
|
||||
if (self.action)
|
||||
self.action(self.userdata);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RADirectoryList
|
||||
|
||||
- (id)initWithPath:(NSString*)path extensions:(const char*)extensions
|
||||
action:(void (^)(RADirectoryList* list, RADirectoryItem* item))action
|
||||
{
|
||||
if ((self = [super initWithStyle:UITableViewStylePlain]))
|
||||
{
|
||||
NSMutableArray *toolbarButtons;
|
||||
self.path = path ? path : NSHomeDirectory();
|
||||
self.chooseAction = action;
|
||||
self.extensions = extensions ? BOXSTRING(extensions) : 0;
|
||||
self.hidesHeaders = YES;
|
||||
|
||||
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:BOXSTRING("Up") style:UIBarButtonItemStyleBordered target:self
|
||||
action:@selector(gotoParent)];
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self
|
||||
action:@selector(cancelBrowser)];
|
||||
|
||||
/* NOTE: The "App" and "Root" buttons aren't really needed for non-jailbreak devices. */
|
||||
toolbarButtons = [NSMutableArray arrayWithObjects:
|
||||
[[UIBarButtonItem alloc] initWithTitle:BOXSTRING("Home") style:UIBarButtonItemStyleBordered target:self
|
||||
action:@selector(gotoHomeDir)],
|
||||
[[UIBarButtonItem alloc] initWithTitle:BOXSTRING("App") style:UIBarButtonItemStyleBordered target:self
|
||||
action:@selector(gotoAppDir)],
|
||||
[[UIBarButtonItem alloc] initWithTitle:BOXSTRING("Root") style:UIBarButtonItemStyleBordered target:self
|
||||
action:@selector(gotoRootDir)],
|
||||
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self
|
||||
action:nil],
|
||||
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self
|
||||
action:@selector(refresh)],
|
||||
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self
|
||||
action:@selector(createNewFolder)],
|
||||
nil
|
||||
];
|
||||
|
||||
self.toolbarItems = toolbarButtons;
|
||||
|
||||
[self.tableView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(fileAction:)]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)cancelBrowser
|
||||
{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)gotoParent
|
||||
{
|
||||
[self browseTo:[self.path stringByDeletingLastPathComponent]];
|
||||
}
|
||||
|
||||
- (void)gotoHomeDir
|
||||
{
|
||||
[self browseTo:NSHomeDirectory()];
|
||||
}
|
||||
|
||||
- (void)gotoAppDir
|
||||
{
|
||||
[self browseTo:NSBundle.mainBundle.bundlePath];
|
||||
}
|
||||
|
||||
- (void)gotoRootDir
|
||||
{
|
||||
[self browseTo:@"/"];
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
[self browseTo: self.path];
|
||||
}
|
||||
|
||||
- (void)browseTo:(NSString*)path
|
||||
{
|
||||
NSString *i;
|
||||
struct string_list *contents = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
self.path = path;
|
||||
self.title = path.lastPathComponent;
|
||||
|
||||
/* Need one array per section. */
|
||||
self.sections = [NSMutableArray array];
|
||||
|
||||
for (i in [self sectionIndexTitlesForTableView:self.tableView])
|
||||
[self.sections addObject:[NSMutableArray arrayWithObject:i]];
|
||||
|
||||
/* List contents */
|
||||
contents = dir_list_new(path.UTF8String,
|
||||
settings->menu.navigation.browser.filter.supported_extensions_enable ? self.extensions.UTF8String : NULL, true);
|
||||
|
||||
if (contents)
|
||||
{
|
||||
ssize_t i;
|
||||
RADirectoryList __weak* weakSelf = self;
|
||||
|
||||
if (self.allowBlank)
|
||||
[self.sections[0] addObject:[RAMenuItemBasic itemWithDescription:BOXSTRING("[ Use Empty Path ]")
|
||||
action:^{ weakSelf.chooseAction(weakSelf, nil); }]];
|
||||
if (self.forDirectory)
|
||||
[self.sections[0] addObject:[RAMenuItemBasic itemWithDescription:BOXSTRING("[ Use This Folder ]")
|
||||
action:^{ weakSelf.chooseAction(weakSelf, [RADirectoryItem directoryItemFromPath:path]); }]];
|
||||
dir_list_sort(contents, true);
|
||||
|
||||
for (i = 0; i < contents->size; i ++)
|
||||
{
|
||||
const char *basename = path_basename(contents->elems[i].data);
|
||||
char is_directory = (contents->elems[i].attr.i == RARCH_DIRECTORY);
|
||||
uint32_t section = is_directory ? 0 : isalpha(basename[0]) ? (toupper(basename[0]) - 'A') + 2 : 1;
|
||||
|
||||
if (! ( self.forDirectory && ! is_directory ))
|
||||
[self.sections[section] addObject:[RADirectoryItem directoryItemFromElement:&contents->elems[i]]];
|
||||
}
|
||||
|
||||
dir_list_free(contents);
|
||||
}
|
||||
else
|
||||
{
|
||||
[self gotoHomeDir];
|
||||
return;
|
||||
}
|
||||
|
||||
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
|
||||
[UIView transitionWithView:self.tableView duration:.25f options:UIViewAnimationOptionTransitionCrossDissolve
|
||||
animations:
|
||||
^{
|
||||
[self.tableView reloadData];
|
||||
} completion:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
[self browseTo: self.path];
|
||||
}
|
||||
|
||||
- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView
|
||||
{
|
||||
static NSArray* names = nil;
|
||||
|
||||
if (!names)
|
||||
names = @[@"/", @"#", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L",
|
||||
@"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z"];
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/* File management
|
||||
* Called as a selector from a toolbar button. */
|
||||
- (void)createNewFolder
|
||||
{
|
||||
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:BOXSTRING("Enter new folder name") message:BOXSTRING("") delegate:self
|
||||
cancelButtonTitle:BOXSTRING("Cancel") otherButtonTitles:BOXSTRING("OK"), nil];
|
||||
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
|
||||
alertView.tag = FA_CREATE;
|
||||
[alertView show];
|
||||
}
|
||||
|
||||
/* Called by the long press gesture recognizer. */
|
||||
- (void)fileAction:(UILongPressGestureRecognizer*)gesture
|
||||
{
|
||||
if (gesture.state == UIGestureRecognizerStateBegan)
|
||||
{
|
||||
CGPoint point = [gesture locationInView:self.tableView];
|
||||
NSIndexPath* idx_path = [self.tableView indexPathForRowAtPoint:point];
|
||||
|
||||
if (idx_path)
|
||||
{
|
||||
int major, minor;
|
||||
bool is_zip;
|
||||
UIActionSheet *menu;
|
||||
NSString *button4_name, *button5_name;
|
||||
|
||||
get_ios_version(&major, &minor);
|
||||
|
||||
button4_name = (major >= 7) ? BOXSTRING("AirDrop") : BOXSTRING("Delete");
|
||||
button5_name = (major >= 7) ? BOXSTRING("Delete") : nil;
|
||||
|
||||
self.selectedItem = [self itemForIndexPath:idx_path];
|
||||
is_zip = !(strcmp(self.selectedItem.path.pathExtension.UTF8String, "zip"));
|
||||
|
||||
menu = [[UIActionSheet alloc] initWithTitle:self.selectedItem.path.lastPathComponent delegate:self
|
||||
cancelButtonTitle:BOXSTRING("Cancel") destructiveButtonTitle:nil
|
||||
otherButtonTitles:is_zip ? BOXSTRING("Unzip") : BOXSTRING("Zip"), BOXSTRING("Move"), BOXSTRING("Rename"), button4_name, button5_name, nil];
|
||||
[menu showFromToolbar:self.navigationController.toolbar];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FILEBROWSER_ACTION_UNZIP 0x0e3f899bU
|
||||
#define FILEBROWSER_ACTION_MOVE 0x7c89307cU
|
||||
#define FILEBROWSER_ACTION_RENAME 0xce87affdU
|
||||
#define FILEBROWSER_ACTION_AIRDROP 0x8c6cdb56U
|
||||
#define FILEBROWSER_ACTION_DELETE 0xadde7058U
|
||||
#define FILEBROWSER_ACTION_CANCEL 0xab41f40bU
|
||||
|
||||
/* Called by the action sheet created in (void)fileAction: */
|
||||
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
uint32_t action_str_hash;
|
||||
int major, minor;
|
||||
NSString* target = self.selectedItem.path;
|
||||
NSString* action = [actionSheet buttonTitleAtIndex:buttonIndex];
|
||||
const char *action_str = action.UTF8String;
|
||||
|
||||
get_ios_version(&major, &minor);
|
||||
|
||||
action_str_hash = djb2_calculate(action_str);
|
||||
|
||||
(void)major;
|
||||
(void)minor;
|
||||
|
||||
switch (action_str_hash)
|
||||
{
|
||||
case FILEBROWSER_ACTION_UNZIP:
|
||||
{
|
||||
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:BOXSTRING("Enter target directory") message:@"" delegate:self
|
||||
cancelButtonTitle:BOXSTRING("Cancel") otherButtonTitles:BOXSTRING("OK"), nil];
|
||||
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
|
||||
alertView.tag = FA_UNZIP;
|
||||
[alertView textFieldAtIndex:0].text = [[target lastPathComponent] stringByDeletingPathExtension];
|
||||
[alertView show];
|
||||
}
|
||||
break;
|
||||
case FILEBROWSER_ACTION_MOVE:
|
||||
[self.navigationController pushViewController:[[RAFoldersList alloc] initWithFilePath:target] animated:YES];
|
||||
break;
|
||||
case FILEBROWSER_ACTION_RENAME:
|
||||
{
|
||||
UIAlertView* alertView = [[UIAlertView alloc]
|
||||
initWithTitle:BOXSTRING("Enter new name") message:@""
|
||||
delegate:self cancelButtonTitle:BOXSTRING("Cancel") otherButtonTitles:BOXSTRING("OK"), nil];
|
||||
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
|
||||
alertView.tag = FA_MOVE;
|
||||
[alertView textFieldAtIndex:0].text = target.lastPathComponent;
|
||||
[alertView show];
|
||||
}
|
||||
break;
|
||||
case FILEBROWSER_ACTION_AIRDROP:
|
||||
#ifdef __IPHONE_7_0
|
||||
if ((major >= 7))
|
||||
{
|
||||
/* TODO: ZIP if not already zipped. */
|
||||
NSURL *url = [NSURL fileURLWithPath:self.selectedItem.path isDirectory:self.selectedItem.isDirectory];
|
||||
NSArray *items = [NSArray arrayWithObject:url];
|
||||
UIActivityViewController* avc = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
|
||||
|
||||
[self presentViewController:avc animated:YES completion:nil];
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case FILEBROWSER_ACTION_DELETE:
|
||||
{
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:BOXSTRING("Really delete?") message:@"" delegate:self cancelButtonTitle:BOXSTRING("Cancel") otherButtonTitles:BOXSTRING("OK"), nil];
|
||||
alertView.tag = FA_DELETE;
|
||||
[alertView show];
|
||||
}
|
||||
break;
|
||||
case FILEBROWSER_ACTION_CANCEL:
|
||||
apple_display_alert("Action not supported.", "Action Failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called by various alert views created in this class,
|
||||
* the alertView.tag value is the action to take. */
|
||||
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
if (buttonIndex != alertView.firstOtherButtonIndex)
|
||||
return;
|
||||
|
||||
if (alertView.tag == FA_DELETE)
|
||||
file_action(FA_DELETE, nil, self.selectedItem.path);
|
||||
else
|
||||
{
|
||||
NSString* text = [alertView textFieldAtIndex:0].text;
|
||||
|
||||
if (text.length)
|
||||
file_action((enum file_action)alertView.tag, self.selectedItem.path, [self.path stringByAppendingPathComponent:text]);
|
||||
}
|
||||
|
||||
[self browseTo: self.path];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RAFoldersList()
|
||||
@property (nonatomic) NSString* path;
|
||||
@end
|
||||
|
||||
@implementation RAFoldersList
|
||||
|
||||
- (id)initWithFilePath:(NSString*)path
|
||||
{
|
||||
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
|
||||
{
|
||||
RAFoldersList* __weak weakSelf = self;
|
||||
NSString *sourceItem = path.stringByDeletingLastPathComponent; /* Parent item */
|
||||
RAMenuItemBasic *parentItem = [RAMenuItemBasic itemWithDescription:BOXSTRING("<Parent>") association:sourceItem.stringByDeletingLastPathComponent
|
||||
action:^(id userdata){ [weakSelf moveInto:userdata]; } detail:NULL];
|
||||
struct string_list *contents = dir_list_new([path stringByDeletingLastPathComponent].UTF8String, NULL, true);
|
||||
NSMutableArray *items = [NSMutableArray arrayWithObject:BOXSTRING("")];
|
||||
|
||||
[self.sections addObject:@[BOXSTRING(""), parentItem]];
|
||||
|
||||
self.path = path;
|
||||
|
||||
if (contents)
|
||||
{
|
||||
size_t i;
|
||||
dir_list_sort(contents, true);
|
||||
|
||||
for (i = 0; i < contents->size; i ++)
|
||||
{
|
||||
if (contents->elems[i].attr.i == RARCH_DIRECTORY)
|
||||
{
|
||||
const char* basename = path_basename(contents->elems[i].data);
|
||||
RAMenuItemBasic* item = [RAMenuItemBasic itemWithDescription:BOXSTRING(basename) association:BOXSTRING(contents->elems[i].data)
|
||||
action:^(id userdata){ [weakSelf moveInto:userdata]; } detail:NULL];
|
||||
[items addObject:item];
|
||||
}
|
||||
}
|
||||
dir_list_free(contents);
|
||||
}
|
||||
|
||||
[self setTitle:[BOXSTRING("Move ") stringByAppendingString: self.path.lastPathComponent]];
|
||||
[self.sections addObject:items];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)moveInto:(NSString*)path
|
||||
{
|
||||
NSString* targetPath = [path stringByAppendingPathComponent:self.path.lastPathComponent];
|
||||
file_action(FA_MOVE, self.path, targetPath);
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
@end
|
Loading…
x
Reference in New Issue
Block a user