summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/tab_contents/sad_tab_view.mm
blob: 769ea749a0be9818506da73d6d4ce17b2e03a91d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_view.h"

#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#import "chrome/browser/ui/cocoa/hyperlink_text_view.h"
#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"

// Offset above vertical middle of page where contents of page start.
static const CGFloat kSadTabOffset = -64;
// Padding between icon and title.
static const CGFloat kIconTitleSpacing = 20;
// Padding between title and message.
static const CGFloat kTitleMessageSpacing = 15;
// Padding between message and link.
static const CGFloat kMessageLinkSpacing = 15;
// Paddings on left and right of page.
static const CGFloat kTabHorzMargin = 13;

@implementation SadTabView

- (void)awakeFromNib {
  // Load resource for image and set it.
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  NSImage* image = rb.GetNativeImageNamed(IDR_SAD_TAB).ToNSImage();
  [image_ setImage:image];

  // Set font for title.
  NSFont* titleFont = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];
  [title_ setFont:titleFont];

  // Set font for message.
  NSFont* messageFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
  [message_ setFont:messageFont];

  DCHECK(controller_);
  [self initializeHelpText];

  // Initialize background color.
  NSColor* backgroundColor = [[NSColor colorWithCalibratedRed:(35.0f/255.0f)
                                                        green:(48.0f/255.0f)
                                                         blue:(64.0f/255.0f)
                                                        alpha:1.0] retain];
  backgroundColor_.reset(backgroundColor);
}

- (void)drawRect:(NSRect)dirtyRect {
  // Paint background.
  [backgroundColor_ set];
  NSRectFill(dirtyRect);
}

- (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
  NSRect newBounds = [self bounds];
  CGFloat maxWidth = NSWidth(newBounds) - (kTabHorzMargin * 2);
  BOOL callSizeToFit = (messageSize_.width == 0);

  // Set new frame origin for image.
  NSRect iconFrame = [image_ frame];
  CGFloat iconX = (maxWidth - NSWidth(iconFrame)) / 2;
  CGFloat iconY =
      MIN(((NSHeight(newBounds) - NSHeight(iconFrame)) / 2) - kSadTabOffset,
          NSHeight(newBounds) - NSHeight(iconFrame));
  iconX = floor(iconX);
  iconY = floor(iconY);
  [image_ setFrameOrigin:NSMakePoint(iconX, iconY)];

  // Set new frame origin for title.
  if (callSizeToFit)
    [title_ sizeToFit];
  NSRect titleFrame = [title_ frame];
  CGFloat titleX = (maxWidth - NSWidth(titleFrame)) / 2;
  CGFloat titleY = iconY - kIconTitleSpacing - NSHeight(titleFrame);
  [title_ setFrameOrigin:NSMakePoint(titleX, titleY)];

  // Set new frame for message, wrapping or unwrapping the text if necessary.
  if (callSizeToFit) {
    [message_ sizeToFit];
    messageSize_ = [message_ frame].size;
  }
  NSRect messageFrame = [message_ frame];
  if (messageSize_.width > maxWidth) {  // Need to wrap message.
    [message_ setFrameSize:NSMakeSize(maxWidth, messageSize_.height)];
    CGFloat heightChange =
        [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:message_];
    messageFrame.size.width = maxWidth;
    messageFrame.size.height = messageSize_.height + heightChange;
    messageFrame.origin.x = kTabHorzMargin;
  } else {
    if (!callSizeToFit) {
      [message_ sizeToFit];
      messageFrame = [message_ frame];
    }
    messageFrame.origin.x = (maxWidth - NSWidth(messageFrame)) / 2;
  }
  messageFrame.origin.y =
      titleY - kTitleMessageSpacing - NSHeight(messageFrame);
  [message_ setFrame:messageFrame];

  // Set new frame for help text and link.
  if (help_) {
    if (callSizeToFit)
      [help_.get() sizeToFit];
    CGFloat helpHeight = [help_.get() frame].size.height;
    [help_.get() setFrameSize:NSMakeSize(maxWidth, helpHeight)];
    // Set new frame origin for link.
    NSRect helpFrame = [help_.get() frame];
    CGFloat helpX = (maxWidth - NSWidth(helpFrame)) / 2;
    CGFloat helpY =
        NSMinY(messageFrame) - kMessageLinkSpacing - NSHeight(helpFrame);
    [help_.get() setFrameOrigin:NSMakePoint(helpX, helpY)];
  }
}

- (void)removeHelpText {
  if (help_.get()) {
    [help_.get() removeFromSuperview];
    help_.reset(nil);
  }
}

- (void)initializeHelpText {
  // Replace the help placeholder NSTextField with the real help NSTextView.
  // The former doesn't show links in a nice way, but the latter can't be added
  // in IB without a containing scroll view, so create the NSTextView
  // programmatically. Taken from -[InfoBarController initializeLabel].
  help_.reset(
      [[HyperlinkTextView alloc] initWithFrame:[helpPlaceholder_ frame]]);
  [help_.get() setAutoresizingMask:[helpPlaceholder_ autoresizingMask]];
  [[helpPlaceholder_ superview]
      replaceSubview:helpPlaceholder_ with:help_.get()];
  helpPlaceholder_ = nil;  // Now released.
  [help_.get() setDelegate:self];
  [help_.get() setAlignment:NSCenterTextAlignment];

  // Get the help text and link.
  size_t linkOffset = 0;
  NSString* helpMessage(base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
      IDS_SAD_TAB_HELP_MESSAGE, base::string16(), &linkOffset)));
  NSString* helpLink = l10n_util::GetNSString(IDS_SAD_TAB_HELP_LINK);
  NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
  [help_.get() setMessageAndLink:helpMessage
                        withLink:helpLink
                        atOffset:linkOffset
                            font:font
                    messageColor:[NSColor whiteColor]
                       linkColor:[NSColor whiteColor]];
}

// Called when someone clicks on the embedded link.
- (BOOL)textView:(NSTextView*)textView
   clickedOnLink:(id)link
         atIndex:(NSUInteger)charIndex {
  if (controller_)
    [controller_ openLearnMoreAboutCrashLink:nil];
  return YES;
}

@end