1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "chrome/browser/ui/cocoa/bookmarks/bookmark_editor_controller.h" 6 7#include "base/prefs/pref_service.h" 8#include "base/strings/string16.h" 9#include "base/strings/sys_string_conversions.h" 10#include "chrome/browser/profiles/profile.h" 11#include "chrome/browser/ui/bookmarks/bookmark_utils.h" 12#include "components/bookmarks/browser/bookmark_expanded_state_tracker.h" 13#include "components/bookmarks/browser/bookmark_model.h" 14#include "components/url_fixer/url_fixer.h" 15#include "components/user_prefs/user_prefs.h" 16 17using bookmarks::BookmarkExpandedStateTracker; 18 19@interface BookmarkEditorController (Private) 20 21// Grab the url from the text field and convert. 22- (GURL)GURLFromUrlField; 23 24@end 25 26@implementation BookmarkEditorController 27 28@synthesize displayURL = displayURL_; 29 30+ (NSSet*)keyPathsForValuesAffectingOkEnabled { 31 return [NSSet setWithObject:@"displayURL"]; 32} 33 34- (id)initWithParentWindow:(NSWindow*)parentWindow 35 profile:(Profile*)profile 36 parent:(const BookmarkNode*)parent 37 node:(const BookmarkNode*)node 38 url:(const GURL&)url 39 title:(const base::string16&)title 40 configuration:(BookmarkEditor::Configuration)configuration { 41 if ((self = [super initWithParentWindow:parentWindow 42 nibName:@"BookmarkEditor" 43 profile:profile 44 parent:parent 45 url:url 46 title:title 47 configuration:configuration])) { 48 // "Add Page..." has no "node" so this may be NULL. 49 node_ = node; 50 } 51 return self; 52} 53 54- (void)dealloc { 55 [displayURL_ release]; 56 [super dealloc]; 57} 58 59- (void)awakeFromNib { 60 // Check if NSTextFieldCell supports the method. This check is in place as 61 // only 10.6 and greater support the setUsesSingleLineMode method. 62 // TODO(kushi.p): Remove this when the project hits a 10.6+ only state. 63 NSTextFieldCell* nameFieldCell_ = [nameTextField_ cell]; 64 if ([nameFieldCell_ 65 respondsToSelector:@selector(setUsesSingleLineMode:)]) { 66 [nameFieldCell_ setUsesSingleLineMode:YES]; 67 } 68 69 // Set text fields to match our bookmark. If the node is NULL we 70 // arrived here from an "Add Page..." item in a context menu. 71 if (node_) { 72 [self setInitialName:base::SysUTF16ToNSString(node_->GetTitle())]; 73 PrefService* prefs = [self profile] ? 74 user_prefs::UserPrefs::Get([self profile]) : 75 NULL; 76 base::string16 urlString = 77 chrome::FormatBookmarkURLForDisplay(node_->url(), prefs); 78 initialUrl_.reset([base::SysUTF16ToNSString(urlString) retain]); 79 } else { 80 GURL url = [self url]; 81 [self setInitialName:base::SysUTF16ToNSString([self title])]; 82 if (url.is_valid()) 83 initialUrl_.reset([[NSString stringWithUTF8String:url.spec().c_str()] 84 retain]); 85 } 86 [self setDisplayURL:initialUrl_]; 87 [super awakeFromNib]; 88 [self expandNodes: 89 [self bookmarkModel]->expanded_state_tracker()->GetExpandedNodes()]; 90} 91 92- (void)nodeRemoved:(const BookmarkNode*)node 93 fromParent:(const BookmarkNode*)parent 94{ 95 // Be conservative; it is needed (e.g. "Add Page...") 96 node_ = NULL; 97 [self cancel:self]; 98} 99 100#pragma mark Bookmark Editing 101 102// If possible, return a valid GURL from the URL text field. 103- (GURL)GURLFromUrlField { 104 NSString* url = [self displayURL]; 105 return url_fixer::FixupURL([url UTF8String], std::string()); 106} 107 108// Enable the OK button if there is a valid URL. 109- (BOOL)okEnabled { 110 BOOL okEnabled = NO; 111 if ([[self displayURL] length]) { 112 GURL newURL = [self GURLFromUrlField]; 113 okEnabled = (newURL.is_valid()) ? YES : NO; 114 } 115 if (okEnabled) 116 [urlField_ setBackgroundColor:[NSColor whiteColor]]; 117 else 118 [urlField_ setBackgroundColor:[NSColor colorWithCalibratedRed:1.0 119 green:0.67 120 blue:0.67 121 alpha:1.0]]; 122 return okEnabled; 123} 124 125// The bookmark's URL is assumed to be valid (otherwise the OK button 126// should not be enabled). Previously existing bookmarks for which the 127// parent has not changed are updated in-place. Those for which the parent 128// has changed are removed with a new node created under the new parent. 129// Called by -[BookmarkEditorBaseController ok:]. 130- (NSNumber*)didCommit { 131 NSString* name = [[self displayName] stringByTrimmingCharactersInSet: 132 [NSCharacterSet newlineCharacterSet]]; 133 base::string16 newTitle = base::SysNSStringToUTF16(name); 134 const BookmarkNode* newParentNode = [self selectedNode]; 135 GURL newURL = [self GURLFromUrlField]; 136 if (!newURL.is_valid()) { 137 // Shouldn't be reached -- OK button should be disabled if not valid! 138 NOTREACHED(); 139 return [NSNumber numberWithBool:NO]; 140 } 141 142 // Determine where the new/replacement bookmark is to go. 143 BookmarkModel* model = [self bookmarkModel]; 144 // If there was an old node then we update the node, and move it to its new 145 // parent if the parent has changed (rather than deleting it from the old 146 // parent and adding to the new -- which also prevents the 'poofing' that 147 // occurs when a node is deleted). 148 if (node_) { 149 model->SetURL(node_, newURL); 150 model->SetTitle(node_, newTitle); 151 const BookmarkNode* oldParentNode = [self parentNode]; 152 if (newParentNode != oldParentNode) 153 model->Move(node_, newParentNode, newParentNode->child_count()); 154 } else { 155 // Otherwise, add a new bookmark at the end of the newly selected folder. 156 model->AddURL(newParentNode, newParentNode->child_count(), newTitle, 157 newURL); 158 } 159 160 // Update the expanded state. 161 BookmarkExpandedStateTracker::Nodes expanded_nodes = [self getExpandedNodes]; 162 [self bookmarkModel]->expanded_state_tracker()-> 163 SetExpandedNodes(expanded_nodes); 164 return [NSNumber numberWithBool:YES]; 165} 166 167- (NSColor *)urlFieldColor { 168 return [urlField_ backgroundColor]; 169} 170 171@end // BookmarkEditorController 172 173