Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: chrome/browser/ui/cocoa/website_settings_bubble_controller.mm

Issue 10827029: [Mac] Website settings: Implement custom tab appearance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove images (submitted in separate CL). Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/website_settings_bubble_controller.h" 5 #import "chrome/browser/ui/cocoa/website_settings_bubble_controller.h"
6 6
7 #include "base/sys_string_conversions.h" 7 #include "base/sys_string_conversions.h"
8 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 8 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
9 #import "chrome/browser/ui/cocoa/info_bubble_view.h" 9 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
10 #import "chrome/browser/ui/cocoa/info_bubble_window.h" 10 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
11 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" 11 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
12 #include "chrome/browser/ui/tab_contents/tab_contents.h" 12 #include "chrome/browser/ui/tab_contents/tab_contents.h"
13 #include "content/public/browser/cert_store.h" 13 #include "content/public/browser/cert_store.h"
14 #include "grit/generated_resources.h" 14 #include "grit/generated_resources.h"
15 #include "grit/theme_resources.h"
15 #include "grit/ui_resources.h" 16 #include "grit/ui_resources.h"
16 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" 17 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
17 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/base/resource/resource_bundle.h"
19 20
20 namespace { 21 namespace {
21 22
22 // The width of the window, in view coordinates. The height will be determined 23 // The width of the window, in view coordinates. The height will be determined
23 // by the content. 24 // by the content.
24 const CGFloat kWindowWidth = 380; 25 const CGFloat kWindowWidth = 380;
(...skipping 21 matching lines...) Expand all
46 // Width of the text fields. 47 // Width of the text fields.
47 const CGFloat kTextWidth = kWindowWidth - (kImageSize + kImageSpacing + 48 const CGFloat kTextWidth = kWindowWidth - (kImageSize + kImageSpacing +
48 kFramePadding * 2); 49 kFramePadding * 2);
49 50
50 // The amount of padding given to tab view contents. 51 // The amount of padding given to tab view contents.
51 const CGFloat kTabViewContentsPadding = kFramePadding; 52 const CGFloat kTabViewContentsPadding = kFramePadding;
52 53
53 // The spacing between individual items in the Permissions tab. 54 // The spacing between individual items in the Permissions tab.
54 const CGFloat kPermissionsTabSpacing = 8; 55 const CGFloat kPermissionsTabSpacing = 8;
55 56
57 // The extra space to the left of the first tab in the tab strip.
58 const CGFloat kTabStripXPadding = 19;
59
60 // The amount of space between the visual borders of adjacent tabs.
61 const CGFloat kTabSpacing = 4;
62
63 // The extra width outside the hit rect used by the visual borders of the tab.
64 const CGFloat kTabBorderExtraWidth = 16;
65
66 // The height of the clickable area of the tab strip.
67 const CGFloat kTabHeight = 27;
68
69 // The height of the background image for the tab strip.
70 const CGFloat kTabStripHeight = 44;
71
72 // The amount of space above tab labels.
73 const CGFloat kTabLabelTopPadding = 20;
74
75 // The amount of padding to leave on either side of the tab label.
76 const CGFloat kTabLabelXPadding = 12;
77
56 // In the permission changing menu, the order of the menu items (which 78 // In the permission changing menu, the order of the menu items (which
57 // correspond to different content settings). 79 // correspond to different content settings).
58 const ContentSetting kPermissionsMenuSettings[] = { 80 const ContentSetting kPermissionsMenuSettings[] = {
59 CONTENT_SETTING_ALLOW, 81 CONTENT_SETTING_ALLOW,
60 CONTENT_SETTING_BLOCK, 82 CONTENT_SETTING_BLOCK,
61 CONTENT_SETTING_DEFAULT 83 CONTENT_SETTING_DEFAULT
62 }; 84 };
63 85
64 } // namespace 86 } // namespace
65 87
66 // A simple container to hold all the contents of the website settings bubble. 88 // A simple container to hold all the contents of the website settings bubble.
67 // It uses a flipped coordinate system to make text layout easier. 89 // It uses a flipped coordinate system to make text layout easier.
68 @interface WebsiteSettingsContentView : NSView 90 @interface WebsiteSettingsContentView : NSView
69 @end 91 @end
70 @implementation WebsiteSettingsContentView 92 @implementation WebsiteSettingsContentView
71 - (BOOL)isFlipped { 93 - (BOOL)isFlipped {
72 return YES; 94 return YES;
73 } 95 }
74 @end 96 @end
75 97
98 @interface WebsiteSettingsTabSegmentedCell : NSSegmentedCell {
99 @private
100 scoped_nsobject<NSImage> tabBackgroundImage_;
101 scoped_nsobject<NSImage> tabCenterImage_;
102 scoped_nsobject<NSImage> tabLeftImage_;
103 scoped_nsobject<NSImage> tabRightImage_;
104 }
105 @end
106
107 @implementation WebsiteSettingsTabSegmentedCell
108 - (id)init {
109 if ((self = [super init])) {
110 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
111 tabBackgroundImage_.reset(
112 [rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TAB_BACKGROUND) retain]);
113 tabCenterImage_.reset(
114 [rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TAB_CENTER) retain]);
115 tabLeftImage_.reset(
116 [rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TAB_LEFT) retain]);
117 tabRightImage_.reset(
118 [rb.GetNativeImageNamed(IDR_WEBSITE_SETTINGS_TAB_RIGHT) retain]);
119 }
120 return self;
121 }
122
123 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
124 // Draw the tab for the selected segment. The drawing area is slightly
125 // larger than the hit rect for the tab.
126 NSRect tabRect = [self hitRectForSegment:[self selectedSegment]];
127 tabRect.origin.x -= kTabBorderExtraWidth;
128 tabRect.size.width += 2 * kTabBorderExtraWidth;
129
130 tabRect.origin.y = 0;
131 tabRect.size.height = kTabStripHeight;
132
133 NSDrawThreePartImage(tabRect,
134 tabLeftImage_,
135 tabCenterImage_,
136 tabRightImage_,
137 /*vertical=*/ NO,
138 NSCompositeSourceOver,
139 1,
140 /*flipped=*/ YES);
141
142 // Draw the background to the left of the selected tab.
143 NSRect backgroundRect = NSMakeRect(0, 0, NSMinX(tabRect), kTabStripHeight);
144 NSDrawThreePartImage(backgroundRect,
145 nil,
146 tabBackgroundImage_,
147 nil,
148 /*vertical=*/ NO,
149 NSCompositeSourceOver,
150 1,
151 /*flipped=*/ YES);
152
153 // Draw the background to the right of the selected tab.
154 backgroundRect.origin.x = NSMaxX(tabRect);
155 backgroundRect.size.width = kWindowWidth - NSMaxX(tabRect);
156 NSDrawThreePartImage(backgroundRect,
157 nil,
158 tabBackgroundImage_,
159 nil,
160 /*vertical=*/ NO,
161 NSCompositeSourceOver,
162 1,
163 /*flipped=*/ YES);
164
165 // Call the superclass method to trigger drawing of the tab labels.
166 [self drawInteriorWithFrame:cellFrame inView:controlView];
167 }
168
169 // Return the hit rect (i.e., the visual bounds of the tab) for
170 // the given segment.
171 - (NSRect)hitRectForSegment:(NSInteger)segment {
172 NSRect rect = NSMakeRect(0, kTabStripHeight - kTabHeight,
173 [self widthForSegment:segment], kTabHeight);
174 for (NSInteger i = 0; i < segment; ++i) {
175 rect.origin.x += [self widthForSegment:i];
176 }
177 int xAdjust = segment == 0 ? kTabStripXPadding : 0;
178 rect.size.width = [self widthForSegment:segment] - kTabSpacing - xAdjust;
179 rect.origin.x += kTabSpacing / 2 + xAdjust;
180
181 return rect;
182 }
183
184 - (void)drawSegment:(NSInteger)segment
185 inFrame:(NSRect)frame
186 withView:(NSView*)controlView {
187 // Call the superclass to draw the label, adjusting the rectangle so that
188 // the label appears centered in the tab.
189 if (segment == 0) {
190 frame.origin.x += kTabStripXPadding / 2;
191 frame.size.width -= kTabStripXPadding;
192 }
193 frame.origin.y += kTabLabelTopPadding;
194 frame.size.height -= kTabLabelTopPadding;
195 [super drawSegment:segment inFrame:frame withView:controlView];
196 }
197
198 // Overrides the default tracking behavior to only respond to clicks inside the
199 // visual borders of the tab.
200 - (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
201 NSInteger segmentCount = [self segmentCount];
202 for (NSInteger i = 0; i < segmentCount; ++i) {
203 if (NSPointInRect(startPoint, [self hitRectForSegment:i]))
204 return YES;
205 }
206 return NO;
207 }
208
209 // Overrides the default cell height to take up the full height of the
210 // segmented control. Otherwise, cliks on the lower part of a tab will be
211 // ignored.
212 - (NSSize)cellSizeForBounds:(NSRect)aRect {
213 return NSMakeSize([super cellSizeForBounds:aRect].width, NSHeight(aRect));
214 }
215 @end
216
76 @implementation WebsiteSettingsBubbleController 217 @implementation WebsiteSettingsBubbleController
77 218
78 - (id)initWithParentWindow:(NSWindow*)parentWindow 219 - (id)initWithParentWindow:(NSWindow*)parentWindow
79 websiteSettingsUIBridge:(WebsiteSettingsUIBridge*)bridge { 220 websiteSettingsUIBridge:(WebsiteSettingsUIBridge*)bridge {
80 DCHECK(parentWindow); 221 DCHECK(parentWindow);
81 222
82 // Use an arbitrary height; it will be changed in performLayout. 223 // Use an arbitrary height; it will be changed in performLayout.
83 NSRect contentRect = NSMakeRect(0, 0, kWindowWidth, 1); 224 NSRect contentRect = NSMakeRect(0, 0, kWindowWidth, 1);
84 // Create an empty window into which content is placed. 225 // Create an empty window into which content is placed.
85 scoped_nsobject<InfoBubbleWindow> window( 226 scoped_nsobject<InfoBubbleWindow> window(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 267
127 // Create a text field to identity status (e.g. verified, not verified). 268 // Create a text field to identity status (e.g. verified, not verified).
128 identityStatusField_ = [self addText:string16() 269 identityStatusField_ = [self addText:string16()
129 withSize:[NSFont smallSystemFontSize] 270 withSize:[NSFont smallSystemFontSize]
130 bold:NO 271 bold:NO
131 toView:contentView_ 272 toView:contentView_
132 atPoint:controlOrigin]; 273 atPoint:controlOrigin];
133 274
134 // Create the tab view and its two tabs. 275 // Create the tab view and its two tabs.
135 276
277 NSRect initialFrame = NSMakeRect(0, 0, kWindowWidth, kTabStripHeight);
278 segmentedControl_.reset(
279 [[NSSegmentedControl alloc] initWithFrame:initialFrame]);
280 [segmentedControl_ setCell:
281 [[[WebsiteSettingsTabSegmentedCell alloc] init] autorelease]];
282 [segmentedControl_ setSegmentCount:2];
283 [segmentedControl_ setTarget:self];
284 [segmentedControl_ setAction:@selector(tabSelected:)];
285
286 NSFont* smallSystemFont =
287 [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
288 NSDictionary* textAttributes =
289 [NSDictionary dictionaryWithObject:smallSystemFont
290 forKey:NSFontAttributeName];
291
292 // Create the "Permissions" tab.
293 NSString* label = l10n_util::GetNSString(
294 IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS);
295 NSSize textSize = [label sizeWithAttributes:textAttributes];
296 CGFloat tabWidth = textSize.width + 2 * kTabLabelXPadding;
297 [segmentedControl_ setLabel:label forSegment:0];
298 [segmentedControl_ setWidth:tabWidth + kTabStripXPadding forSegment:0];
299
300 // Create the "Connection" tab.
301 label = l10n_util::GetNSString(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION);
302 textSize = [label sizeWithAttributes:textAttributes];
303 [segmentedControl_ setLabel:label forSegment:1];
304
305 // Make both tabs the width of the widest. The first segment has some
306 // additional padding that is not part of the tab, which is used for drawing
307 // the background of the tab strip.
308 tabWidth = std::max(tabWidth,
309 textSize.width + 2 * kTabLabelXPadding);
310 [segmentedControl_ setWidth:tabWidth + kTabStripXPadding forSegment:0];
311 [segmentedControl_ setWidth:tabWidth forSegment:1];
312
313 [segmentedControl_ setFont:smallSystemFont];
314 [segmentedControl_ setSelectedSegment:0];
315 [contentView_ addSubview:segmentedControl_];
316
136 NSRect tabFrame = NSMakeRect(0, 0, kWindowWidth, 300); 317 NSRect tabFrame = NSMakeRect(0, 0, kWindowWidth, 300);
137 tabView_.reset([[NSTabView alloc] initWithFrame:tabFrame]); 318 tabView_.reset([[NSTabView alloc] initWithFrame:tabFrame]);
138 [tabView_ setTabViewType:NSTopTabsBezelBorder]; 319 [tabView_ setTabViewType:NSNoTabsNoBorder];
320 [tabView_ setDrawsBackground:NO];
139 [tabView_ setControlSize:NSSmallControlSize]; 321 [tabView_ setControlSize:NSSmallControlSize];
140 [tabView_ setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
141 [contentView_ addSubview:tabView_.get()]; 322 [contentView_ addSubview:tabView_.get()];
142 323
143 permissionsContentView_ = [self addPermissionsTabToTabView:tabView_]; 324 permissionsContentView_ = [self addPermissionsTabToTabView:tabView_];
144 [self addConnectionTabToTabView:tabView_]; 325 [self addConnectionTabToTabView:tabView_];
145 326
146 // Replace the window's content. 327 // Replace the window's content.
147 [[[self window] contentView] setSubviews: 328 [[[self window] contentView] setSubviews:
148 [NSArray arrayWithObject:contentView_.get()]]; 329 [NSArray arrayWithObject:contentView_.get()]];
149 330
150 [self performLayout]; 331 [self performLayout];
151 } 332 }
152 333
153 // Create the contents of the Permissions tab and add it to the given tab view. 334 // Create the contents of the Permissions tab and add it to the given tab view.
154 // Returns a weak reference to the tab view item's view. 335 // Returns a weak reference to the tab view item's view.
155 - (NSView*)addPermissionsTabToTabView:(NSTabView*)tabView { 336 - (NSView*)addPermissionsTabToTabView:(NSTabView*)tabView {
156 scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]); 337 scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
157 [item setLabel:
158 l10n_util::GetNSString(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS)];
159 [tabView_ addTabViewItem:item.get()]; 338 [tabView_ addTabViewItem:item.get()];
160 scoped_nsobject<NSView> contentView([[WebsiteSettingsContentView alloc] 339 scoped_nsobject<NSView> contentView([[WebsiteSettingsContentView alloc]
161 initWithFrame:[tabView_ contentRect]]); 340 initWithFrame:[tabView_ contentRect]]);
162 [item setView:contentView.get()]; 341 [item setView:contentView.get()];
163 return contentView.get(); 342 return contentView.get();
164 } 343 }
165 344
166 // Create the contents of the Connection tab and add it to the given tab view. 345 // Create the contents of the Connection tab and add it to the given tab view.
167 // Returns a weak reference to the tab view item's view. 346 // Returns a weak reference to the tab view item's view.
168 - (NSView*)addConnectionTabToTabView:(NSTabView*)tabView { 347 - (NSView*)addConnectionTabToTabView:(NSTabView*)tabView {
169 scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]); 348 scoped_nsobject<NSTabViewItem> item([[NSTabViewItem alloc] init]);
170 [item setLabel:
171 l10n_util::GetNSString(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION)];
172
173 scoped_nsobject<NSView> contentView([[WebsiteSettingsContentView alloc] 349 scoped_nsobject<NSView> contentView([[WebsiteSettingsContentView alloc]
174 initWithFrame:[tabView_ contentRect]]); 350 initWithFrame:[tabView_ contentRect]]);
175 351
176 // Place all the text at the same position. It will be adjusted in 352 // Place all the text at the same position. It will be adjusted in
177 // performLayout. 353 // performLayout.
178 NSPoint textPosition = NSMakePoint( 354 NSPoint textPosition = NSMakePoint(
179 kTabViewContentsPadding + kImageSize + kImageSpacing, 355 kTabViewContentsPadding + kImageSize + kImageSpacing,
180 kTabViewContentsPadding); 356 kTabViewContentsPadding);
181 357
182 identityStatusIcon_ = 358 identityStatusIcon_ =
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 436
261 // Lay out the last visit section. 437 // Lay out the last visit section.
262 [self setYPositionOfView:firstVisitIcon_ to:yPos]; 438 [self setYPositionOfView:firstVisitIcon_ to:yPos];
263 [self sizeTextFieldHeightToFit:firstVisitHeaderField_]; 439 [self sizeTextFieldHeightToFit:firstVisitHeaderField_];
264 yPos = [self setYPositionOfView:firstVisitHeaderField_ to:yPos]; 440 yPos = [self setYPositionOfView:firstVisitHeaderField_ to:yPos];
265 yPos += kHeadlineSpacing; 441 yPos += kHeadlineSpacing;
266 [self sizeTextFieldHeightToFit:firstVisitDescriptionField_]; 442 [self sizeTextFieldHeightToFit:firstVisitDescriptionField_];
267 [self setYPositionOfView:firstVisitDescriptionField_ to:yPos]; 443 [self setYPositionOfView:firstVisitDescriptionField_ to:yPos];
268 444
269 // Adjust the tab view size and place it below the identity status. 445 // Adjust the tab view size and place it below the identity status.
446
447 NSRect segmentedControlFrame = [segmentedControl_ frame];
448 segmentedControlFrame.origin.y =
449 NSMaxY([identityStatusField_ frame]);
450 [segmentedControl_ setFrame:segmentedControlFrame];
451
270 NSRect tabViewFrame = [tabView_ frame]; 452 NSRect tabViewFrame = [tabView_ frame];
271 tabViewFrame.origin.y = 453 tabViewFrame.origin.y = NSMaxY(segmentedControlFrame);
272 NSMaxY([identityStatusField_ frame]) + kVerticalSpacing;
273 454
274 CGFloat connectionTabHeight = std::max( 455 CGFloat connectionTabHeight = std::max(
275 NSMaxY([firstVisitDescriptionField_ frame]), 456 NSMaxY([firstVisitDescriptionField_ frame]),
276 NSMaxY([firstVisitIcon_ frame ])); 457 NSMaxY([firstVisitIcon_ frame ]));
277 connectionTabHeight += kVerticalSpacing; 458 connectionTabHeight += kVerticalSpacing;
278 459
279 CGFloat tabContentHeight = std::max(connectionTabHeight, 460 CGFloat tabContentHeight = std::max(connectionTabHeight,
280 permissionsTabHeight_); 461 permissionsTabHeight_);
281 tabViewFrame.size.height = tabContentHeight + 462 tabViewFrame.size.height = tabContentHeight +
282 NSHeight(tabViewFrame) - NSHeight([tabView_ contentRect]); 463 NSHeight(tabViewFrame) - NSHeight([tabView_ contentRect]);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 643
463 [button setAction:@selector(permissionValueChanged:)]; 644 [button setAction:@selector(permissionValueChanged:)];
464 [button setTarget:self]; 645 [button setTarget:self];
465 646
466 [self setTitleOfButton:button]; 647 [self setTitleOfButton:button];
467 648
468 [view addSubview:button.get()]; 649 [view addSubview:button.get()];
469 return button.get(); 650 return button.get();
470 } 651 }
471 652
653 - (void)tabSelected:(id)sender {
654 [tabView_ selectTabViewItemAtIndex:[segmentedControl_ selectedSegment]];
655 }
656
472 // Handler for the permission-changing menus. 657 // Handler for the permission-changing menus.
473 - (void)permissionValueChanged:(id)sender { 658 - (void)permissionValueChanged:(id)sender {
474 DCHECK([sender isKindOfClass:[NSPopUpButton class]]); 659 DCHECK([sender isKindOfClass:[NSPopUpButton class]]);
475 NSPopUpButton* button = static_cast<NSPopUpButton*>(sender); 660 NSPopUpButton* button = static_cast<NSPopUpButton*>(sender);
476 ContentSettingsType type = static_cast<ContentSettingsType>([button tag]); 661 ContentSettingsType type = static_cast<ContentSettingsType>([button tag]);
477 ContentSetting newSetting = [self contentSettingForButton:button]; 662 ContentSetting newSetting = [self contentSettingForButton:button];
478 663
479 [self setTitleOfButton:button]; 664 [self setTitleOfButton:button];
480 if (presenter_.get()) 665 if (presenter_.get())
481 presenter_->OnSitePermissionChanged(type, newSetting); 666 presenter_->OnSitePermissionChanged(type, newSetting);
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 } 796 }
612 797
613 void WebsiteSettingsUIBridge::SetIdentityInfo( 798 void WebsiteSettingsUIBridge::SetIdentityInfo(
614 const WebsiteSettingsUI::IdentityInfo& identity_info) { 799 const WebsiteSettingsUI::IdentityInfo& identity_info) {
615 [bubble_controller_ setIdentityInfo:identity_info]; 800 [bubble_controller_ setIdentityInfo:identity_info];
616 } 801 }
617 802
618 void WebsiteSettingsUIBridge::SetFirstVisit(const string16& first_visit) { 803 void WebsiteSettingsUIBridge::SetFirstVisit(const string16& first_visit) {
619 [bubble_controller_ setFirstVisit:first_visit]; 804 [bubble_controller_ setFirstVisit:first_visit];
620 } 805 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698