Skip to content

Commit

Permalink
Fix #3 slowly bug and add image rotate
Browse files Browse the repository at this point in the history
  • Loading branch information
MakeHui committed May 21, 2019
1 parent 2610e8c commit 7fbb133
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 368 deletions.
15 changes: 15 additions & 0 deletions MHWhiteboard.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@
objects = {

/* Begin PBXBuildFile section */
7C61FE7B2293A8CC00B0F69A /* MHDrawView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C61FE792293A8CC00B0F69A /* MHDrawView.h */; };
7C61FE7C2293A8CC00B0F69A /* MHDrawView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C61FE7A2293A8CC00B0F69A /* MHDrawView.m */; };
7C61FE832293AA4F00B0F69A /* MHPathModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C61FE822293AA4E00B0F69A /* MHPathModel.m */; };
7CA0ECD022375A88005A6914 /* MHWhiteboard.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 7CA0ECCF22375A88005A6914 /* MHWhiteboard.bundle */; };
7CF4C76821E7366B00890AA5 /* MHWhiteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF4C76621E7366B00890AA5 /* MHWhiteboard.h */; settings = {ATTRIBUTES = (Public, ); }; };
7CF4C77021E736A000890AA5 /* MHWhiteboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CF4C76E21E736A000890AA5 /* MHWhiteboardView.m */; };
7CF4C77121E736A000890AA5 /* MHWhiteboardView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF4C76F21E736A000890AA5 /* MHWhiteboardView.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
7C61FE792293A8CC00B0F69A /* MHDrawView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHDrawView.h; sourceTree = "<group>"; };
7C61FE7A2293A8CC00B0F69A /* MHDrawView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHDrawView.m; sourceTree = "<group>"; };
7C61FE812293AA4E00B0F69A /* MHPathModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHPathModel.h; sourceTree = "<group>"; };
7C61FE822293AA4E00B0F69A /* MHPathModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHPathModel.m; sourceTree = "<group>"; };
7CA0ECCF22375A88005A6914 /* MHWhiteboard.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MHWhiteboard.bundle; sourceTree = "<group>"; };
7CF4C76321E7366B00890AA5 /* MHWhiteboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MHWhiteboard.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7CF4C76621E7366B00890AA5 /* MHWhiteboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHWhiteboard.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -53,6 +60,10 @@
isa = PBXGroup;
children = (
7CA0ECCF22375A88005A6914 /* MHWhiteboard.bundle */,
7C61FE812293AA4E00B0F69A /* MHPathModel.h */,
7C61FE822293AA4E00B0F69A /* MHPathModel.m */,
7C61FE792293A8CC00B0F69A /* MHDrawView.h */,
7C61FE7A2293A8CC00B0F69A /* MHDrawView.m */,
7CF4C76F21E736A000890AA5 /* MHWhiteboardView.h */,
7CF4C76E21E736A000890AA5 /* MHWhiteboardView.m */,
7CF4C76621E7366B00890AA5 /* MHWhiteboard.h */,
Expand All @@ -70,6 +81,7 @@
files = (
7CF4C77121E736A000890AA5 /* MHWhiteboardView.h in Headers */,
7CF4C76821E7366B00890AA5 /* MHWhiteboard.h in Headers */,
7C61FE7B2293A8CC00B0F69A /* MHDrawView.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -114,6 +126,7 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 7CF4C75921E7366B00890AA5;
productRefGroup = 7CF4C76421E7366B00890AA5 /* Products */;
Expand Down Expand Up @@ -142,6 +155,8 @@
buildActionMask = 2147483647;
files = (
7CF4C77021E736A000890AA5 /* MHWhiteboardView.m in Sources */,
7C61FE7C2293A8CC00B0F69A /* MHDrawView.m in Sources */,
7C61FE832293AA4F00B0F69A /* MHPathModel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
29 changes: 29 additions & 0 deletions MHWhiteboard/MHDrawView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// MHDrawView.h
// MHWhiteboard
//
// Created by MakeHui on 21/5/2019.
// Copyright © 2019 MakeHui. All rights reserved.
//

#import "MHWhiteboardView.h"

NS_ASSUME_NONNULL_BEGIN

@interface MHDrawView : UIView

@property(assign, nonatomic)MHPathModelAction pathModelAction;
@property(assign, nonatomic)CGFloat brushWidth;
@property(strong, nonatomic)UIColor *brushColor;

@property(assign, nonatomic)NSUInteger polygonSides;

@property(strong, nonatomic)UIFont *textFont;

- (void)undo;
- (void)repeat;
- (void)clearAll;

@end

NS_ASSUME_NONNULL_END
225 changes: 225 additions & 0 deletions MHWhiteboard/MHDrawView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
//
// MHDrawView.m
// MHWhiteboard
//
// Created by MakeHui on 21/5/2019.
// Copyright © 2019 MakeHui. All rights reserved.
//

#import "MHDrawView.h"
#import "MHPathModel.h"

#define MHGetImage(imageName) [UIImage imageNamed:[@"Frameworks/MHWhiteboard.framework/MHWhiteboard.bundle" stringByAppendingPathComponent:imageName]]

@interface MHDrawView ()<UITextFieldDelegate>

@end

@implementation MHDrawView
{
UITextField *_textField;
UIImageView *_selectedImageView;

CGMutablePathRef _currentPath;
NSMutableArray<MHPathModel *> *_pathModelArray;
}

- (instancetype)init
{
self = [super init];
if (self) {
[self customInit];
}
return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self customInit];
}
return self;
}

- (void)customInit
{
self.backgroundColor = [UIColor whiteColor];
self.pathModelAction = MHPathModelActionLine;
self.brushWidth = 5.0f;
self.brushColor = [UIColor redColor];
self.polygonSides = 6;
self.textFont = [UIFont systemFontOfSize:24];

_pathModelArray = [NSMutableArray array];
}

- (void)addPathModelToArray:(MHPathModel *)pathModel
{
for (int i = 0; i < _pathModelArray.count; ++i) {
if (_pathModelArray[i].action & MHPathModelActionUndo) {
[_pathModelArray removeObject:_pathModelArray[i]];
}
}
[_pathModelArray addObject:pathModel];
}

#pragma mark - Draw UI

- (void)drawRect:(CGRect)rect
{
for(MHPathModel *pathModel in _pathModelArray) {
if (pathModel.action & MHPathModelActionUndo) continue;

if (pathModel.action & MHPathModelActionText) {
NSDictionary *attributes = @{NSForegroundColorAttributeName: pathModel.color, NSFontAttributeName: pathModel.font};
NSAttributedString *text=[[NSAttributedString alloc] initWithString:pathModel.text attributes:attributes];
NSArray<NSValue *> *pathPoints = [MHPathModel pathPointsWithCGPath:pathModel.path.CGPath];
CGPoint point = pathPoints.firstObject.CGPointValue;

[text drawAtPoint:point];
}
else {
[pathModel.color set];
[pathModel.path stroke];
}
}

if (_currentPath) {
if (self.pathModelAction & MHPathModelActionText) { return; }

MHPathModel *pathModel = [MHPathModel pathModelWithAction:self.pathModelAction path:_currentPath lineWidth:self.brushWidth color:self.brushColor sides:self.polygonSides];

[pathModel.color set];
[pathModel.path stroke];
}
}

#pragma mark - Touches Event

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
CGPoint location = [touches.anyObject locationInView:self];

_currentPath = CGPathCreateMutable();

CGPathMoveToPoint(_currentPath, NULL, location.x, location.y);

if (self.pathModelAction & MHPathModelActionText) {
if (_textField) { [_textField removeFromSuperview]; }

static const CGFloat rightMargin = 8.0f;
static const CGFloat topMargin = 4.0f;
static const CGFloat bottomMargin = 4.0f;
static const CGFloat innerMargin = 7.0f;

CGSize textSize = [[NSAttributedString alloc] initWithString:@"文字/words" attributes: @{NSFontAttributeName: self.textFont}].size;
_textField = [[UITextField alloc] initWithFrame:CGRectMake(location.x - innerMargin, location.y - topMargin, self.frame.size.width - location.x - rightMargin, textSize.height + topMargin + bottomMargin)];
_textField.borderStyle = UITextBorderStyleRoundedRect;
_textField.delegate = self;
_textField.font = self.textFont;
[_textField becomeFirstResponder];

[self addSubview:_textField];
}
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (self.pathModelAction & MHPathModelActionText) { return; }

CGPoint location = [touches.anyObject locationInView:self];

if (self.pathModelAction & MHPathModelActionStraightLine ||
self.pathModelAction & MHPathModelActionCircle ||
self.pathModelAction & MHPathModelActionRectangle ||
self.pathModelAction & MHPathModelActionPolygon) {
CGPoint firstPoint = [[MHPathModel pathPointsWithCGPath:_currentPath] firstObject].CGPointValue;
CGPathRelease(_currentPath);
_currentPath = CGPathCreateMutable();
CGPathMoveToPoint(_currentPath, NULL, firstPoint.x, firstPoint.y);
}

CGPathAddLineToPoint(_currentPath, NULL, location.x, location.y);

[self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (self.pathModelAction & MHPathModelActionText) { return; }

MHPathModel *pathModel = [MHPathModel pathModelWithAction:self.pathModelAction path:_currentPath lineWidth:self.brushWidth color:self.brushColor sides:self.polygonSides];
[self addPathModelToArray:pathModel];

CGPathRelease(_currentPath);
_currentPath = nil;

[self setNeedsDisplay];
}

#pragma mark - UITextFieldDelegate

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];

if (textField.text.length) {
MHPathModel *pathModel = [MHPathModel pathModelWithAction:self.pathModelAction path:_currentPath text:textField.text color:self.brushColor font:self.textFont];
[self addPathModelToArray:pathModel];
}

CGPathRelease(_currentPath);
_currentPath = nil;

[textField removeFromSuperview];
[self setNeedsDisplay];

return true;
}

#pragma mark - Function

- (void)undo
{
for (MHPathModel *pathModel in [_pathModelArray reverseObjectEnumerator]) {
if (! (pathModel.action & MHPathModelActionUndo)) {
pathModel.action |= MHPathModelActionUndo;
break;
}
}

[self setNeedsDisplay];
}

- (void)repeat
{
for (MHPathModel *pathModel in _pathModelArray) {
if (pathModel.action & MHPathModelActionUndo) {
pathModel.action ^= MHPathModelActionUndo;
break;
}
}

[self setNeedsDisplay];
}

- (void)clearAll
{
for (MHPathModel *pathModel in _pathModelArray) {
pathModel.action |= MHPathModelActionUndo;
}

[self setNeedsDisplay];
}

@end
32 changes: 32 additions & 0 deletions MHWhiteboard/MHPathModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// MHPathModel.h
// MHWhiteboard
//
// Created by MakeHui on 21/5/2019.
// Copyright © 2019 MakeHui. All rights reserved.
//

#import "MHWhiteboardView.h"

NS_ASSUME_NONNULL_BEGIN

@interface MHPathModel : NSObject

+ (instancetype)pathModelWithAction:(MHPathModelAction)action path:(CGPathRef)path lineWidth:(CGFloat)lineWidth color:(UIColor *)color;

+ (instancetype)pathModelWithAction:(MHPathModelAction)action path:(CGPathRef)path lineWidth:(CGFloat)lineWidth color:(UIColor *)color sides:(NSUInteger)sides;

+ (instancetype)pathModelWithAction:(MHPathModelAction)action path:(CGPathRef)path text:(NSString *)text color:(UIColor *)color font:(UIFont *)font;

+ (NSArray<NSValue *> *)pathPointsWithCGPath:(CGPathRef)path;

@property(assign, nonatomic)MHPathModelAction action;
@property(strong, nonatomic)UIBezierPath *path;
@property(strong, nonatomic)UIColor *color;

@property(strong, nonatomic)NSString *text;
@property(strong, nonatomic)UIFont *font;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 7fbb133

Please sign in to comment.