OLD | NEW |
---|---|
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/web_intent_sheet_controller.h" | 5 #import "chrome/browser/ui/cocoa/web_intent_sheet_controller.h" |
6 | 6 |
7 #include "base/memory/scoped_nsobject.h" | 7 #include "base/memory/scoped_nsobject.h" |
8 #include "base/sys_string_conversions.h" | 8 #include "base/sys_string_conversions.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/ui/browser_list.h" | 10 #include "chrome/browser/ui/browser_list.h" |
(...skipping 17 matching lines...) Expand all Loading... | |
28 #include "ui/base/l10n/l10n_util.h" | 28 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/base/l10n/l10n_util_mac.h" | 29 #include "ui/base/l10n/l10n_util_mac.h" |
30 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
31 #include "ui/base/text/text_elider.h" | 31 #include "ui/base/text/text_elider.h" |
32 #include "ui/gfx/font.h" | 32 #include "ui/gfx/font.h" |
33 #include "ui/gfx/image/image.h" | 33 #include "ui/gfx/image/image.h" |
34 | 34 |
35 using content::OpenURLParams; | 35 using content::OpenURLParams; |
36 using content::Referrer; | 36 using content::Referrer; |
37 | 37 |
38 @interface CustomLinkButtonCell : HyperlinkButtonCell | |
39 @end | |
40 | |
38 namespace { | 41 namespace { |
39 | 42 |
40 // The width of a service button, in view coordinates. | 43 // The width of a service button, in view coordinates. |
41 const CGFloat kServiceButtonWidth = 300; | 44 const CGFloat kServiceButtonWidth = 300; |
42 | 45 |
43 // Spacing in between sections. | 46 // Spacing in between sections. |
44 const CGFloat kVerticalSpacing = 18; | 47 const CGFloat kVerticalSpacing = 18; |
45 | 48 |
46 // Square size of the close button. | 49 // Square size of the close button. |
47 const CGFloat kCloseButtonSize = 16; | 50 const CGFloat kCloseButtonSize = 16; |
48 | 51 |
49 // Font size for picker header. | |
50 const CGFloat kHeaderFontSize = 14.5; | |
51 | |
52 // Width of the text fields. | 52 // Width of the text fields. |
53 const CGFloat kTextWidth = WebIntentPicker::kWindowWidth - | 53 const CGFloat kTextWidth = WebIntentPicker::kWindowWidth - |
54 (WebIntentPicker::kContentAreaBorder * 2.0 + kCloseButtonSize); | 54 (WebIntentPicker::kContentAreaBorder * 2.0 + kCloseButtonSize); |
55 | 55 |
56 // Maximum number of intents (suggested and installed) displayed. | 56 // Maximum number of intents (suggested and installed) displayed. |
57 const int kMaxIntentRows = 4; | 57 const int kMaxIntentRows = 4; |
58 | 58 |
59 // Sets properties on the given |field| to act as title or description labels. | 59 // Sets properties on the given |field| to act as title or description labels. |
60 void ConfigureTextFieldAsLabel(NSTextField* field) { | 60 void ConfigureTextFieldAsLabel(NSTextField* field) { |
61 [field setEditable:NO]; | 61 [field setEditable:NO]; |
62 [field setSelectable:YES]; | 62 [field setSelectable:YES]; |
63 [field setDrawsBackground:NO]; | 63 [field setDrawsBackground:NO]; |
64 [field setBezeled:NO]; | 64 [field setBezeled:NO]; |
65 } | 65 } |
66 | 66 |
67 NSButton* CreateHyperlinkButton(NSString* title, const NSRect& frame) { | 67 NSButton* CreateHyperlinkButton(NSString* title, const NSRect& frame) { |
68 NSButton* button = [[NSButton alloc] initWithFrame:frame]; | 68 NSButton* button = [[NSButton alloc] initWithFrame:frame]; |
69 scoped_nsobject<HyperlinkButtonCell> cell( | 69 scoped_nsobject<CustomLinkButtonCell> cell( |
70 [[HyperlinkButtonCell alloc] initTextCell:title]); | 70 [[CustomLinkButtonCell alloc] initTextCell:title]); |
71 [cell setControlSize:NSSmallControlSize]; | 71 [cell setControlSize:NSSmallControlSize]; |
72 [button setCell:cell.get()]; | 72 [button setCell:cell.get()]; |
73 [button setButtonType:NSMomentaryPushInButton]; | 73 [button setButtonType:NSMomentaryPushInButton]; |
74 [button setBezelStyle:NSRegularSquareBezelStyle]; | 74 [button setBezelStyle:NSRegularSquareBezelStyle]; |
75 | 75 |
76 return button; | 76 return button; |
77 } | 77 } |
78 | 78 |
79 } // namespace | 79 } // namespace |
80 | 80 |
81 | |
82 // Overrides attributes for the custom link format in intent picker. | |
83 @implementation CustomLinkButtonCell | |
84 - (NSDictionary*)linkAttributes { | |
85 scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( | |
86 [[NSParagraphStyle defaultParagraphStyle] mutableCopy]); | |
87 [paragraphStyle setAlignment:[self alignment]]; | |
88 | |
89 return [NSDictionary dictionaryWithObjectsAndKeys: | |
Nico
2012/09/05 04:32:33
nit:
return @{
NSForegroundColorAttributeName:
groby-ooo-7-16
2012/09/06 02:43:48
Done.
| |
90 [self textColor], NSForegroundColorAttributeName, | |
91 [self font], NSFontAttributeName, | |
92 [NSCursor pointingHandCursor], NSCursorAttributeName, | |
93 paragraphStyle.get(), NSParagraphStyleAttributeName, | |
94 nil | |
Nico
2012/09/05 04:32:33
So this is overridden to remove the underline? Why
groby-ooo-7-16
2012/09/06 02:43:48
Because UI directive is to look like WebUI, even i
Nico
2012/09/06 02:48:21
Can you add a comment to that end? (And maybe remo
groby-ooo-7-16
2012/09/07 00:05:21
Done.
| |
95 ]; | |
96 } | |
97 @end | |
98 | |
81 // This simple NSView subclass is used as the single subview of the page info | 99 // This simple NSView subclass is used as the single subview of the page info |
82 // bubble's window's contentView. Drawing is flipped so that layout of the | 100 // bubble's window's contentView. Drawing is flipped so that layout of the |
83 // sections is easier. Apple recommends flipping the coordinate origin when | 101 // sections is easier. Apple recommends flipping the coordinate origin when |
84 // doing a lot of text layout because it's more natural. | 102 // doing a lot of text layout because it's more natural. |
85 @interface WebIntentsContentView : NSView | 103 @interface WebIntentsContentView : NSView |
86 @end | 104 @end |
87 @implementation WebIntentsContentView | 105 @implementation WebIntentsContentView |
88 - (BOOL)isFlipped { | 106 - (BOOL)isFlipped { |
89 return YES; | 107 return YES; |
90 } | 108 } |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 styleMask:NSTitledWindowMask | 648 styleMask:NSTitledWindowMask |
631 backing:NSBackingStoreBuffered | 649 backing:NSBackingStoreBuffered |
632 defer:YES]); | 650 defer:YES]); |
633 if ((self = [super initWithWindow:window.get()])) { | 651 if ((self = [super initWithWindow:window.get()])) { |
634 picker_ = picker; | 652 picker_ = picker; |
635 if (picker) | 653 if (picker) |
636 model_ = picker->model(); | 654 model_ = picker->model(); |
637 | 655 |
638 inlineDispositionTitleField_.reset([[NSTextField alloc] init]); | 656 inlineDispositionTitleField_.reset([[NSTextField alloc] init]); |
639 ConfigureTextFieldAsLabel(inlineDispositionTitleField_); | 657 ConfigureTextFieldAsLabel(inlineDispositionTitleField_); |
640 | 658 [inlineDispositionTitleField_ setFont:[NSFont boldSystemFontOfSize:0]]; |
641 flipView_.reset([[WebIntentsContentView alloc] init]); | 659 flipView_.reset([[WebIntentsContentView alloc] init]); |
642 [flipView_ setAutoresizingMask:NSViewMinYMargin]; | 660 [flipView_ setAutoresizingMask:NSViewMinYMargin]; |
643 [[[self window] contentView] setSubviews: | 661 [[[self window] contentView] setSubviews: |
644 [NSArray arrayWithObject:flipView_]]; | 662 [NSArray arrayWithObject:flipView_]]; |
645 | 663 |
646 [self performLayoutWithModel:model_]; | 664 [self performLayoutWithModel:model_]; |
647 [[self window] makeFirstResponder:self]; | 665 [[self window] makeFirstResponder:self]; |
648 } | 666 } |
649 return self; | 667 return self; |
650 } | 668 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 std::max(CGFloat(WebIntentPicker::kWindowWidth), containerSize.width); | 715 std::max(CGFloat(WebIntentPicker::kWindowWidth), containerSize.width); |
698 | 716 |
699 // Resize web contents. | 717 // Resize web contents. |
700 [webContentView setFrameSize:inlineContentSize]; | 718 [webContentView setFrameSize:inlineContentSize]; |
701 | 719 |
702 // Position close button. | 720 // Position close button. |
703 NSRect buttonFrame = [closeButton_ frame]; | 721 NSRect buttonFrame = [closeButton_ frame]; |
704 buttonFrame.origin.x = containerSize.width - | 722 buttonFrame.origin.x = containerSize.width - |
705 WebIntentPicker::kContentAreaBorder - kCloseButtonSize; | 723 WebIntentPicker::kContentAreaBorder - kCloseButtonSize; |
706 [closeButton_ setFrame:buttonFrame]; | 724 [closeButton_ setFrame:buttonFrame]; |
707 | |
708 [self setContainerSize:containerSize]; | 725 [self setContainerSize:containerSize]; |
709 } | 726 } |
710 | 727 |
711 - (void)setContainerSize:(NSSize)containerSize { | 728 - (void)setContainerSize:(NSSize)containerSize { |
712 // Resize container views | 729 // Resize container views |
713 NSRect frame = NSMakeRect(0, 0, 0, 0); | 730 NSRect frame = NSMakeRect(0, 0, 0, 0); |
714 frame.size = containerSize; | 731 frame.size = containerSize; |
715 [[[self window] contentView] setFrame:frame]; | 732 [[[self window] contentView] setFrame:frame]; |
716 [flipView_ setFrame:frame]; | 733 [flipView_ setFrame:frame]; |
717 | 734 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 WebIntentPicker::kContentAreaBorder, offset, size.width(), size.height()); | 866 WebIntentPicker::kContentAreaBorder, offset, size.width(), size.height()); |
850 | 867 |
851 [contents_->web_contents()->GetNativeView() setFrame:frame]; | 868 [contents_->web_contents()->GetNativeView() setFrame:frame]; |
852 [subviews addObject:contents_->web_contents()->GetNativeView()]; | 869 [subviews addObject:contents_->web_contents()->GetNativeView()]; |
853 | 870 |
854 return NSHeight(frame); | 871 return NSHeight(frame); |
855 } | 872 } |
856 | 873 |
857 - (CGFloat)addAnotherServiceLinkToSubviews:(NSMutableArray*)subviews | 874 - (CGFloat)addAnotherServiceLinkToSubviews:(NSMutableArray*)subviews |
858 atOffset:(CGFloat)offset { | 875 atOffset:(CGFloat)offset { |
876 DCHECK(model_); | |
877 DCHECK(model_->IsInlineDisposition()); | |
878 GURL url = model_->inline_disposition_url(); | |
859 | 879 |
880 const WebIntentPickerModel::InstalledService* service = | |
881 model_->GetInstalledServiceWithURL(url); | |
882 DCHECK(service); | |
883 | |
884 CGFloat originalOffset = offset; | |
885 | |
886 // Icon for current service. | |
887 scoped_nsobject<NSImageView> icon; | |
888 NSRect imageFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, offset, | |
889 0, 0); | |
890 icon.reset([[NSImageView alloc] initWithFrame:imageFrame]); | |
891 [icon setImage:service->favicon.ToNSImage()]; | |
892 [icon setImageFrameStyle:NSImageFrameNone]; | |
893 [icon setEnabled:YES]; | |
894 | |
895 imageFrame.size = [service->favicon.ToNSImage() size]; | |
896 [icon setFrame:imageFrame]; | |
897 | |
898 [subviews addObject:icon]; | |
899 | |
900 // Resize control to fit text | |
860 NSRect textFrame = | 901 NSRect textFrame = |
861 NSMakeRect(WebIntentPicker::kContentAreaBorder, offset, kTextWidth, 1); | 902 NSMakeRect(NSMaxX(imageFrame) + 4, |
903 offset, | |
904 WebIntentPicker::kTitleLinkMaxWidth, 1); | |
862 [inlineDispositionTitleField_ setFrame:textFrame]; | 905 [inlineDispositionTitleField_ setFrame:textFrame]; |
863 [subviews addObject:inlineDispositionTitleField_]; | 906 [subviews addObject:inlineDispositionTitleField_]; |
864 [GTMUILocalizerAndLayoutTweaker sizeToFitView:inlineDispositionTitleField_]; | 907 [GTMUILocalizerAndLayoutTweaker sizeToFitView:inlineDispositionTitleField_]; |
865 textFrame = [inlineDispositionTitleField_ frame]; | 908 textFrame = [inlineDispositionTitleField_ frame]; |
866 | 909 |
867 // Add link for "choose another service" if other suggestions are available | 910 // Add link for "choose another service" if other suggestions are available |
868 // or if more than one (the current) service is installed. | 911 // or if more than one (the current) service is installed. |
869 if (model_->GetInstalledServiceCount() > 1 || | 912 if (model_->GetInstalledServiceCount() > 1 || |
870 model_->GetSuggestedExtensionCount()) { | 913 model_->GetSuggestedExtensionCount()) { |
871 NSRect frame = NSMakeRect( | 914 NSRect frame = NSMakeRect( |
872 NSMaxX(textFrame) + WebIntentPicker::kContentAreaBorder, offset, | 915 NSMaxX(textFrame) + WebIntentPicker::kContentAreaBorder, offset, |
873 WebIntentPicker::kTitleLinkMaxWidth, 1); | 916 1, 1); |
874 NSString* string = l10n_util::GetNSStringWithFixup( | 917 NSString* string = l10n_util::GetNSStringWithFixup( |
875 IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE); | 918 IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE); |
876 scoped_nsobject<NSButton> button(CreateHyperlinkButton(string, frame)); | 919 scoped_nsobject<NSButton> button(CreateHyperlinkButton(string, frame)); |
877 [[button cell] setControlSize:NSRegularControlSize]; | 920 [[button cell] setControlSize:NSRegularControlSize]; |
921 [[button cell] setFont:[NSFont controlContentFontOfSize:0]]; | |
878 [button setTarget:self]; | 922 [button setTarget:self]; |
879 [button setAction:@selector(chooseAnotherService:)]; | 923 [button setAction:@selector(chooseAnotherService:)]; |
880 [subviews addObject:button]; | 924 [subviews addObject:button]; |
881 | 925 |
882 // Call size-to-fit to fixup for the localized string. | 926 // Call size-to-fit to fixup for the localized string. |
883 [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; | 927 [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; |
884 | 928 |
929 // Right-align the "use another service" button. | |
930 frame = [button frame]; | |
931 frame.origin.x = WebIntentPicker::kWindowWidth - NSWidth(frame) - | |
932 2 * WebIntentPicker::kContentAreaBorder - kCloseButtonSize; | |
933 [button setFrame:frame]; | |
934 [button setAutoresizingMask:NSViewMinXMargin]; | |
935 | |
885 // And finally, make sure the link and the title are horizontally centered. | 936 // And finally, make sure the link and the title are horizontally centered. |
886 frame = [button frame]; | 937 frame = [button frame]; |
887 CGFloat height = std::max(NSHeight(textFrame), NSHeight(frame)); | 938 CGFloat height = std::max(NSHeight(textFrame), NSHeight(frame)); |
888 frame.origin.y += (height - NSHeight(frame)) / 2.0; | 939 frame.origin.y += (height - NSHeight(frame)) / 2.0; |
889 frame.size.height = height; | 940 frame.size.height = height; |
890 textFrame.origin.y += (height - NSHeight(textFrame)) / 2.0; | 941 textFrame.origin.y += (height - NSHeight(textFrame)) / 2.0; |
891 textFrame.size.height = height; | 942 textFrame.size.height = height; |
892 [button setFrame:frame]; | 943 [button setFrame:frame]; |
893 [inlineDispositionTitleField_ setFrame:textFrame]; | 944 [inlineDispositionTitleField_ setFrame:textFrame]; |
894 } | 945 } |
895 | 946 |
896 return NSHeight(textFrame); | 947 offset += NSHeight(textFrame) + kVerticalSpacing; |
948 | |
949 scoped_nsobject<NSBox> spacer; | |
950 NSRect frame = NSMakeRect(0, offset, WebIntentPicker::kWindowWidth, 1.0); | |
951 spacer.reset([[NSBox alloc] initWithFrame:frame]); | |
952 [spacer setBoxType:NSBoxSeparator]; | |
953 [spacer setBorderColor:[NSColor blackColor]]; | |
954 [spacer setAutoresizingMask:NSViewWidthSizable]; | |
955 [subviews addObject: spacer]; | |
956 | |
957 return offset + kVerticalSpacing - originalOffset; | |
897 } | 958 } |
898 | 959 |
899 - (NSView*)createEmptyView { | 960 - (NSView*)createEmptyView { |
900 NSMutableArray* subviews = [NSMutableArray array]; | 961 NSMutableArray* subviews = [NSMutableArray array]; |
901 | 962 |
902 NSRect titleFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, | 963 NSRect titleFrame = NSMakeRect(WebIntentPicker::kContentAreaBorder, |
903 WebIntentPicker::kContentAreaBorder, | 964 WebIntentPicker::kContentAreaBorder, |
904 kTextWidth, 1); | 965 kTextWidth, 1); |
905 scoped_nsobject<NSTextField> title( | 966 scoped_nsobject<NSTextField> title( |
906 [[NSTextField alloc] initWithFrame:titleFrame]); | 967 [[NSTextField alloc] initWithFrame:titleFrame]); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
963 !model_->GetInstalledServiceCount() && | 1024 !model_->GetInstalledServiceCount() && |
964 !model_->GetSuggestedExtensionCount(); | 1025 !model_->GetSuggestedExtensionCount(); |
965 | 1026 |
966 if (isEmpty) { | 1027 if (isEmpty) { |
967 scoped_nsobject<NSView> emptyView([self createEmptyView]); | 1028 scoped_nsobject<NSView> emptyView([self createEmptyView]); |
968 [subviews addObject:emptyView]; | 1029 [subviews addObject:emptyView]; |
969 offset += NSHeight([emptyView frame]); | 1030 offset += NSHeight([emptyView frame]); |
970 } else if (contents_) { | 1031 } else if (contents_) { |
971 offset += [self addAnotherServiceLinkToSubviews:subviews | 1032 offset += [self addAnotherServiceLinkToSubviews:subviews |
972 atOffset:offset]; | 1033 atOffset:offset]; |
973 offset += WebIntentPicker::kContentAreaBorder; | |
974 offset += [self addInlineHtmlToSubviews:subviews atOffset:offset]; | 1034 offset += [self addInlineHtmlToSubviews:subviews atOffset:offset]; |
975 } else { | 1035 } else { |
976 offset += [self addHeaderToSubviews:subviews atOffset:offset]; | 1036 offset += [self addHeaderToSubviews:subviews atOffset:offset]; |
977 | 1037 |
978 if (model) { | 1038 if (model) { |
979 intentView_.reset( | 1039 intentView_.reset( |
980 [[IntentView alloc] initWithModel:model forController:self]); | 1040 [[IntentView alloc] initWithModel:model forController:self]); |
981 offset += [self addStackedView:intentView_ | 1041 offset += [self addStackedView:intentView_ |
982 toSubviews:subviews | 1042 toSubviews:subviews |
983 atOffset:offset]; | 1043 atOffset:offset]; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1032 - (void)stopThrobber { | 1092 - (void)stopThrobber { |
1033 [closeButton_ setEnabled:YES]; | 1093 [closeButton_ setEnabled:YES]; |
1034 [intentView_ stopThrobber]; | 1094 [intentView_ stopThrobber]; |
1035 } | 1095 } |
1036 | 1096 |
1037 - (void)closeSheet { | 1097 - (void)closeSheet { |
1038 [NSApp endSheet:[self window]]; | 1098 [NSApp endSheet:[self window]]; |
1039 } | 1099 } |
1040 | 1100 |
1041 @end // WebIntentPickerSheetController | 1101 @end // WebIntentPickerSheetController |
OLD | NEW |