Files
leanote-ios/Leanote/editor/EditorClasses/WPEditorToolbarView.m
2015-08-21 23:49:41 +08:00

571 lines
21 KiB
Objective-C
Executable File

#import "WPEditorToolbarView.h"
#import "WPDeviceIdentification.h"
#import "WPEditorToolbarButton.h"
#import "ZSSBarButtonItem.h"
// life
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "DDLog.h"
#import "WPEditorLoggingConfiguration.h"
#ifndef IS_IPAD
#define IS_IPAD ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
#endif
#ifndef IS_IPHONE
#define IS_IPHONE (!IS_IPAD)
#endif
#ifndef IS_RETINA
#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2)
#endif
#endif
// life -end
static int kDefaultToolbarItemPadding = 10;
static int kDefaultToolbarLeftPadding = 10;
static int kNegativeToolbarItemPadding = 12;
static int kNegativeSixToolbarItemPadding = 6;
static int kNegativeSixPlusToolbarItemPadding = 2;
static int kNegativeLeftToolbarLeftPadding = 3;
static int kNegativeRightToolbarPadding = 20;
static int kNegativeSixPlusRightToolbarPadding = 24;
static const CGFloat WPEditorToolbarHeight = 40;
static const CGFloat WPEditorToolbarButtonHeight = 40;
static const CGFloat WPEditorToolbarButtonWidth = 40;
static const CGFloat WPEditorToolbarRightButtonWidth = 50;
static const CGFloat WPEditorToolbarDividerLineHeight = 28;
static const CGFloat WPEditorToolbarDividerLineWidth = 0.6f;
@interface WPEditorToolbarView ()
#pragma mark - Properties: Toolbar
@property (nonatomic, weak) UIView *contentView;
@property (nonatomic, weak) UIView *topBorderView;
@property (nonatomic, weak) UIToolbar *leftToolbar;
@property (nonatomic, weak) UIToolbar *rightToolbar;
@property (nonatomic, weak) UIView *rightToolbarHolder;
@property (nonatomic, weak) UIView *rightToolbarDivider;
@property (nonatomic, weak) UIScrollView *toolbarScroll;
#pragma mark - Properties: Toolbar items
@property (nonatomic, strong, readwrite) UIBarButtonItem* htmlBarButtonItem;
/**
* Toolbar items to include
*/
@property (nonatomic, assign, readwrite) ZSSRichTextEditorToolbar enabledToolbarItems;
@end
@implementation WPEditorToolbarView
/**
* @brief Initializer for the view with a certain frame.
*
* @param frame The frame for the view.
*
* @return The initialized object.
*/
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_enabledToolbarItems = [self defaultToolbarItems];
[self buildToolbar];
}
return self;
}
// life
- (instancetype)initWithFrame:(CGRect)frame isMarkdown:(BOOL)isMarkdown
{
self = [super initWithFrame:frame];
self.isMarkdown = isMarkdown;
if (self) {
_enabledToolbarItems = [self defaultToolbarItems];
[self buildToolbar];
}
return self;
}
#pragma mark - Toolbar building
- (void)buildToolbar
{
[self buildMainToolbarHolder];
[self buildToolbarScroll];
[self buildLeftToolbar];
// 右侧html source
/*
if (!IS_IPAD && !self.isMarkdown) {
[self.contentView addSubview:[self rightToolbarHolder]];
}
*/
}
- (void)reloadItems
{
if (IS_IPAD) {
[self reloadiPadItems];
} else {
[self reloadiPhoneItems];
}
}
- (void)reloadiPhoneItems
{
NSMutableArray *items = [self.items mutableCopy];
CGFloat toolbarItemsSeparation = 0.0f;
if ([WPDeviceIdentification isiPhoneSixPlus]) {
toolbarItemsSeparation = kNegativeSixPlusToolbarItemPadding;
} else if ([WPDeviceIdentification isiPhoneSix]) {
toolbarItemsSeparation = kNegativeSixToolbarItemPadding;
} else {
toolbarItemsSeparation = kNegativeToolbarItemPadding;
}
CGFloat toolbarWidth = 0.0f;
NSUInteger numberOfItems = items.count;
if (numberOfItems > 0) {
CGFloat finalPaddingBetweenItems = kDefaultToolbarItemPadding - toolbarItemsSeparation;
toolbarWidth += (numberOfItems * WPEditorToolbarButtonWidth);
toolbarWidth += (numberOfItems * finalPaddingBetweenItems);
}
UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
negativeSeparator.width = -toolbarItemsSeparation;
// This code adds a negative separator between all the toolbar buttons
for (NSInteger i = [items count]; i >= 0; i--) {
[items insertObject:negativeSeparator atIndex:i];
}
UIBarButtonItem *negativeSeparatorForToolbar = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
CGFloat finalToolbarLeftPadding = kDefaultToolbarLeftPadding - kNegativeLeftToolbarLeftPadding;
negativeSeparatorForToolbar.width = -kNegativeLeftToolbarLeftPadding;
toolbarWidth += finalToolbarLeftPadding;
self.leftToolbar.items = items;
self.leftToolbar.frame = CGRectMake(0, 0, toolbarWidth, WPEditorToolbarHeight);
self.toolbarScroll.contentSize = CGSizeMake(CGRectGetWidth(self.leftToolbar.frame),
WPEditorToolbarHeight);
}
- (void)reloadiPadItems
{
NSMutableArray *items = [self.items mutableCopy];
CGFloat toolbarWidth = CGRectGetWidth(self.toolbarScroll.frame);
UIBarButtonItem *flexSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
UIBarButtonItem *buttonSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
buttonSpacer.width = WPEditorToolbarButtonWidth;
[items insertObject:buttonSpacer atIndex:1];
[items insertObject:buttonSpacer atIndex:5];
[items insertObject:buttonSpacer atIndex:7];
[items insertObject:buttonSpacer atIndex:11];
[items insertObject:flexSpacer atIndex:0];
[items insertObject:flexSpacer atIndex:items.count];
self.leftToolbar.items = items;
self.leftToolbar.frame = CGRectMake(0, 0, toolbarWidth, WPEditorToolbarHeight);
self.toolbarScroll.contentSize = CGSizeMake(CGRectGetWidth(self.leftToolbar.frame),
WPEditorToolbarHeight);
}
#pragma mark - Toolbar building helpers
- (void)buildLeftToolbar
{
NSAssert(_leftToolbar == nil, @"This is supposed to be called only once.");
UIToolbar* leftToolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
leftToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
leftToolbar.barTintColor = self.backgroundColor;
leftToolbar.translucent = NO;
// We had some issues with the left toolbar not resizing properly - and we didn't realize
// immediately. Clipping to bounds is a good way to realize sooner and not later.
//
leftToolbar.clipsToBounds = YES;
[self.toolbarScroll addSubview:leftToolbar];
self.leftToolbar = leftToolbar;
}
- (void)buildMainToolbarHolder
{
CGRect subviewFrame = self.frame;
subviewFrame.origin = CGPointZero;
UIView* mainToolbarHolderContent = [[UIView alloc] initWithFrame:subviewFrame];
mainToolbarHolderContent.autoresizingMask = UIViewAutoresizingFlexibleWidth;
subviewFrame.size.height = 1.0f;
UIView* mainToolbarHolderTopBorder = [[UIView alloc] initWithFrame:subviewFrame];
mainToolbarHolderTopBorder.autoresizingMask = UIViewAutoresizingFlexibleWidth;
mainToolbarHolderTopBorder.backgroundColor = self.borderColor;
[self addSubview:mainToolbarHolderContent];
[self addSubview:mainToolbarHolderTopBorder];
self.contentView = mainToolbarHolderContent;
self.topBorderView = mainToolbarHolderTopBorder;
}
- (void)buildToolbarScroll
{
NSAssert(_toolbarScroll == nil, @"This is supposed to be called only once.");
CGFloat scrollviewWidth = CGRectGetWidth(self.frame);
/* 都不要
if (!IS_IPAD && !self.isMarkdown) {
scrollviewWidth -= WPEditorToolbarRightButtonWidth; // WPEditorToolbarButtonWidth;
}
*/
CGRect toolbarScrollFrame = CGRectMake(0,
0,
scrollviewWidth,
WPEditorToolbarHeight);
UIScrollView* toolbarScroll = [[UIScrollView alloc] initWithFrame:toolbarScrollFrame];
toolbarScroll.showsHorizontalScrollIndicator = NO;
if (IS_IPAD) {
toolbarScroll.scrollEnabled = NO;
}
toolbarScroll.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.contentView addSubview:toolbarScroll];
self.toolbarScroll = toolbarScroll;
}
#pragma mark - Toolbar size
+ (CGFloat)height
{
return WPEditorToolbarHeight;
}
#pragma mark - Toolbar buttons
// 创建每一个bar
- (ZSSBarButtonItem*)barButtonItemWithTag:(WPEditorViewControllerElementTag)tag
htmlProperty:(NSString*)htmlProperty
imageName:(NSString*)imageName
target:(id)target
selector:(SEL)selector
accessibilityLabel:(NSString*)accessibilityLabel
{
ZSSBarButtonItem *barButtonItem = [[ZSSBarButtonItem alloc] initWithImage:nil
style:UIBarButtonItemStylePlain
target:nil
action:nil];
barButtonItem.tag = tag;
barButtonItem.htmlProperty = htmlProperty;
barButtonItem.accessibilityLabel = accessibilityLabel;
UIImage* buttonImage = [[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
WPEditorToolbarButton* customButton = [[WPEditorToolbarButton alloc] initWithFrame:CGRectMake(0,
0,
WPEditorToolbarButtonWidth,
WPEditorToolbarButtonHeight)];
[customButton setImage:buttonImage forState:UIControlStateNormal];
customButton.normalTintColor = self.itemTintColor;
customButton.selectedTintColor = self.selectedItemTintColor;
customButton.isMarkdown = self.isMarkdown;
[customButton addTarget:target
action:selector
forControlEvents:UIControlEventTouchUpInside];
barButtonItem.customView = customButton;
return barButtonItem;
}
#pragma mark - Toolbar items
- (BOOL)canShowToolbarOption:(ZSSRichTextEditorToolbar)toolbarOption
{
return (self.enabledToolbarItems & toolbarOption
|| self.enabledToolbarItems & ZSSRichTextEditorToolbarAll);
}
- (ZSSRichTextEditorToolbar)defaultToolbarItems
{
ZSSRichTextEditorToolbar defaultToolbarItems = (ZSSRichTextEditorToolbarInsertImage
| ZSSRichTextEditorToolbarBold
| ZSSRichTextEditorToolbarItalic
| ZSSRichTextEditorToolbarInsertLink
| ZSSRichTextEditorToolbarBlockQuote
| ZSSRichTextEditorToolbarUnorderedList
| ZSSRichTextEditorToolbarOrderedList);
// iPad gets the HTML source button too
if (IS_IPAD) {
defaultToolbarItems = (defaultToolbarItems
| ZSSRichTextEditorToolbarStrikeThrough
| ZSSRichTextEditorToolbarViewSource);
}
return defaultToolbarItems;
}
- (void)enableToolbarItems:(BOOL)enable
shouldShowSourceButton:(BOOL)showSource
{
NSArray *items = self.leftToolbar.items;
for (ZSSBarButtonItem *item in items) {
if (item.tag == kWPEditorViewControllerElementShowSourceBarButton) {
item.enabled = showSource;
} else {
item.enabled = enable;
if (!enable) {
[item setSelected:NO];
}
}
}
}
- (void)clearSelectedToolbarItems
{
for (ZSSBarButtonItem *item in self.leftToolbar.items) {
if (item.tag != kWPEditorViewControllerElementShowSourceBarButton) {
[item setSelected:NO];
}
}
}
- (BOOL)hasSomeEnabledToolbarItems
{
return !(self.enabledToolbarItems & ZSSRichTextEditorToolbarNone);
}
- (void)selectToolbarItemsForStyles:(NSArray*)styles
{
NSArray *items = self.leftToolbar.items;
for (UIBarButtonItem *item in items) {
// Since we're using UIBarItem as negative separators, we need to make sure we don't try to
// use those here.
if ([item isKindOfClass:[ZSSBarButtonItem class]]) {
ZSSBarButtonItem* zssItem = (ZSSBarButtonItem*)item;
if ([styles containsObject:zssItem.htmlProperty]) {
zssItem.selected = YES;
} else {
zssItem.selected = NO;
}
// markdown编辑器btn没有selected
if(self.isMarkdown) {
zssItem.selected = NO;
}
// [zssItem setSelected:YES];
// zssItem.selected = YES;
}
}
}
#pragma mark - Getters
- (UIBarButtonItem*)htmlBarButtonItem
{
if (!_htmlBarButtonItem) {
UIBarButtonItem* htmlBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"HTML"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
UIFont * font = [UIFont boldSystemFontOfSize:10];
NSDictionary * attributes = @{NSFontAttributeName: font};
[htmlBarButtonItem setTitleTextAttributes:attributes forState:UIControlStateNormal];
htmlBarButtonItem.accessibilityLabel = NSLocalizedString(@"Display HTML",
@"Accessibility label for display HTML button on formatting toolbar.");
CGRect customButtonFrame = CGRectMake(0,
0,
WPEditorToolbarButtonWidth,
WPEditorToolbarButtonHeight);
WPEditorToolbarButton* customButton = [[WPEditorToolbarButton alloc] initWithFrame:customButtonFrame];
[customButton setTitle:@"HTML" forState:UIControlStateNormal];
customButton.normalTintColor = self.itemTintColor;
customButton.selectedTintColor = self.selectedItemTintColor;
customButton.reversesTitleShadowWhenHighlighted = YES;
customButton.titleLabel.font = font;
[customButton addTarget:self
action:@selector(showHTMLSource:)
forControlEvents:UIControlEventTouchUpInside];
htmlBarButtonItem.customView = customButton;
_htmlBarButtonItem = htmlBarButtonItem;
}
return _htmlBarButtonItem;
}
// 右侧
- (UIView*)rightToolbarHolder
{
UIView* rightToolbarHolder = _rightToolbarHolder;
if (!rightToolbarHolder) {
UIView* rightToolbarDivider = _rightToolbarDivider;
if (!rightToolbarDivider) {
CGRect dividerLineFrame = CGRectMake(0.0f,
floorf((WPEditorToolbarHeight - WPEditorToolbarDividerLineHeight) / 2),
WPEditorToolbarDividerLineWidth,
WPEditorToolbarDividerLineHeight);
rightToolbarDivider = [[UIView alloc] initWithFrame:dividerLineFrame];
rightToolbarDivider.backgroundColor = self.borderColor;
rightToolbarDivider.alpha = 0.7f;
_rightToolbarDivider = rightToolbarDivider;
}
CGRect rightSpacerFrame = CGRectMake(CGRectGetMaxX(self.rightToolbarDivider.frame),
0.0f,
kNegativeRightToolbarPadding / 2,
WPEditorToolbarHeight);
UIView *rightSpacer = [[UIView alloc] initWithFrame:rightSpacerFrame];
CGRect rightToolbarHolderFrame = CGRectMake(CGRectGetWidth(self.frame) - (WPEditorToolbarButtonWidth + CGRectGetWidth(self.rightToolbarDivider.frame) + CGRectGetWidth(rightSpacer.frame)),
0.0f,
WPEditorToolbarButtonWidth + CGRectGetWidth(self.rightToolbarDivider.frame) + CGRectGetWidth(rightSpacer.frame),
WPEditorToolbarHeight);
rightToolbarHolder = [[UIView alloc] initWithFrame:rightToolbarHolderFrame];
rightToolbarHolder.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
rightToolbarHolder.clipsToBounds = YES;
CGRect toolbarFrame = CGRectMake(CGRectGetMaxX(rightSpacer.frame),
0.0f,
CGRectGetWidth(rightToolbarHolder.frame),
CGRectGetHeight(rightToolbarHolder.frame));
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame];
self.rightToolbar = toolbar;
[rightToolbarHolder addSubview:rightSpacer];
[rightToolbarHolder addSubview:self.rightToolbarDivider];
[rightToolbarHolder addSubview:toolbar];
UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
// Negative separator needs to be different on 6+
if ([WPDeviceIdentification isiPhoneSixPlus]) {
negativeSeparator.width = -kNegativeSixPlusRightToolbarPadding;
} else {
negativeSeparator.width = -kNegativeRightToolbarPadding;
}
toolbar.items = @[negativeSeparator, [self htmlBarButtonItem]];
toolbar.barTintColor = self.backgroundColor;
}
return rightToolbarHolder;
}
#pragma mark - Setters
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
if (self.backgroundColor != backgroundColor) {
super.backgroundColor = backgroundColor;
self.leftToolbar.barTintColor = backgroundColor;
self.rightToolbar.barTintColor = backgroundColor;
}
}
- (void)setBorderColor:(UIColor *)borderColor
{
if (_borderColor != borderColor) {
_borderColor = borderColor;
self.topBorderView.backgroundColor = borderColor;
self.rightToolbarDivider.backgroundColor = borderColor;
}
}
- (void)setItems:(NSArray*)items
{
if (_items != items) {
_items = [items copy];
[self reloadItems];
}
}
- (void)setItemTintColor:(UIColor *)itemTintColor
{
_itemTintColor = itemTintColor;
for (UIBarButtonItem *item in self.leftToolbar.items) {
item.tintColor = _itemTintColor;
}
if (self.htmlBarButtonItem) {
WPEditorToolbarButton* htmlButton = (WPEditorToolbarButton*)self.htmlBarButtonItem.customView;
NSAssert([htmlButton isKindOfClass:[WPEditorToolbarButton class]],
@"Expected to have an HTML button of class WPEditorToolbarButton here.");
htmlButton.normalTintColor = itemTintColor;
self.htmlBarButtonItem.tintColor = itemTintColor;
}
}
- (void)setSelectedItemTintColor:(UIColor *)selectedItemTintColor
{
_selectedItemTintColor = selectedItemTintColor;
if (self.htmlBarButtonItem) {
WPEditorToolbarButton* htmlButton = (WPEditorToolbarButton*)self.htmlBarButtonItem.customView;
NSAssert([htmlButton isKindOfClass:[WPEditorToolbarButton class]],
@"Expected to have an HTML button of class WPEditorToolbarButton here.");
htmlButton.selectedTintColor = selectedItemTintColor;
}
}
#pragma mark - Temporary: added to make the refactor easier, but should be removed at some point
- (void)showHTMLSource:(UIBarButtonItem *)barButtonItem
{
[self.delegate editorToolbarView:self showHTMLSource:barButtonItem];
}
@end