Skip to content

Instantly share code, notes, and snippets.

@eliotfowler
Created May 14, 2016 15:00
Show Gist options
  • Save eliotfowler/ad640a61b7004247a023ef8aee6d9252 to your computer and use it in GitHub Desktop.
Save eliotfowler/ad640a61b7004247a023ef8aee6d9252 to your computer and use it in GitHub Desktop.
Interface for a crossword puzzle
//
// Grid.h
// Crossword
//
// Created by Eliot Fowler on 10/9/14.
// Copyright (c) 2014 Eliot Fowler. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "GridSize.h"
#import "CrosswordPuzzle.h"
/**
* Selected Direction indicates the current direction of the selected word
* on the grid
*/
typedef enum : NSUInteger {
Horizontal = 1,
Vertical = 2,
} SelectedDirection;
@class Grid;
@class UserLetter;
/**
* The `GridDataSource` protocol defines both required and optional methods
* that allow for on the fly grid customizations.
*
* Required methods in the GridDataSource request information that is
* necessary for the grid to draw itself.
*/
@protocol GridDataSource <NSObject>
@required
/**
* This method is called in almost every drawing method and is used to calculate
* the size of each individual square.
*
* @param grid The grid object requesting the number of rows
*
* @return The number of rows
*
* @warning Currently, the grid expects the number of rows to equal the number of columns
*/
- (NSInteger)numberOfRowsInGrid:(Grid *)grid;
/**
* This method is called in almost every drawing method and is used to calculate
* the size of each individual square.
*
* @param grid The grid object requesting the number of columns
*
* @return The number of columns
*
* @warning Currently, the grid expects the number of rows to equal the number of columns
*/
- (NSInteger)numberOfColumnsInGrid:(Grid *)grid;
/**
* This method is used to define the structure of the grid.
*
* This method is often called when looping through each square on the grid. Conformants
* of this protocol typically use an NSArray of size rows * squares and simply return
* the object at the specified index.
*
* @param grid The grid object request the layout symbol
* @param index The index of the current square. For example: in a 15x15 grid, the square
* in the second row, first column would be at index 15.
*
* @returns The layout symbol at the specified index. The correct letter if the current
* index is a white square, a "." if the current index is a black square.
*/
- (NSString *)gridLayoutSymbolForGrid:(Grid *)grid atIndex:(NSInteger)index;
/**
* This method is used to define the locations of the numbers in the grid.
*
* @param grid The grid object requesting the grid number
* @param index The index of the current square. For example: in a 15x15 grid, the square
* in the second row, first column would be at index 15.
*
* @returns The number that should be drawn in the square at the specified index. If no
* number should be drawn, a @0 should be returned.
*
* @warning This could be calculated algorithmically. Currently, it is required to be
* explicit to allow for greater customization
*/
- (NSNumber *)gridNumberForGrid:(Grid *)grid atIndex:(NSInteger)index;
/**
* This method is used to determine if the grid is empty.
*
* @returns Whether the user has entered any letters
*/
- (BOOL)hasText;
@optional
/**
* This method is used to determine if the user has entered a letter at the specified index.
*
* @param grid The grid object requesting the letter
*
* @returns The letter that the user entered if one exists, otherwise nil or @"".
*/
- (UserLetter *)userEnteredLetterForGrid:(Grid *)grid atIndex:(NSInteger)index;
@end
/**
* The `GridDelegate` protocol defines optional methods that the grid uses to update
* interested parties in state changes.
*
* GridDelegate methods typically err on the side of over-firing in an effort to
* ensure interested parties are aware of all changes. For example, if you explicitly call
* `-setSelectedIndex`, the `-selectedIndexChangedToIndex` delegate method will still
* get called.
*
*/
@protocol GridDelegate <NSObject>
@optional
/**
* Called when the selected index changes for any reason.
*
* @param index The index of the new selected index
*
* @note This method will get called regardless of the reason that the index changed. Even
* if you explicitly change the index, this method still gets called.
*/
- (void)selectedIndexChangedToIndex:(NSInteger)index;
/**
* Called when the selected direction changes for any reason.
*
* @param selectedDirection The new selected direction
*
* @note This method will get called regardless of the reason that the direction changed. Even
* if you explicitly change the direction, this method still gets called.
*/
- (void)selectedDirectionChangedToDirection:(SelectedDirection)selectedDirection;
/**
* Since `Grid` conforms to the UIKeyInput protocol, this delegate provides this method to
* inform interested parties that the user wants to add the specified text in the square at
* the specified index.
*
* @note This method specifies that the user entered the text at the specified index. It does
* not, however, mean that the text has been captured. Typical implementations of this method
* add the text to the backing store for the `-userEnteredLetterForGrid:atIndex:` data source
* method.
*
* @param text The text entered. This is typically a single character
* @param index The index that was selected when the text was entered
*/
- (void)text:(NSString *)text enteredAtIndex:(NSInteger)index;
/**
* Since `Grid` conforms to the UIKeyInput protocol, this delegate provides this method to
* inform interested parties that the user wants to delete the specified text from the square
* at the specified index.
*
* @note This method specifies that the user deleted the text at the specified index. It does
* not, however, mean that the text has been captured. Typical implementations of this method
* remove the text from the backing store for the `-userEnteredLetterForGrid:atIndex:` data
* source method.
*
* @param text The text deleted. This is typically a single character
* @param index The index that was selected when the text was deleted
*/
- (void)text:(NSString *)text deletedAtIndex:(NSInteger)index;
@end
IB_DESIGNABLE
/**
* The `Grid` class defines a heavily customizable, Crossword-style grid.
*/
@interface Grid : UIView <UIKeyInput, GridDataSource>
/**
* The color of the currently selected word, in the selected direction.
*/
@property (nonatomic, strong) IBInspectable UIColor *selectedWord;
/**
* The color of the selected letter that is contained within the selected word.
*/
@property (nonatomic, strong) IBInspectable UIColor *selectedLetter;
/**
* The color of the word in the opposite direction at the selected index.
*/
@property (nonatomic, strong) IBInspectable UIColor *oppositeDirWord;
/**
* The color of the grid lines within the grid.
*/
@property (nonatomic, strong) IBInspectable UIColor *gridLine;
/**
* The color of the boxes that can have text in them. On a traditional crossword puzzle,
* this is white
*/
@property (nonatomic, strong) IBInspectable UIColor *unfilledBox;
/**
* The color of the boxes that can not have text in them. On a traditional crossword puzzle,
* this is black.
*/
@property (nonatomic, strong) IBInspectable UIColor *filledBox;
/**
* The color of the slash that is shown when a user checks a square with an incorrect letter
* in it
*/
@property (nonatomic, strong) IBInspectable UIColor *incorrectSlash;
/**
* The color of the slash that is shown when a user checks a square with an incorrect letter
* in it
*/
@property (nonatomic, strong) IBInspectable UIFont *letterFont;
/**
* The width of the border.
*/
@property (nonatomic, assign) IBInspectable CGFloat borderWidth;
/**
* The width (or height) of the square.
*/
@property (nonatomic, assign, readonly) CGFloat squareSize;
/**
* The font size of the letters in the square.
*/
@property (nonatomic, assign, readonly) CGFloat fontSize;
@property (nonatomic, weak) IBOutlet id<GridDelegate> delegate;
@property (nonatomic, weak) IBOutlet id<GridDataSource> dataSource;
/**
* The currently selected index on the grid.
*
* @note This defaults to the first non-filled square on the grid
*/
@property (nonatomic, assign) NSInteger selectedIndex;
/**
* The indexes that make up the word that contains the currently selected index
*/
@property (nonatomic, strong) NSArray *selectedIndexes;
/**
* The currently selected direction on the grid.
*
* @note This defaults to horizontal
*/
@property (nonatomic, assign) SelectedDirection selectedDirection;
/**
* Whether or not to draw letters.
*
* @note This includes user letters, checked letters, and revealed letters.
*/
@property (nonatomic, assign) BOOL showLettersAndNumbers;
/**
* The current clue number
*
* @return The number of the clue that the selected index is in.
*/
- (NSInteger)currentClueNumber;
/**
* Find all indexes that are in the word that contains the selected index, in the
* selected direction
*
* @param selectedIndex The selected index that defines the word
* @param direction The direction that defines the word
*
* @return A sorted list of the indexes that would be selected if the `selectedIndex` was selected
* and the `selectedDirection` was selected
*/
- (NSArray *)selectedIndexesForSelectedIndex:(NSInteger)selectedIndex direction:(SelectedDirection)direction;
/**
* Check whether all squares at the specified indexes have letters in them
*
* @param indexes The indexes of the squares to check
*
* @return YES if all squares have letters in them, NO otherwise
*/
- (BOOL)allLettersFilledAtIndexes:(NSArray *)indexes;
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment