Postgraduate Award in Technology Enhanced Learning ePortfolio

Appendix B: Code

SBTutorViewController.h


//
//  SBTutorViewController.h
//  SMART Board Tutor
//
//  Created by Steve on 10/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SBTutorViewController : UIViewController

@end
        

SBTutorViewController.m


//
//  SBTutorViewController.m
//  SMART Board Tutor
//
//  Created by Steve on 10/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "SBTutorViewController.h"
#import "KnowledgeTree.h"
#import "SBTutorExploreViewController.h"

@interface SBTutorViewController () <UIActionSheetDelegate>
@property (strong, nonatomic) KnowledgeTree *knowledgeTree;

@end

@implementation SBTutorViewController

#pragma mark getters

- (KnowledgeTree *)knowledgeTree {
    if (!_knowledgeTree) {
        _knowledgeTree = [[KnowledgeTree alloc] init];
    }
    return _knowledgeTree;
}

#pragma mark seques

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"menuToExplore" ] || [segue.identifier isEqualToString:@"menuToLearn"]) {
        if ([segue.destinationViewController isKindOfClass:[SBTutorKnowledgeTreeViewController class]]) {
            SBTutorKnowledgeTreeViewController *newViewController = (SBTutorKnowledgeTreeViewController *)segue.destinationViewController;
            newViewController.knowledgeTree = self.knowledgeTree;
        }
    }
}

#pragma mark delegate methods

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex == actionSheet.destructiveButtonIndex) {
        [self.knowledgeTree reset];
    }
}


#pragma mark button actions

- (IBAction)requestModelReset:(UIButton*)resetButton {
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure that you want to reset everything?"
                                                             delegate:self
                                                    cancelButtonTitle:nil
                                               destructiveButtonTitle:@"Reset everything"
                                                    otherButtonTitles:nil];
    [actionSheet showFromRect:resetButton.frame inView:self.view animated:YES];
}

@end
        

SBTutorKnowledgeTreeViewController.h


//
//  SBTutorKnowledgeTreeViewController.h
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "KnowledgeTree.h"

@interface SBTutorKnowledgeTreeViewController : UIViewController

@property (strong, nonatomic) KnowledgeTree *knowledgeTree;

@end
        

SBTutorKnowledgeTreeViewController.m


//
//  SBTutorKnowledgeTreeViewController.m
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "SBTutorKnowledgeTreeViewController.h"

@interface SBTutorKnowledgeTreeViewController ()

@end

@implementation SBTutorKnowledgeTreeViewController

#pragma mark getters

- (KnowledgeTree *)knowledgeTree {
    if (!_knowledgeTree) {
        _knowledgeTree = [[KnowledgeTree alloc] init];
    }
    return _knowledgeTree;
}

@end
        

SBTutorExploreViewController.h


//
//  SBTutorExploreViewController.h
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SBTutorKnowledgeTreeViewController.h"

@interface SBTutorExploreViewController : SBTutorKnowledgeTreeViewController <UITableViewDelegate, UITableViewDataSource>

@end
        

SBTutorExploreViewController.m


//
//  SBTutorExploreViewController.m
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "SBTutorExploreViewController.h"
#import "VideoView.h"

@interface SBTutorExploreViewController ()
@property (weak, nonatomic) IBOutlet UILabel *nodeTitle;
@property (weak, nonatomic) IBOutlet VideoView *nodeVideo;
@property (weak, nonatomic) IBOutlet UIWebView *nodeContent;
@property (strong, nonatomic) UITableViewController *dependantsPopoverViewController;
@property (strong, nonatomic) UITableViewController *prerequisitesPopoverViewController;
@property (strong, nonatomic) UIPopoverController *dependantsPopoverController;
@property (strong, nonatomic) UIPopoverController *prerequisitesPopoverController;

@end

@implementation SBTutorExploreViewController

# pragma mark UITableView Delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (tableView == self.prerequisitesPopoverViewController.tableView) {
        // Need to display pre-requisite node
        self.knowledgeTree.currentNode = self.knowledgeTree.currentNode.prerequisites[indexPath.row];
    } else if (tableView == self.dependantsPopoverViewController.tableView) {
        // Need to display dependant node
        self.knowledgeTree.currentNode = self.knowledgeTree.currentNode.dependants[indexPath.row];
    }
}

# pragma mark UITableView DataSource

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Related Node" forIndexPath:indexPath];
    if (tableView == self.prerequisitesPopoverViewController.tableView) {
        // Need to fill cell with pre-requisite node
        cell.textLabel.text = self.knowledgeTree.currentNode.prerequisites[indexPath.row];
    } else if (tableView == self.dependantsPopoverViewController.tableView) {
        // Need to fill cell with dependant node
        cell.textLabel.text = self.knowledgeTree.currentNode.dependants[indexPath.row];
    }
    return cell;
}

