GBA002/Delta/Pause Menu/Cheats/CheatsViewController.swift

311 lines
11 KiB
Swift

//
// CheatsViewController.swift
// Delta
//
// Created by Riley Testut on 5/20/16.
// Copyright © 2016 Riley Testut. All rights reserved.
//
import UIKit
import CoreData
import DeltaCore
import Roxas
protocol CheatsViewControllerDelegate: class
{
func cheatsViewControllerActiveEmulatorCore(saveStatesViewController: CheatsViewController) -> EmulatorCore
func cheatsViewController(cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
func cheatsViewController(cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat) throws
}
class CheatsViewController: UITableViewController
{
weak var delegate: CheatsViewControllerDelegate! {
didSet {
self.updateFetchedResultsController()
}
}
private var backgroundView: RSTBackgroundView!
private var fetchedResultsController: NSFetchedResultsController!
}
extension CheatsViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.title = NSLocalizedString("Cheats", comment: "")
self.backgroundView = RSTBackgroundView(frame: self.view.bounds)
self.backgroundView.hidden = false
self.backgroundView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.backgroundView.textLabel.text = NSLocalizedString("No Cheats", comment: "")
self.backgroundView.textLabel.textColor = UIColor.whiteColor()
self.backgroundView.detailTextLabel.text = NSLocalizedString("You can add a new cheat by pressing the + button in the top right.", comment: "")
self.backgroundView.detailTextLabel.textColor = UIColor.whiteColor()
self.tableView.backgroundView = self.backgroundView
self.registerForPreviewingWithDelegate(self, sourceView: self.tableView)
}
override func viewWillAppear(animated: Bool)
{
self.fetchedResultsController.performFetchIfNeeded()
self.updateBackgroundView()
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
//MARK: - Navigation -
private extension CheatsViewController
{
@IBAction func unwindFromEditCheatViewController(segue: UIStoryboardSegue)
{
}
}
//MARK: - Update -
private extension CheatsViewController
{
func updateFetchedResultsController()
{
let game = self.delegate.cheatsViewControllerActiveEmulatorCore(self).game as! Game
let fetchRequest = Cheat.fetchRequest()
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
self.fetchedResultsController.delegate = self
}
func updateBackgroundView()
{
if let fetchedObjects = self.fetchedResultsController.fetchedObjects where fetchedObjects.count > 0
{
self.tableView.separatorStyle = .SingleLine
self.backgroundView.hidden = true
}
else
{
self.tableView.separatorStyle = .None
self.backgroundView.hidden = false
}
}
}
//MARK: - Managing Cheats -
/// Managing Cheats
private extension CheatsViewController
{
@IBAction func addCheat()
{
let editCheatViewController = self.makeEditCheatViewController(cheat: nil)
self.presentViewController(RSTContainInNavigationController(editCheatViewController), animated: true, completion: nil)
}
func deleteCheat(cheat: Cheat)
{
let _ = try? self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlock {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID)
backgroundContext.deleteObject(temporaryCheat)
backgroundContext.saveWithErrorLogging()
}
}
}
//MARK: - Convenience -
/// Convenience
private extension CheatsViewController
{
func configure(cell cell: UITableViewCell, forIndexPath indexPath: NSIndexPath)
{
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
cell.textLabel?.text = cheat.name
cell.textLabel?.font = UIFont.boldSystemFontOfSize(cell.textLabel!.font.pointSize)
cell.accessoryType = cheat.enabled ? .Checkmark : .None
}
func makeEditCheatViewController(cheat cheat: Cheat?) -> EditCheatViewController
{
let editCheatViewController = self.storyboard!.instantiateViewControllerWithIdentifier("editCheatViewController") as! EditCheatViewController
editCheatViewController.delegate = self
editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).supportedCheatFormats
editCheatViewController.cheat = cheat
editCheatViewController.game = self.delegate.cheatsViewControllerActiveEmulatorCore(self).game as! Game
return editCheatViewController
}
}
extension CheatsViewController
{
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
let numberOfSections = self.fetchedResultsController.sections!.count
return numberOfSections
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let section = self.fetchedResultsController.sections![section]
return section.numberOfObjects
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier(RSTGenericCellIdentifier, forIndexPath: indexPath)
self.configure(cell: cell, forIndexPath: indexPath)
return cell
}
}
extension CheatsViewController
{
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
backgroundContext.performBlockAndWait {
let temporaryCheat = backgroundContext.objectWithID(cheat.objectID) as! Cheat
temporaryCheat.enabled = !temporaryCheat.enabled
do
{
if temporaryCheat.enabled
{
try self.delegate.cheatsViewController(self, didActivateCheat: temporaryCheat)
}
else
{
try self.delegate.cheatsViewController(self, didDeactivateCheat: temporaryCheat)
}
}
catch EmulatorCore.CheatError.invalid
{
print("Invalid cheat:", cheat.name, cheat.code)
}
catch EmulatorCore.CheatError.doesNotExist
{
print("Cheat does not exist:", cheat.name, cheat.code)
}
catch let error as NSError
{
print("Unknown Cheat Error:", error, cheat.name, cheat.code)
}
backgroundContext.saveWithErrorLogging()
}
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?
{
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
let deleteAction = UITableViewRowAction(style: .Destructive, title: NSLocalizedString("Delete", comment: "")) { (action, indexPath) in
self.deleteCheat(cheat)
}
let editAction = UITableViewRowAction(style: .Normal, title: NSLocalizedString("Edit", comment: "")) { (action, indexPath) in
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
self.presentViewController(RSTContainInNavigationController(editCheatViewController), animated: true, completion: nil)
}
return [deleteAction, editAction]
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
{
// This method intentionally left blank because someone decided it was a Good Idea to require this method be implemented to use UITableViewRowActions
}
}
//MARK: - <UIViewControllerPreviewingDelegate> -
extension CheatsViewController: UIViewControllerPreviewingDelegate
{
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
{
guard let indexPath = self.tableView.indexPathForRowAtPoint(location) else { return nil }
let frame = self.tableView.rectForRowAtIndexPath(indexPath)
previewingContext.sourceRect = frame
let cheat = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Cheat
let editCheatViewController = self.makeEditCheatViewController(cheat: cheat)
return editCheatViewController
}
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController)
{
self.presentViewController(RSTContainInNavigationController(viewControllerToCommit), animated: true, completion: nil)
}
}
//MARK: - <EditCheatViewControllerDelegate> -
extension CheatsViewController: EditCheatViewControllerDelegate
{
func editCheatViewController(editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
{
try self.delegate.cheatsViewController(self, didActivateCheat: cheat)
if let previousCheat = previousCheat
{
let code = cheat.code
previousCheat.managedObjectContext?.performBlockAndWait({
guard previousCheat.code != code else { return }
do
{
try self.delegate.cheatsViewController(self, didDeactivateCheat: previousCheat)
}
catch let error as NSError
{
print(error)
}
})
}
}
func editCheatViewController(editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
{
let _ = try? self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
}
}
//MARK: - <NSFetchedResultsControllerDelegate> -
extension CheatsViewController: NSFetchedResultsControllerDelegate
{
func controllerDidChangeContent(controller: NSFetchedResultsController)
{
self.tableView.reloadData()
self.updateBackgroundView()
}
}