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

2134 lines
63 KiB
Objective-C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#import "WPEditorViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <UIAlertView+Blocks/UIAlertView+Blocks.h>
#import <UIKit/UIKit.h>
#import <WordPressCom-Analytics-iOS/WPAnalytics.h>
#import <WordPress-iOS-Shared/WPFontManager.h>
#import <WordPress-iOS-Shared/WPStyleGuide.h>
#import <WordPress-iOS-Shared/WPTableViewCell.h>
#import <WordPress-iOS-Shared/UIImage+Util.h>
#import <WordPress-iOS-Shared/UIColor+Helpers.h>
#import "WPEditorField.h"
#import "WPEditorToolbarButton.h"
#import "WPEditorToolbarView.h"
#import "WPEditorView.h"
#import "WPImageMeta.h"
#import "ZSSBarButtonItem.h"
#import "DRColorPicker.h"
#import "DRColorPickerHomeViewController.h"
#import "WPDeviceIdentification.h"
CGFloat const EPVCStandardOffset = 10.0;
NSInteger const WPImageAlertViewTag = 91;
NSInteger const WPLinkAlertViewTag = 92;
@interface WPEditorViewController () <HRColorPickerViewControllerDelegate, UIAlertViewDelegate, WPEditorToolbarViewDelegate, WPEditorViewDelegate>
@property (nonatomic, strong) NSString *htmlString;
@property (nonatomic, strong) NSArray *editorItemsEnabled;
@property (nonatomic, strong) UIAlertView *alertView;
@property (nonatomic, strong) NSString *selectedImageURL;
@property (nonatomic, strong) NSString *selectedImageAlt;
@property (nonatomic) BOOL didFinishLoadingEditor;
@property (nonatomic, weak) WPEditorField* focusedField;
#pragma mark - Properties: First Setup On View Will Appear
@property (nonatomic, assign, readwrite) BOOL isFirstSetupComplete;
#pragma mark - Properties: Editing
@property (nonatomic, assign, readwrite, getter=isEditingEnabled) BOOL editingEnabled;
@property (nonatomic, assign, readwrite, getter=isEditing) BOOL editing;
@property (nonatomic, assign, readwrite) BOOL wasEditing;
#pragma mark - Properties: Editor View
@property (nonatomic, strong, readwrite) WPEditorView *editorView;
#pragma mark - Properties: Toolbar
@property (nonatomic, strong, readwrite) WPEditorToolbarView* toolbarView;
#pragma colorPicker
@property (nonatomic, strong) DRColorPickerColor* color;
@property (nonatomic, weak) DRColorPickerViewController* colorPickerVC;
@end
@implementation WPEditorViewController
#pragma mark - Initializers
// 这里, 编辑模式, fuck
- (instancetype)init
{
return [self initWithMode:kWPEditorViewControllerModeEdit];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self sharedInitializationWithEditing:YES];
}
return self;
}
- (instancetype)initWithMode:(WPEditorViewControllerMode)mode
{
self = [super init];
if (self) {
BOOL editing = NO;
if (mode == kWPEditorViewControllerModePreview) {
editing = NO;
} else {
editing = YES;
}
[self sharedInitializationWithEditing:editing];
}
return self;
}
// life
- (instancetype)initWithMode:(WPEditorViewControllerMode)mode isMarkdown:(BOOL)isMarkdown
{
self = [super init];
if (self) {
BOOL editing = NO;
if (mode == kWPEditorViewControllerModePreview) {
editing = NO;
} else {
editing = YES;
}
[self sharedInitializationWithEditing:editing];
}
self.isMarkdown = isMarkdown;
return self;
}
#pragma mark - Shared Initialization Code
- (void)sharedInitializationWithEditing:(BOOL)editing
{
if (editing == kWPEditorViewControllerModePreview) {
_editing = NO;
} else {
_editing = YES;
}
}
#pragma mark - Creation of subviews
- (void)createToolbarView
{
NSAssert(!_toolbarView, @"The toolbar view should not exist here.");
CGRect toolbarFrame = CGRectMake(0,
0,
CGRectGetWidth(self.view.frame),
[WPEditorToolbarView height]);
_toolbarView = [[WPEditorToolbarView alloc] initWithFrame:toolbarFrame isMarkdown:self.isMarkdown];
_toolbarView.delegate = self;
_toolbarView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_toolbarView.backgroundColor = [UIColor whiteColor];
_toolbarView.borderColor = [WPStyleGuide readGrey];
_toolbarView.itemTintColor = [WPStyleGuide textFieldPlaceholderGrey];
_toolbarView.selectedItemTintColor = [WPStyleGuide baseDarkerBlue];
_toolbarView.items = [self itemsForToolbar];
}
#pragma mark - UIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// It's important to set this up here, in case the main view of the VC is unloaded due to low
// memory (it can happen if the view is hidden).
//
self.isFirstSetupComplete = NO;
self.didFinishLoadingEditor = NO;
self.view.backgroundColor = [UIColor whiteColor];
// Calling the fonts we use here so they are availible to the UIWebView
[WPFontManager merriweatherBoldFontOfSize:30];
[WPFontManager openSansRegularFontOfSize:16];
[WPFontManager openSansItalicFontOfSize:16];
[WPFontManager openSansBoldFontOfSize:16];
[WPFontManager openSansBoldItalicFontOfSize:16];
// start 之前这段代码是放在viewDidLoad中的, 但frame有问题, 包括了navigation的高度
// 这两处地方不能换啊, 换了有大问题. 如果换了, 当切换到source view 时, 它的input accessory不会显示
// 创建工具栏
[self createToolbarView];
// 创建编辑区
[self buildTextViews];
NSLog(@"frame height viewWillAppear %f", CGRectGetHeight(self.view.frame));
// end
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// 为什么不能放到这里, 好奇怪, 会让按钮的selected失效, 当弹图片后
// 为什么这么怪?
// frame height有什么用?
// 因为viewWillApper 每次都会调用createToolbarView
/*
// start 之前这段代码是放在viewDidLoad中的, 但frame有问题, 包括了navigation的高度
// 这两处地方不能换啊, 换了有大问题. 如果换了, 当切换到source view 时, 它的input accessory不会显示
// 创建工具栏
[self createToolbarView];
// 创建编辑区
[self buildTextViews];
NSLog(@"frame height viewWillAppear %f", CGRectGetHeight(self.view.frame));
// end
*/
if (!self.isFirstSetupComplete) {
self.isFirstSetupComplete = YES;
// When restoring state, the navigationController is nil when the view loads,
// so configure its appearance here instead.
self.navigationController.navigationBar.translucent = NO;
for (UIView *view in self.navigationController.toolbar.subviews) {
[view setExclusiveTouch:YES];
}
if (self.isEditing) {
// [self startEditing];
}
}
[self.navigationController setToolbarHidden:YES animated:animated];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.isFirstSetupComplete) {
// 这里, 当图片取消后插入后, 会执行这个
[self restoreEditSelection];
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// It's important to save the edit selection before the view disappears, because as soon as it
// disappears the first responder is changed.
//
[self saveEditSelection];
}
#pragma mark - Toolbar items
- (NSMutableArray *)itemsForToolbar
{
NSMutableArray *items = [[NSMutableArray alloc] init];
if ([self.toolbarView hasSomeEnabledToolbarItems]) {
if ([self canShowInsertImageBarButton]) {
[items addObject:[self insertImageBarButton]];
}
if(self.isMarkdown) {
[items addObject:[self header1BarButton]];
}
if ([self canShowBoldBarButton]) {
[items addObject:[self boldBarButton]];
}
if ([self canShowItalicBarButton]) {
[items addObject:[self italicBarButton]];
}
if ([self canShowSubscriptBarButton]) {
[items addObject:[self subscriptBarButton]];
}
if ([self canShowSuperscriptBarButton]) {
[items addObject:[self superscriptBarButton]];
}
// strike, color, background-color
if(!self.isMarkdown) {
// if ([self canShowUnderlineBarButton]) {
[items addObject:[self underlineBarButton]];
// }
// if ([self canShowStrikeThroughBarButton]) {
[items addObject:[self strikeThroughBarButton]];
// }
// if ([self canShowTextColorBarButton]) {
[items addObject:[self textColorBarButton]];
// }
// if ([self canShowBackgroundColorBarButton]) {
[items addObject:[self backgroundColorBarButton]];
// }
}
if (!IS_IPAD && [self canShowBlockQuoteBarButton]) {
[items addObject:[self blockQuoteBarButton]];
}
if ([self canShowAlignLeftBarButton]) {
[items addObject:[self alignLeftBarButton]];
}
if ([self canShowAlignCenterBarButton]) {
[items addObject:[self alignCenterBarButton]];
}
if ([self canShowAlignRightBarButton]) {
[items addObject:[self alignRightBarButton]];
}
if ([self canShowAlignFullBarButton]) {
[items addObject:[self alignFullBarButton]];
}
if ([self canShowHeader2BarButton]) {
[items addObject:[self header2BarButton]];
}
if ([self canShowHeader3BarButton]) {
[items addObject:[self header3BarButton]];
}
if ([self canShowHeader4BarButton]) {
[items addObject:[self header4BarButton]];
}
if ([self canShowHeader5BarButton]) {
[items addObject:[self header5BarButton]];
}
if ([self canShowHeader6BarButton]) {
[items addObject:[self header6BarButton]];
}
if (IS_IPAD && [self canShowInsertLinkBarButton]) {
[items addObject:[self inserLinkBarButton]];
}
if ([self canShowUnorderedListBarButton]) {
[items addObject:[self unorderedListBarButton]];
}
if ([self canShowOrderedListBarButton]) {
[items addObject:[self orderedListBarButton]];
}
// if ([self canShowHorizontalRuleBarButton]) {
[items addObject:[self horizontalRuleBarButton]];
// }
if ([self canShowIndentBarButton]) {
[items addObject:[self indentBarButton]];
}
if ([self canShowOutdentBarButton]) {
[items addObject:[self outdentBarButton]];
}
if (!IS_IPAD && [self canShowInsertLinkBarButton]) {
[items addObject:[self inserLinkBarButton]];
}
if (IS_IPAD && [self canShowBlockQuoteBarButton]) {
[items addObject:[self blockQuoteBarButton]];
}
if ([self canShowRemoveLinkBarButton]) {
[items addObject:[self removeLinkBarButton]];
}
if ([self canShowQuickLinkBarButton]) {
[items addObject:[self quickLinkBarButton]];
}
if ([self canShowSourceBarButton]) {
// [items addObject:[self showSourceBarButton]];
}
if(!self.isMarkdown) {
[items addObject:[self header1BarButton]];
[items addObject:[self header2BarButton]];
[items addObject:[self header3BarButton]];
[items addObject:[self removeFormatBarButton]];
[items addObject:[self showSourceBarButton]];
// undo, redo没用
// [items addObject:[self undoBarButton]];
// [items addObject:[self redoBarButton]];
}
else {
[items addObject:[self newlineBarButton]];
}
}
return items;
}
#pragma mark - Toolbar: helper methods
- (void)clearToolbar
{
if (!self.editorView.isInVisualMode) {
[self.toolbarView clearSelectedToolbarItems];
}
}
- (BOOL)canShowToolbarOption:(ZSSRichTextEditorToolbar)toolbarOption
{
return [self.toolbarView canShowToolbarOption:toolbarOption];
}
- (BOOL)canShowAlignLeftBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarJustifyLeft];
}
- (BOOL)canShowAlignCenterBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarJustifyCenter];
}
- (BOOL)canShowAlignFullBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarJustifyFull];
}
- (BOOL)canShowAlignRightBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarJustifyRight];
}
- (BOOL)canShowBackgroundColorBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarBackgroundColor];
}
- (BOOL)canShowBlockQuoteBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarBlockQuote];
}
- (BOOL)canShowBoldBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarBold];
}
- (BOOL)canShowHeader1BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH1];
}
- (BOOL)canShowHeader2BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH2];
}
- (BOOL)canShowHeader3BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH3];
}
- (BOOL)canShowHeader4BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH4];
}
- (BOOL)canShowHeader5BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH5];
}
- (BOOL)canShowHeader6BarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarH6];
}
- (BOOL)canShowHorizontalRuleBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarHorizontalRule];
}
- (BOOL)canShowIndentBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarIndent];
}
- (BOOL)canShowInsertImageBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarInsertImage];
}
- (BOOL)canShowInsertLinkBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarInsertLink];
}
- (BOOL)canShowItalicBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarItalic];
}
- (BOOL)canShowOrderedListBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarOrderedList];
}
- (BOOL)canShowOutdentBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarOutdent];
}
- (BOOL)canShowQuickLinkBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarQuickLink];
}
- (BOOL)canShowRedoBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarRedo];
}
- (BOOL)canShowRemoveFormatBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarRemoveFormat];
}
- (BOOL)canShowRemoveLinkBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarRemoveLink];
}
- (BOOL)canShowSourceBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarViewSource];
}
- (BOOL)canShowStrikeThroughBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarStrikeThrough];
}
- (BOOL)canShowSubscriptBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarSubscript];
}
- (BOOL)canShowSuperscriptBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarSuperscript];
}
- (BOOL)canShowTextColorBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarTextColor];
}
- (BOOL)canShowUnderlineBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarUnderline];
}
- (BOOL)canShowUndoBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarUndo];
}
- (BOOL)canShowUnorderedListBarButton
{
return [self canShowToolbarOption:ZSSRichTextEditorToolbarUnorderedList];
}
#pragma mark - Toolbar: buttons
// 这些方法没用啊
- (ZSSBarButtonItem*)barButtonItemWithTag:(WPEditorViewControllerElementTag)tag
htmlProperty:(NSString*)htmlProperty
imageName:(NSString*)imageName
target:(id)target
selector:(SEL)selector
accessibilityLabel:(NSString*)accessibilityLabel
{
return [self.toolbarView barButtonItemWithTag:tag
htmlProperty:htmlProperty
imageName:imageName
target:target
selector:selector
accessibilityLabel:accessibilityLabel];
}
- (ZSSBarButtonItem*)alignLeftBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagJustifyLeftBarButton
htmlProperty:@"justifyLeft"
imageName:@"ZSSleftjustify.png"
target:self
selector:@selector(alignLeft)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)alignCenterBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagJustifyCenterBarButton
htmlProperty:@"justifyCenter"
imageName:@"ZSScenterjustify.png"
target:self
selector:@selector(alignCenter)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)alignFullBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagJustifyFullBarButton
htmlProperty:@"justifyFull"
imageName:@"ZSSforcejustify.png"
target:self
selector:@selector(alignFull)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)alignRightBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagJustifyRightBarButton
htmlProperty:@"justifyRight"
imageName:@"ZSSrightjustify.png"
target:self
selector:@selector(alignRight)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)backgroundColorBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagBackgroundColorBarButton
htmlProperty:@"backgroundColor"
imageName:@"ZSSbgcolor.png"
target:self
selector:@selector(bgColor)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)blockQuoteBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Block Quote",
@"Accessibility label for block quote button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagBlockQuoteBarButton
htmlProperty:@"blockquote"
imageName:@"icon_format_quote"
target:self
selector:@selector(setBlockQuote)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)boldBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Bold",
@"Accessibility label for bold button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagBoldBarButton
htmlProperty:@"bold"
imageName:@"icon_format_bold"
target:self
selector:@selector(setBold)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)header1BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH1BarButton
htmlProperty:@"h1"
imageName: self.isMarkdown ? @"ZSSh.png" : @"ZSSh1.png" // ZSSh1.png
target:self
selector:@selector(heading1)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)header2BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH2BarButton
htmlProperty:@"h2"
imageName:@"ZSSh2.png"
target:self
selector:@selector(heading2)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)header3BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH3BarButton
htmlProperty:@"h3"
imageName:@"ZSSh3.png"
target:self
selector:@selector(heading3)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)header4BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH4BarButton
htmlProperty:@"h4"
imageName:@"ZSSh4.png"
target:self
selector:@selector(heading4)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)header5BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH5BarButton
htmlProperty:@"h5"
imageName:@"ZSSh5.png"
target:self
selector:@selector(heading5)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)header6BarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagH6BarButton
htmlProperty:@"h6"
imageName:@"ZSSh6.png"
target:self
selector:@selector(heading6)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)horizontalRuleBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagHorizontalRuleBarButton
htmlProperty:@"horizontalRule"
imageName:@"ZSShorizontalrule.png"
target:self
selector:@selector(setHR)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)indentBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagIndentBarButton
htmlProperty:@"indent"
imageName:@"ZSSindent.png"
target:self
selector:@selector(setIndent)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)insertImageBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Insert Image",
@"Accessibility label for insert image button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagInsertImageBarButton
htmlProperty:@"image"
imageName:@"icon_format_media"
target:self
selector:@selector(didTouchMediaOptions)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)inserLinkBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Insert Link",
@"Accessibility label for insert link button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagInsertLinkBarButton
htmlProperty:@"link"
imageName:@"icon_format_link"
target:self
selector:@selector(linkBarButtonTapped:)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)italicBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Italic",
@"Accessibility label for italic button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTagItalicBarButton
htmlProperty:@"italic"
imageName:@"icon_format_italic"
target:self
selector:@selector(setItalic)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)orderedListBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Ordered List",
@"Accessibility label for ordered list button on formatting toolbar.");;
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementOrderedListBarButton
htmlProperty:@"orderedList"
imageName:@"icon_format_ol"
target:self
selector:@selector(setOrderedList)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)outdentBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementOutdentBarButton
htmlProperty:@"outdent"
imageName:@"ZSSoutdent.png"
target:self
selector:@selector(setOutdent)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)quickLinkBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementQuickLinkBarButton
htmlProperty:@"quickLink"
imageName:@"ZSSquicklink.png"
target:self
selector:@selector(quickLink)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)redoBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementRedoBarButton
htmlProperty:@"redo"
imageName:@"ZSSredo.png"
target:self
selector:@selector(redo:)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)removeFormatBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementRemoveFormatBarButton
htmlProperty:@"removeFormat"
imageName:@"ZSSclearstyle.png"
target:self
selector:@selector(removeFormat)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)removeLinkBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Remove Link",
@"Accessibility label for remove link button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementRemoveFormatBarButton
htmlProperty:@"link"
imageName:@"icon_format_unlink"
target:self
selector:@selector(removeLink)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)showSourceBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"HTML",
@"Accessibility label for HTML button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementShowSourceBarButton
htmlProperty:@"source"
imageName:@"icon_format_html"
target:self
selector:@selector(showHTMLSource:)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)strikeThroughBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Strike Through",
@"Accessibility label for strikethrough button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementStrikeThroughBarButton
htmlProperty:@"strikeThrough"
imageName:@"icon_format_strikethrough"
target:self
selector:@selector(setStrikethrough)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)subscriptBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementSubscriptBarButton
htmlProperty:@"subscript"
imageName:@"ZSSsubscript.png"
target:self
selector:@selector(setSubscript)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)superscriptBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementSuperscriptBarButton
htmlProperty:@"superscript"
imageName:@"ZSSsuperscript.png"
target:self
selector:@selector(setSuperscript)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)textColorBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementTextColorBarButton
htmlProperty:@"textColor"
imageName:@"ZSStextcolor.png"
target:self
selector:@selector(textColor)
accessibilityLabel:nil];
return barButtonItem;
}
- (UIBarButtonItem*)underlineBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Underline",
@"Accessibility label for underline button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementUnderlineBarButton
htmlProperty:@"underline"
imageName:@"icon_format_underline"
target:self
selector:@selector(setUnderline)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)unorderedListBarButton
{
NSString* accessibilityLabel = NSLocalizedString(@"Unordered List",
@"Accessibility label for unordered list button on formatting toolbar.");
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementUnorderedListBarButton
htmlProperty:@"unorderedList"
imageName:@"icon_format_ul"
target:self
selector:@selector(setUnorderedList)
accessibilityLabel:accessibilityLabel];
return barButtonItem;
}
- (UIBarButtonItem*)undoBarButton
{
ZSSBarButtonItem *barButtonItem = [self barButtonItemWithTag:kWPEditorViewControllerElementUndoBarButton
htmlProperty:@"undo"
imageName:@"ZSSundo.png"
target:self
selector:@selector(undo:)
accessibilityLabel:nil];
return barButtonItem;
}
// markdown 回车
- (UIBarButtonItem*)newlineBarButton
{
ZSSBarButtonItem *newlineBarButton = [self barButtonItemWithTag:kWPEditorViewControllerElementEnterBarButton
htmlProperty:@"enter"
imageName:@"enter.png"
target:self
selector:@selector(newline)
accessibilityLabel:nil];
return newlineBarButton;
}
#pragma mark - Builders
// 编辑器初始化 WPEditorView
- (void)buildTextViews
{
if (!self.editorView) {
CGFloat viewWidth = CGRectGetWidth(self.view.frame);
UIViewAutoresizing mask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// 568, 504 怎么搞的
CGRect frame = CGRectMake(0.0f, 0.0f, viewWidth, CGRectGetHeight(self.view.frame));
self.editorView = [[WPEditorView alloc] initWithFrame:frame isMarkdown:self.isMarkdown];
self.editorView.delegate = self;
self.editorView.autoresizesSubviews = YES;
self.editorView.autoresizingMask = mask;
self.editorView.backgroundColor = [UIColor whiteColor];
self.editorView.sourceView.inputAccessoryView = self.toolbarView;
self.editorView.sourceViewTitleField.inputAccessoryView = self.toolbarView;
// Default placeholder text
self.titlePlaceholderText = NSLocalizedString(@"Title", @"Placeholder for the post title.");
self.bodyPlaceholderText = NSLocalizedString(@"Content", @"Placeholder for the post body.");
}
[self.view addSubview:self.editorView];
}
#pragma mark - Getters and Setters
- (NSString*)titleText
{
return [self.editorView title];
}
- (void)setTitleText:(NSString*)titleText
{
[self.editorView.titleField setText:titleText];
[self.editorView.sourceViewTitleField setText:titleText];
}
- (void)setTitlePlaceholderText:(NSString*)titlePlaceholderText
{
NSParameterAssert(titlePlaceholderText);
if (![titlePlaceholderText isEqualToString:_titlePlaceholderText]) {
_titlePlaceholderText = titlePlaceholderText;
[self.editorView.titleField setPlaceholderText:_titlePlaceholderText];
self.editorView.sourceViewTitleField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:_titlePlaceholderText
attributes:@{NSForegroundColorAttributeName: [WPStyleGuide allTAllShadeGrey]}];
}
}
- (NSString*)bodyText
{
return [self.editorView contents];
}
- (void)setBodyText:(NSString*)bodyText
{
[self.editorView.contentField setHtml:bodyText];
}
- (void)setBodyPlaceholderText:(NSString*)bodyPlaceholderText
{
NSParameterAssert(bodyPlaceholderText);
if (![bodyPlaceholderText isEqualToString:_bodyPlaceholderText]) {
_bodyPlaceholderText = bodyPlaceholderText;
[self.editorView.contentField setPlaceholderText:_bodyPlaceholderText];
}
}
#pragma mark - Actions
- (void)didTouchMediaOptions
{
if (self.editorView.isInVisualMode) {
if ([self.delegate respondsToSelector: @selector(editorDidPressMedia:)]) {
[self.delegate editorDidPressMedia:self];
}
} else {
// Do not allow users to insert images in HTML mode for now
__weak __typeof(self)weakSelf = self;
[UIAlertView showWithTitle:NSLocalizedString(@"Unable to insert image", @"Title of dialog notifing user they cannot insert an image in the editor's HTML mode.")
message:NSLocalizedString(@"You cannot insert images while editing HTML directly. Please switch back to visual mode.", @"Body of dialog notifing user they cannot insert an image in the editor's HTML mode.")
cancelButtonTitle:NSLocalizedString(@"OK", @"OK")
otherButtonTitles:nil
tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
[weakSelf clearToolbar];
}
];
}
[WPAnalytics track:WPAnalyticsStatEditorTappedImage];
}
#pragma mark - Editor and Misc Methods
- (BOOL)isBodyTextEmpty
{
if(!self.bodyText
|| self.bodyText.length == 0
|| [[self.bodyText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]
|| [[self.bodyText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@"<br>"]
|| [[self.bodyText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@"<br />"]) {
return YES;
}
return NO;
}
#pragma mark - Editing
/**
* @brief Enables editing.
*/
- (void)enableEditing
{
self.editingEnabled = YES;
if (self.didFinishLoadingEditor)
{
[self.editorView enableEditing];
}
}
/**
* @brief Disables editing.
*/
- (void)disableEditing
{
self.editingEnabled = NO;
if (self.didFinishLoadingEditor)
{
[self.editorView disableEditing];
}
}
/**
* @brief Restored the previously saved edit selection.
* @details Will only really do anything if editing is enabled.
*/
- (void)restoreEditSelection
{
if (self.isEditing) {
// IOS7 大BUG
// 不是markdown才这样, 因为在markdown下, io7有先focus会把selection去掉, 导致有问题!!!
if (!self.isMarkdown && [WPDeviceIdentification isiOSVersionEarlierThan8]){
[self.focusedField blur];
[self.focusedField focus];
}
[self.editorView restoreSelection];
}
}
/**
* @brief Saves the current edit selection, if any.
*/
- (void)saveEditSelection
{
if (self.isEditing) {
if ([WPDeviceIdentification isiOSVersionEarlierThan8]){
self.focusedField = self.editorView.focusedField;
}
[self.editorView saveSelection];
}
}
- (void)startEditing
{
self.editing = YES;
// We need the editor ready before executing the steps in the conditional block below.
// If it's not ready, this method will be called again on webViewDidFinishLoad:
//
if (self.didFinishLoadingEditor)
{
[self enableEditing];
[self tellOurDelegateEditingDidBegin];
}
}
- (void)stopEditing
{
self.editing = NO;
[self disableEditing];
[self tellOurDelegateEditingDidEnd];
}
#pragma mark - WPEditorToolbarViewDelegate
- (void)editorToolbarView:(WPEditorToolbarView *)editorToolbarView
showHTMLSource:(UIBarButtonItem *)barButtonItem
{
[self showHTMLSource:barButtonItem];
}
#pragma mark - Editor Interaction
- (void)showHTMLSource:(UIBarButtonItem *)barButtonItem
{
if ([self.editorView isInVisualMode]) {
if ([self askOurDelegateShouldDisplaySourceView]) {
[self.editorView showHTMLSource];
barButtonItem.tintColor = [self barButtonItemSelectedDefaultColor];
} else {
// Deselect the HTML button so it is in the proper state
[(UIButton *)barButtonItem setSelected:NO];
}
} else {
[self.editorView showVisualEditor];
barButtonItem.tintColor = [self.toolbarView itemTintColor];
}
// [WPAnalytics track:WPAnalyticsStatEditorTappedHTML];
}
- (void)removeFormat
{
[self.editorView removeFormat];
}
- (void)alignLeft
{
[self.editorView alignLeft];
}
- (void)alignCenter
{
[self.editorView alignCenter];
}
- (void)alignRight
{
[self.editorView alignRight];
}
- (void)alignFull
{
[self.editorView alignFull];
}
- (void)setBold
{
[self.editorView setBold];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedBold];
}
- (void)setBlockQuote
{
[self.editorView setBlockQuote];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedBlockquote];
}
- (void)setItalic
{
[self.editorView setItalic];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedItalic];
}
- (void)setSubscript
{
[self.editorView setSubscript];
}
- (void)setUnderline
{
[self.editorView setUnderline];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedUnderline];
}
- (void)setSuperscript
{
[self.editorView setSuperscript];
}
- (void)setStrikethrough
{
[self.editorView setStrikethrough];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedStrikethrough];
}
- (void)setUnorderedList
{
[self.editorView setUnorderedList];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedUnorderedList];
}
- (void)setOrderedList
{
[self.editorView setOrderedList];
[self clearToolbar];
[WPAnalytics track:WPAnalyticsStatEditorTappedOrderedList];
}
- (void)setHR
{
[self.editorView setHR];
}
- (void)setIndent
{
[self.editorView setIndent];
}
- (void)setOutdent
{
[self.editorView setOutdent];
}
- (void)heading1
{
[self.editorView heading1];
}
- (void)heading2
{
[self.editorView heading2];
}
- (void)heading3
{
[self.editorView heading3];
}
- (void)heading4
{
[self.editorView heading4];
}
- (void)heading5
{
[self.editorView heading5];
}
- (void)heading6
{
[self.editorView heading6];
}
- (void)newline
{
[self.editorView newline];
}
- (void)textColor
{
// Save the selection location
[self.editorView saveSelection];
[self initColorPicker2:YES];
/*
// Call the picker
HRColorPickerViewController *colorPicker = [HRColorPickerViewController cancelableFullColorPickerViewControllerWithColor:[UIColor whiteColor]];
colorPicker.delegate = self;
colorPicker.tag = 1;
colorPicker.title = NSLocalizedString(@"Text Color", nil);
[self.navigationController pushViewController:colorPicker animated:YES];
*/
}
- (void)bgColor
{
// Save the selection location
[self.editorView saveSelection];
[self initColorPicker2:NO];
/*
// Call the picker
HRColorPickerViewController *colorPicker = [HRColorPickerViewController cancelableFullColorPickerViewControllerWithColor:[UIColor whiteColor]];
colorPicker.delegate = self;
colorPicker.tag = 2;
colorPicker.title = NSLocalizedString(@"BG Color", nil);
[self.navigationController pushViewController:colorPicker animated:YES];
*/
}
// 是用modal来的, 但在ios8上, 关闭后不出键盘
- (void) initColorPicker:(BOOL)isTextColor
{
DRColorPickerBackgroundColor = [UIColor colorWithWhite:1.0f alpha:1.0f];
// border color of the color thumbnails
DRColorPickerBorderColor = [UIColor colorWithWhite:1.0f alpha:0.1f]; // [UIColor UIColorFromRGBAColorWithRed:238 green:238 blue:238 alpha:1];
DRColorPickerBorderColor = [UIColor UIColorFromRGBAColorWithRed:238 green:238 blue:238 alpha:1];
// font for any labels in the color picker
DRColorPickerFont = [UIFont systemFontOfSize:16.0f];
// font color for labels in the color picker
DRColorPickerLabelColor = [UIColor blackColor];
// END REQUIRED SETUP
// OPTIONAL SETUP....................
// max number of colors in the recent and favorites - default is 200
DRColorPickerStoreMaxColors = 200;
// show a saturation bar in the color wheel view - default is NO
DRColorPickerShowSaturationBar = YES;
// highlight the last hue in the hue view - default is NO
DRColorPickerHighlightLastHue = YES;
// use JPEG2000, not PNG which is the default
// *** WARNING - NEVER CHANGE THIS ONCE YOU RELEASE YOUR APP!!! ***
DRColorPickerUsePNG = NO;
// JPEG2000 quality default is 0.9, which really reduces the file size but still keeps a nice looking image
// *** WARNING - NEVER CHANGE THIS ONCE YOU RELEASE YOUR APP!!! ***
DRColorPickerJPEG2000Quality = 0.9f;
// set to your shared app group to use the same color picker settings with multiple apps and extensions
DRColorPickerSharedAppGroup = nil;
// END OPTIONAL SETUP
// create the color picker
DRColorPickerViewController* vc = [DRColorPickerViewController newColorPickerWithColor:self.color];
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.rootViewController.showAlphaSlider = YES; // default is YES, set to NO to hide the alpha slider
// DRColorPickerHomeViewController *vc = [[DRColorPickerHomeViewController alloc] init];
NSInteger theme = 2; // 0 = default, 1 = dark, 2 = light
// in addition to the default images, you can set the images for a light or dark navigation bar / toolbar theme, these are built-in to the color picker bundle
if (theme == 0)
{
// setting these to nil (the default) tells it to use the built-in default images
vc.rootViewController.addToFavoritesImage = nil;
vc.rootViewController.favoritesImage = nil;
vc.rootViewController.hueImage = nil;
vc.rootViewController.wheelImage = nil;
vc.rootViewController.importImage = nil;
}
else if (theme == 1)
{
vc.rootViewController.addToFavoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-addtofavorites-dark.png");
vc.rootViewController.favoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-favorites-dark.png");
vc.rootViewController.hueImage = DRColorPickerImage(@"images/dark/drcolorpicker-hue-v3-dark.png");
vc.rootViewController.wheelImage = DRColorPickerImage(@"images/dark/drcolorpicker-wheel-dark.png");
vc.rootViewController.importImage = DRColorPickerImage(@"images/dark/drcolorpicker-import-dark.png");
}
else if (theme == 2)
{
vc.rootViewController.addToFavoritesImage = DRColorPickerImage(@"images/light/drcolorpicker-addtofavorites-light.png");
// vc.rootViewController.favoritesImage = DRColorPickerImage(@"images/light/drcolorpicker-favorites-light.png");
vc.rootViewController.favoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-favorites-dark.png");
// vc.rootViewController.hueImage = DRColorPickerImage(@"images/light/drcolorpicker-hue-v3-light.png");
vc.rootViewController.hueImage = DRColorPickerImage(@"images/dark/drcolorpicker-hue-v3-dark.png");
vc.rootViewController.wheelImage = DRColorPickerImage(@"images/light/drcolorpicker-wheel-light.png");
// vc.rootViewController.importImage = DRColorPickerImage(@"images/light/drcolorpicker-import-light.png");
}
// assign a weak reference to the color picker, need this for UIImagePickerController delegate
self.colorPickerVC = vc;
// make an import block, this allows using images as colors, this import block uses the UIImagePickerController,
// but in You Doodle for iOS, I have a more complex import that allows importing from many different sources
// *** Leave this as nil to not allowing import of textures ***
vc.rootViewController.importBlock = nil;
// dismiss the color picker
vc.rootViewController.dismissBlock = ^(BOOL cancel)
{
// 如果是点击的Done, 则使用该color
if(!cancel && self.color.rgbColor) {
if(isTextColor) {
[self setSelectedColor:self.color.rgbColor tag:1];
}
else {
[self setSelectedColor:self.color.rgbColor tag:2];
}
}
[self dismissViewControllerAnimated:YES completion:nil];
};
// 选择颜色
// a color was selected, do something with it, but do NOT dismiss the color picker, that happens in the dismissBlock
vc.rootViewController.colorSelectedBlock = ^(DRColorPickerColor* color, DRColorPickerBaseViewController* vc)
{
NSLog(@"select color");
self.color = color;
};
// finally, present the color picker
[self presentViewController:vc animated:YES completion:nil];
// [self.navigationController pushViewController:vc animated:YES];
}
- (void) initColorPicker2:(BOOL)isTextColor
{
DRColorPickerBackgroundColor = [UIColor colorWithWhite:1.0f alpha:1.0f];
// border color of the color thumbnails
DRColorPickerBorderColor = [UIColor colorWithWhite:1.0f alpha:0.1f]; // [UIColor UIColorFromRGBAColorWithRed:238 green:238 blue:238 alpha:1];
DRColorPickerBorderColor = [UIColor UIColorFromRGBAColorWithRed:238 green:238 blue:238 alpha:1];
// font for any labels in the color picker
DRColorPickerFont = [UIFont systemFontOfSize:16.0f];
// font color for labels in the color picker
DRColorPickerLabelColor = [UIColor blackColor];
// END REQUIRED SETUP
// OPTIONAL SETUP....................
// max number of colors in the recent and favorites - default is 200
DRColorPickerStoreMaxColors = 200;
// show a saturation bar in the color wheel view - default is NO
DRColorPickerShowSaturationBar = YES;
// highlight the last hue in the hue view - default is NO
DRColorPickerHighlightLastHue = YES;
// use JPEG2000, not PNG which is the default
// *** WARNING - NEVER CHANGE THIS ONCE YOU RELEASE YOUR APP!!! ***
DRColorPickerUsePNG = NO;
// JPEG2000 quality default is 0.9, which really reduces the file size but still keeps a nice looking image
// *** WARNING - NEVER CHANGE THIS ONCE YOU RELEASE YOUR APP!!! ***
DRColorPickerJPEG2000Quality = 0.9f;
// set to your shared app group to use the same color picker settings with multiple apps and extensions
DRColorPickerSharedAppGroup = nil;
// END OPTIONAL SETUP
// create the color picker
DRColorPickerHomeViewController *vc = [[DRColorPickerHomeViewController alloc] init];
vc.showAlphaSlider = YES; // default is YES, set to NO to hide the alpha slider
NSInteger theme = 2; // 0 = default, 1 = dark, 2 = light
// in addition to the default images, you can set the images for a light or dark navigation bar / toolbar theme, these are built-in to the color picker bundle
if (theme == 0)
{
// setting these to nil (the default) tells it to use the built-in default images
vc.addToFavoritesImage = nil;
vc.favoritesImage = nil;
vc.hueImage = nil;
vc.wheelImage = nil;
vc.importImage = nil;
}
else if (theme == 1)
{
vc.addToFavoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-addtofavorites-dark.png");
vc.favoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-favorites-dark.png");
vc.hueImage = DRColorPickerImage(@"images/dark/drcolorpicker-hue-v3-dark.png");
vc.wheelImage = DRColorPickerImage(@"images/dark/drcolorpicker-wheel-dark.png");
vc.importImage = DRColorPickerImage(@"images/dark/drcolorpicker-import-dark.png");
}
else if (theme == 2)
{
vc.addToFavoritesImage = DRColorPickerImage(@"images/light/drcolorpicker-addtofavorites-light.png");
// vc.rootViewController.favoritesImage = DRColorPickerImage(@"images/light/drcolorpicker-favorites-light.png");
vc.favoritesImage = DRColorPickerImage(@"images/dark/drcolorpicker-favorites-dark.png");
// vc.rootViewController.hueImage = DRColorPickerImage(@"images/light/drcolorpicker-hue-v3-light.png");
vc.hueImage = DRColorPickerImage(@"images/dark/drcolorpicker-hue-v3-dark.png");
vc.wheelImage = DRColorPickerImage(@"images/light/drcolorpicker-wheel-light.png");
// vc.rootViewController.importImage = DRColorPickerImage(@"images/light/drcolorpicker-import-light.png");
}
// assign a weak reference to the color picker, need this for UIImagePickerController delegate
// self.colorPickerVC = vc;
// make an import block, this allows using images as colors, this import block uses the UIImagePickerController,
// but in You Doodle for iOS, I have a more complex import that allows importing from many different sources
// *** Leave this as nil to not allowing import of textures ***
vc.importBlock = nil;
// dismiss the color picker
vc.dismissBlock = ^(BOOL cancel)
{
// 如果是点击的Done, 则使用该color
if(!cancel && self.color.rgbColor) {
if(isTextColor) {
[self setSelectedColor:self.color.rgbColor tag:1];
}
else {
[self setSelectedColor:self.color.rgbColor tag:2];
}
}
[self.navigationController popViewControllerAnimated:YES];
// [self dismissViewControllerAnimated:YES completion:nil];
};
// 选择颜色
// a color was selected, do something with it, but do NOT dismiss the color picker, that happens in the dismissBlock
vc.colorSelectedBlock = ^(DRColorPickerColor* color, DRColorPickerBaseViewController* vc)
{
NSLog(@"select color");
self.color = color;
};
// finally, present the color picker
// [self presentViewController:vc animated:YES completion:nil];
[self.navigationController pushViewController:vc animated:YES];
}
- (void)setSelectedColor:(UIColor*)color tag:(int)tag
{
[self.editorView setSelectedColor:color tag:tag];
}
- (void)undo:(ZSSBarButtonItem *)barButtonItem
{
[self.editorView undo];
}
- (void)redo:(ZSSBarButtonItem *)barButtonItem
{
[self.editorView redo];
}
- (void)linkBarButtonTapped:(WPEditorToolbarButton*)button
{
if ([self.editorView isSelectionALink]) {
[self removeLink];
} else {
[self showInsertLinkDialogWithLink:self.editorView.selectedLinkURL
title:[self.editorView selectedText]];
// [WPAnalytics track:WPAnalyticsStatEditorTappedLink];
}
}
- (void)showInsertLinkDialogWithLink:(NSString*)url
title:(NSString*)title
{
BOOL isInsertingNewLink = (url == nil);
if (!url) {
NSURL* pasteboardUrl = [self urlFromPasteboard];
url = [pasteboardUrl absoluteString];
}
NSString *insertButtonTitle = isInsertingNewLink ? NSLocalizedString(@"Insert", nil) : NSLocalizedString(@"Update", nil);
NSString *removeButtonTitle = isInsertingNewLink ? nil : NSLocalizedString(@"Remove Link", nil);
self.alertView = [[UIAlertView alloc] initWithTitle:insertButtonTitle
message:nil
delegate:self
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
otherButtonTitles:insertButtonTitle, removeButtonTitle, nil];
// The reason why we're setting a login & password style, is that it's the only style that
// supports having two edit fields. We'll customize the password field to behave as we want.
//
self.alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
self.alertView.tag = WPLinkAlertViewTag;
UITextField *linkURL = [self.alertView textFieldAtIndex:0];
linkURL.clearButtonMode = UITextFieldViewModeAlways;
linkURL.placeholder = NSLocalizedString(@"URL", nil);
if (url) {
linkURL.text = url;
}
UITextField *linkNameTextField = [self.alertView textFieldAtIndex:1];
linkNameTextField.clearButtonMode = UITextFieldViewModeAlways;
linkNameTextField.placeholder = NSLocalizedString(@"Link Name", nil);
linkNameTextField.secureTextEntry = NO;
linkNameTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
linkNameTextField.autocorrectionType = UITextAutocorrectionTypeDefault;
linkNameTextField.spellCheckingType = UITextSpellCheckingTypeDefault;
if (title) {
linkNameTextField.text = title;
}
__weak __typeof(self) weakSelf = self;
self.alertView.willPresentBlock = ^(UIAlertView* alertView) {
// 先保存selection
[weakSelf.editorView saveSelection];
[weakSelf.editorView endEditing];
};
self.alertView.didDismissBlock = ^(UIAlertView *alertView, NSInteger buttonIndex) {
// 这里, restoreSelection
[weakSelf.editorView restoreSelection];
if (alertView.tag == WPLinkAlertViewTag) {
if (buttonIndex == 1) {
NSString *linkURL = [alertView textFieldAtIndex:0].text;
NSString *linkTitle = [alertView textFieldAtIndex:1].text;
if ([linkTitle length] == 0) {
linkTitle = linkURL;
}
if (isInsertingNewLink) {
[weakSelf insertLink:linkURL title:linkTitle];
} else {
[weakSelf updateLink:linkURL title:linkTitle];
}
} else if (buttonIndex == 2) {
[weakSelf removeLink];
}
}
};
self.alertView.shouldEnableFirstOtherButtonBlock = ^BOOL(UIAlertView *alertView) {
if (alertView.tag == WPLinkAlertViewTag) {
UITextField *textField = [alertView textFieldAtIndex:0];
if ([textField.text length] == 0) {
return NO;
}
}
return YES;
};
[self.alertView show];
}
- (void)insertLink:(NSString *)url
title:(NSString*)title
{
[self.editorView insertLink:url title:title];
}
- (void)updateLink:(NSString *)url
title:(NSString*)title
{
[self.editorView updateLink:url title:title];
}
- (void)dismissAlertView
{
[self.alertView dismissWithClickedButtonIndex:self.alertView.cancelButtonIndex animated:YES];
}
- (void)removeLink
{
[self.editorView removeLink];
[WPAnalytics track:WPAnalyticsStatEditorTappedUnlink];
}
- (void)quickLink
{
[self.editorView quickLink];
}
- (void)insertImage:(NSString *)url alt:(NSString *)alt
{
[self.editorView insertImage:url alt:alt];
}
- (void)updateImage:(NSString *)url alt:(NSString *)alt
{
[self.editorView updateImage:url alt:alt];
}
#pragma mark - UIPasteboard interaction
/**
* @brief Returns an URL from the general pasteboard.
*
* @param The URL or nil if no valid URL is found.
*/
- (NSURL*)urlFromPasteboard
{
NSURL* url = nil;
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
NSString* const kURLPasteboardType = (__bridge NSString*)kUTTypeURL;
NSString* const kTextPasteboardType = (__bridge NSString*)kUTTypeText;
if ([pasteboard containsPasteboardTypes:@[kURLPasteboardType]]) {
url = [pasteboard valueForPasteboardType:kURLPasteboardType];
} else if ([pasteboard containsPasteboardTypes:@[kTextPasteboardType]]) {
NSString* urlString = [pasteboard valueForPasteboardType:kTextPasteboardType];
url = [self urlFromStringOnlyIfValid:urlString];
}
return url;
}
/**
* @brief Validates a URL.
* @details The validations we perform here are pretty basic. But the idea of having this
* method is to add any additional checks we want to perform, as we come up with them.
*
* @parameter url The URL to validate. You will usually call [NSURL URLWithString] to create
* this URL from a string, before passing it to this method. Cannot be nil.
*/
- (BOOL)isURLValid:(NSURL*)url
{
NSParameterAssert([url isKindOfClass:[NSURL class]]);
return url && url.scheme && url.host;
}
/**
* @brief Returns the url from a string only if the final URL is valid.
*
* @param urlString The url string to normalize. Cannot be nil.
*
* @returns The normalized URL.
*/
- (NSURL*)urlFromStringOnlyIfValid:(NSString*)urlString
{
NSParameterAssert([urlString isKindOfClass:[NSString class]]);
if ([urlString hasPrefix:@"www"]) {
urlString = [self.editorView normalizeURL:urlString];
}
NSURL* prevalidatedUrl = [NSURL URLWithString:urlString];
NSURL* url = nil;
if (prevalidatedUrl && [self isURLValid:prevalidatedUrl]) {
url = prevalidatedUrl;
}
return url;
}
// WPEditorView.h定义的协议
#pragma mark - WPEditorViewDelegate
- (void)editorTextDidChange:(WPEditorView*)editorView
{
if ([self.delegate respondsToSelector: @selector(editorTextDidChange:)]) {
[self.delegate editorTextDidChange:self];
}
}
- (void)editorTitleDidChange:(WPEditorView *)editorView
{
if ([self.delegate respondsToSelector: @selector(editorTitleDidChange:)]) {
[self.delegate editorTitleDidChange:self];
}
}
- (void)editorViewDidFinishLoadingDOM:(WPEditorView*)editorView
{
// DRM: the reason why we're doing is when the DOM finishes loading, instead of when the full
// content finishe loading, is that the content may not finish loading at all when the device is
// offline and the content has remote subcontent (such as pictures).
//
self.didFinishLoadingEditor = YES;
if (self.editing) {
[self startEditing];
} else {
[self.editorView disableEditing];
}
[self tellOurDelegateEditorDidFinishLoadingDOM];
}
- (void)editorView:(WPEditorView*)editorView
fieldCreated:(WPEditorField*)field
{
/*
UITextFields和UITextView有一个inputAccessoryView的属性当你想在键盘上展示一个自定义的view时你就可以设置该属性。你设置的view就会自动和键盘keyboard一起显示了。
需要注意的是你所自定义的view既不应该处在其他的视图层里也不应该成为其他视图的子视图。其实也就是说你所自定义的view只需要赋给属性inputAccessoryView就可以了不要再做其他多余的操作。
*/
if (field == self.editorView.titleField) {
field.inputAccessoryView = self.toolbarView;
[field setRightToLeftTextEnabled:[self isCurrentLanguageDirectionRTL]];
[field setMultiline:NO];
[field setPlaceholderColor:[WPStyleGuide allTAllShadeGrey]];
[field setPlaceholderText:self.titlePlaceholderText];
self.editorView.sourceViewTitleField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.titlePlaceholderText
attributes:@{NSForegroundColorAttributeName: [WPStyleGuide allTAllShadeGrey]}];
} else if (field == self.editorView.contentField) {
field.inputAccessoryView = self.toolbarView;
[field setRightToLeftTextEnabled:[self isCurrentLanguageDirectionRTL]];
[field setMultiline:YES];
[field setPlaceholderText:self.bodyPlaceholderText];
[field setPlaceholderColor:[WPStyleGuide allTAllShadeGrey]];
}
if ([self.delegate respondsToSelector:@selector(editorViewController:fieldCreated:)]) {
[self.delegate editorViewController:self fieldCreated:field];
}
}
// focus field
// enable/disable 工具栏, 都会显示
// WPEditorView调用
- (void)editorView:(WPEditorView*)editorView
fieldFocused:(WPEditorField*)field
{
if (field == self.editorView.titleField) {
[self.toolbarView enableToolbarItems:NO shouldShowSourceButton:YES];
} else if (field == self.editorView.contentField) {
[self.toolbarView enableToolbarItems:YES shouldShowSourceButton:YES];
}
}
- (void)editorView:(WPEditorView*)editorView sourceFieldFocused:(UIView*)view
{
[self.toolbarView enableToolbarItems:NO shouldShowSourceButton:YES];
// Enable the toolbar if the HTML editor has focus
if (view == self.editorView.sourceView) {
[self.toolbarView enableToolbarItems:YES shouldShowSourceButton:YES];
} else {
[self.toolbarView enableToolbarItems:NO shouldShowSourceButton:YES];
}
}
- (BOOL)editorView:(WPEditorView*)editorView
linkTapped:(NSURL *)url
title:(NSString*)title
{
if (self.isEditing) {
[self showInsertLinkDialogWithLink:url.absoluteString
title:title];
}
else {
if ([self.delegate respondsToSelector:@selector(editorViewController:linkTapped:)]) {
[self.delegate editorViewController:self linkTapped:url.absoluteString];
}
}
return YES;
}
// 点击图片
- (void)editorView:(WPEditorView*)editorView
imageTapped:(NSString *)imageId
url:(NSURL *)url
imageMeta:(WPImageMeta *)imageMeta
{
if ([self.delegate respondsToSelector:@selector(editorViewController:imageTapped:url:imageMeta:)]) {
[self.delegate editorViewController:self imageTapped:imageId url:url imageMeta:imageMeta];
}
}
- (BOOL)editorView:(WPEditorView*)editorView
imageTapped:(NSString *)imageId
url:(NSURL *)url
{
if ([self.delegate respondsToSelector:@selector(editorViewController:imageTapped:url:)]) {
[self.delegate editorViewController:self imageTapped:imageId url:url];
}
return YES;
}
- (void)editorView:(WPEditorView*)editorView
videoTapped:(NSString *)videoId
url:(NSURL *)url
{
if ([self.delegate respondsToSelector:@selector(editorViewController:videoTapped:url:)]) {
[self.delegate editorViewController:self videoTapped:videoId url:url];
}
}
- (void)editorView:(WPEditorView*)editorView
imageReplaced:(NSString *)imageId
{
if ([self.delegate respondsToSelector:@selector(editorViewController:imageReplaced:)]) {
[self.delegate editorViewController:self imageReplaced:imageId];
}
}
- (void)editorView:(WPEditorView*)editorView
videoReplaced:(NSString *)videoId
{
if ([self.delegate respondsToSelector:@selector(editorViewController:videoReplaced:)]) {
[self.delegate editorViewController:self videoReplaced:videoId];
}
}
- (void)editorView:(WPEditorView *)editorView videoPressInfoRequest:(NSString *)videoPressID
{
if ([self.delegate respondsToSelector:@selector(editorViewController:videoPressInfoRequest:)]) {
[self.delegate editorViewController:self videoPressInfoRequest:videoPressID];
}
}
- (void)editorView:(WPEditorView *)editorView mediaRemoved:(NSString *)mediaID
{
if ([self.delegate respondsToSelector:@selector(editorViewController:mediaRemoved:)]) {
[self.delegate editorViewController:self mediaRemoved:mediaID];
}
}
- (void)editorView:(WPEditorView*)editorView stylesForCurrentSelection:(NSArray*)styles
{
self.editorItemsEnabled = styles;
[self.toolbarView selectToolbarItemsForStyles:styles];
}
#ifdef DEBUG
- (void)webView:(UIWebView *)webView
didFailLoadWithError:(NSError *)error
{
DDLogError(@"Loading error: %@", error);
NSAssert(NO,
@"This should never happen since the editor is a local HTML page of our own making.");
}
#endif
#pragma mark - Asset Picker
- (void)showInsertURLAlternatePicker
{
// Blank method. User should implement this in their subclass
NSAssert(NO, @"Blank method. User should implement this in their subclass");
}
- (void)showInsertImageAlternatePicker
{
// Blank method. User should implement this in their subclass
NSAssert(NO, @"Blank method. User should implement this in their subclass");
}
#pragma mark - Utilities
- (UIColor *)barButtonItemDefaultColor
{
if (self.toolbarView.itemTintColor) {
return self.toolbarView.itemTintColor;
}
return [WPStyleGuide allTAllShadeGrey];
}
- (UIColor *)barButtonItemSelectedDefaultColor
{
if (self.toolbarView.selectedItemTintColor) {
return self.toolbarView.selectedItemTintColor;
}
return [WPStyleGuide wordPressBlue];
}
- (BOOL)isCurrentLanguageDirectionRTL
{
return ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft);
}
#pragma mark - Delegate calls
- (void)tellOurDelegateEditingDidBegin
{
NSAssert(self.isEditing,
@"Can't call this delegate method if not editing.");
if ([self.delegate respondsToSelector: @selector(editorDidBeginEditing:)]) {
[self.delegate editorDidBeginEditing:self];
}
}
- (void)tellOurDelegateEditingDidEnd
{
NSAssert(!self.isEditing,
@"Can't call this delegate method if editing.");
if ([self.delegate respondsToSelector: @selector(editorDidEndEditing:)]) {
[self.delegate editorDidEndEditing:self];
}
}
- (void)tellOurDelegateEditorDidFinishLoadingDOM
{
if ([self.delegate respondsToSelector:@selector(editorDidFinishLoadingDOM:)]) {
[self.delegate editorDidFinishLoadingDOM:self];
}
}
- (BOOL)askOurDelegateShouldDisplaySourceView
{
if ([self.delegate respondsToSelector:@selector(editorShouldDisplaySourceView:)]) {
return [self.delegate editorShouldDisplaySourceView:self];
}
return YES;
}
@end