- (NSInteger)numberOfPrerequisites {
    return [self.knowledgeTree.currentNode.prerequisites count];
}

- (NSInteger)numberOfDependants {
    return [self.knowledgeTree.currentNode.dependants count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSInteger numberOfRowsInSection = 0;
    if (tableView == self.prerequisitesPopoverViewController.tableView) {
        // Need number of pre-requisite nodes
        numberOfRowsInSection = [self numberOfPrerequisites];
    } else if (tableView == self.dependantsPopoverViewController.tableView) {
        // Need number of dependant nodes
        numberOfRowsInSection = [self numberOfDependants];
    }
    return numberOfRowsInSection;
}

# pragma mark Property instantiations

- (UITableViewController *)prerequisitesPopoverViewController {
    if (!_prerequisitesPopoverViewController) {
        _prerequisitesPopoverViewController = [[UITableViewController alloc] init];
        _prerequisitesPopoverViewController.tableView.delegate = self;
        _prerequisitesPopoverViewController.tableView.dataSource = self;
    }
    return _prerequisitesPopoverViewController;
}

- (UITableViewController *)dependantsPopoverViewController {
    if (!_dependantsPopoverViewController) {
        _dependantsPopoverViewController = [[UITableViewController alloc] init];
        _dependantsPopoverViewController.tableView.delegate = self;
        _dependantsPopoverViewController.tableView.dataSource = self;
    }
    return  _dependantsPopoverViewController;
}

- (UIPopoverController *)prerequisitesPopoverController {
    if (!_prerequisitesPopoverController) {
        _prerequisitesPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.prerequisitesPopoverViewController];
    }
    return _prerequisitesPopoverController;
}

- (UIPopoverController *)dependantsPopoverController {
    if (!_dependantsPopoverController) {
        _dependantsPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.dependantsPopoverViewController];
    }
    return _dependantsPopoverController;
}



# pragma mark IBActions

- (IBAction)displayPrerequisites:(UIButton *)sender {
    [self.prerequisitesPopoverController presentPopoverFromRect:sender.frame
                                                         inView:self.view
                                       permittedArrowDirections:UIPopoverArrowDirectionAny
                                                       animated:YES];
}

- (IBAction)displayDependants:(UIButton *)sender {
    [self.dependantsPopoverController presentPopoverFromRect:sender.frame
                                                      inView:self.view
                                    permittedArrowDirections:UIPopoverArrowDirectionAny
                                                    animated:YES];
}


# pragma mark Controller Lifecycle

- (void)viewWillAppear:(BOOL)animated {
    Node *currentNode = self.knowledgeTree.currentNode;
    if (currentNode) {
        self.nodeTitle.text = currentNode.title;
        [self.nodeVideo setVideoSourceTo:currentNode.video];
        [self.nodeContent loadHTMLString:currentNode.htmlContent baseURL:[[NSURL alloc] init]];
    }
}

@end
        

SBTutorLearnViewController.h


//
//  SBTutorLearnViewController.h
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SBTutorKnowledgeTreeViewController.h"

@interface SBTutorLearnViewController : SBTutorKnowledgeTreeViewController

@end
        

SBTutorLearnViewController.m


//
//  SBTutorLearnViewController.m
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "SBTutorLearnViewController.h"

@interface SBTutorLearnViewController ()

@end

@implementation SBTutorLearnViewController

@end
        

SBTutorQuestionnaireViewController.h


//
//  SBTutorQuestionnaireViewController.h
//  SMART Board Tutor
//
//  Created by Steve on 26/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SBTutorQuestionnaireViewController : UITableViewController

@end
        

SBTutorQuestionnaireViewController.m


//
//  SBTutorQuestionnaireViewController.m
//  SMART Board Tutor
//
//  Created by Steve on 26/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "SBTutorQuestionnaireViewController.h"

@interface SBTutorQuestionnaireViewController ()
@property (weak, nonatomic) IBOutlet UISlider *questionOneSlider;
@property (weak, nonatomic) IBOutlet UISlider *questionTwoSlider;
@property (weak, nonatomic) IBOutlet UISlider *questionThreeSlider;

@end

@implementation SBTutorQuestionnaireViewController

- (void)setSliderToNearestWholeValue:(UISlider *)slider {
    NSNumber *currentFloatValue = [NSNumber numberWithFloat:slider.value];
    [slider setValue:[currentFloatValue integerValue] animated:YES];
}

- (IBAction)questionOneSliderValueChanged:(UISlider *)sender {
    [self setSliderToNearestWholeValue:sender];
}

- (IBAction)questionTwoSliderValueChanged:(UISlider *)sender {
    [self setSliderToNearestWholeValue:sender];
}

- (IBAction)questionThreeSliderValueChanged:(UISlider *)sender {
    [self setSliderToNearestWholeValue:sender];
}


@end
        

KnowledgeTree.h


//
//  KnowledgeTree.h
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Node.h"

@interface KnowledgeTree : NSObject

@property (strong, nonatomic) Node *currentNode;

- (void)reset;

@end
        

KnowledgeTree.m


//
//  KnowledgeTree.m
//  SMART Board Tutor
//
//  Created by Steve on 13/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "KnowledgeTree.h"

@implementation KnowledgeTree
#pragma mark Property instantiators

#pragma mark Public methods

- (void)reset {
    
}

@end
        

Node.h


//
//  Node.h
//  SMART Board Tutor
//
//  Created by Steve on 14/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Node : NSObject

@property (strong, nonatomic, readonly) NSString *title;
@property (strong, nonatomic, readonly) NSURL *video;
@property (strong, nonatomic, readonly) NSString *htmlContent;
@property (strong, nonatomic, readonly) NSArray *prerequisites; // of Nodes
@property (strong, nonatomic, readonly) NSArray *dependants; // of Nodes

@end
        

Node.m


//
//  Node.m
//  SMART Board Tutor
//
//  Created by Steve on 14/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "Node.h"

@interface Node ()

@property (strong, nonatomic, readwrite) NSString *title;
@property (strong, nonatomic, readwrite) NSURL *video;
@property (strong, nonatomic, readwrite) NSString *htmlContent;
@property (strong, nonatomic, readwrite) NSArray *prerequisites; // of Nodes
@property (strong, nonatomic, readwrite) NSArray *dependants; // of Nodes

@end

@implementation Node

#pragma mark Propert instantiators

- (NSArray *)dependants {
    if (!_dependants) {
        _dependants = [[NSArray alloc] init];
    }
    return _dependants;
}

- (NSArray *)prerequisites {
    if (!_prerequisites) {
        _prerequisites = [[NSArray alloc] init];
    }
    return _prerequisites;
}

- (NSString*)htmlContent {
    if (!_htmlContent) {
        _htmlContent = @"";
    }
    return _htmlContent;
}

- (NSURL*)video {
    if (!_video) {
        _video = [[NSURL alloc] init];
    }
    return _video;
}

- (NSString*)title {
    if (!_title) {
        _title = @"";
    }
    return _title;
}

@end
        

RelatedNodesTVC.h


//
// RelatedNodesTVC.h
// SMART Board Tutor
//
// Created by Steve on 17/04/2014.
// Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "Node.h"

@protocol KnowledgeTreeDisplay

@property (strong, nonatomic) Node *currentNode;

@end

@interface RelatedNodesTVC : UITableViewController <UITableViewDelegate>

@property (nonatomic, strong) NSArray *relatedNodes; // of Nodes
@property (strong, nonatomic) id <KnowledgeTreeDisplay, UIPopoverControllerDelegate> delegate; // Who will be notified when a cell is selected?

@end
        

RelatedNodesTVC.m


//
// RelatedNodesTVC.m
// SMART Board Tutor
//
// Created by Steve on 17/04/2014.
// Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "RelatedNodesTVC.h"
#import "SBTutorExploreViewController.h"

@interface RelatedNodesTVC ()

@end

@implementation RelatedNodesTVC

#pragma mark Table View delegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.delegate.currentNode = self.relatedNodes[indexPath.row];
}

#pragma mark Public methods

-(void)setRelatedNodes:(NSArray *)relatedNodes {
_relatedNodes = relatedNodes;
[self.tableView reloadData];
}

#pragma mark Default methods

- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
self.tableView.delegate = self;
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.relatedNodes count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Related Node" forIndexPath:indexPath];

if ([self.relatedNodes[indexPath.row] isKindOfClass:[Node class]]) {
Node *node = (Node*)self.relatedNodes[indexPath.row];
cell.textLabel.text = node.title;
}

return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

@end
        

VideoView.h


//
//  VideoView.h
//  SMART Board Tutor
//
//  Created by Steve on 14/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface VideoView : UIView

- (void)setVideoSourceTo:(NSURL*)url;

@end
        

VideoView.m


//
//  VideoView.m
//  SMART Board Tutor
//
//  Created by Steve on 14/02/2014.
//  Copyright (c) 2014 Steve Locke-Wheaton. All rights reserved.
//

#import "VideoView.h"
#import <MediaPlayer/MediaPlayer.h>

@interface VideoView ()

@property (strong, nonatomic) NSURL *videoSource;

@end

@implementation VideoView

#pragma mark Getters

- (NSURL*)videoSource {
    if (!_videoSource) {
        _videoSource = [[NSURL alloc] init];
    }
    return _videoSource;
}

#pragma mark Private methods

- (void)playVideo {
    MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:self.videoSource];
    player.view.frame = self.frame;
    [self addSubview:player.view];
    [player play];
}

#pragma mark Public methods

- (void)setVideoSourceTo:(NSURL *)url {
    self.videoSource = url;
    [self playVideo];
}

#pragma mark Template code

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end