summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/cocoa/infobars/confirm_infobar_controller.mm
blob: aa5478ddd85ea5b3373ba1202656c924e56c37cd (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
// Copyright 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/infobars/confirm_infobar_controller.h"

#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/ui/chrome_style.h"
#include "chrome/browser/ui/cocoa/infobars/infobar_cocoa.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
#import "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/cocoa/controls/hyperlink_text_view.h"
#include "ui/base/window_open_disposition.h"

@implementation ConfirmInfoBarController

// Called when someone clicks on the "OK" button.
- (IBAction)ok:(id)sender {
  if (![self isOwned])
    return;
  if ([self delegate]->AsConfirmInfoBarDelegate()->Accept())
    [self removeSelf];
}

// Called when someone clicks on the "Cancel" button.
- (IBAction)cancel:(id)sender {
  if (![self isOwned])
    return;
  if ([self delegate]->AsConfirmInfoBarDelegate()->Cancel())
    [self removeSelf];
}

// Confirm infobars can have OK and/or cancel buttons, depending on
// the return value of GetButtons().  We create each button if
// required and position them to the left of the close button.
- (void)addAdditionalControls {
  ConfirmInfoBarDelegate* delegate =
      [self delegate]->AsConfirmInfoBarDelegate();
  DCHECK(delegate);
  int visibleButtons = delegate->GetButtons();

  NSRect okButtonFrame = [okButton_ frame];
  NSRect cancelButtonFrame = [cancelButton_ frame];

  DCHECK(NSMaxX(cancelButtonFrame) < NSMinX(okButtonFrame))
      << "Ok button expected to be on the right of the Cancel button in nib";

  CGFloat rightEdge = NSMaxX(okButtonFrame);
  CGFloat spaceBetweenButtons =
      NSMinX(okButtonFrame) - NSMaxX(cancelButtonFrame);
  CGFloat spaceBeforeButtons =
      NSMinX(cancelButtonFrame) - NSMaxX([label_.get() frame]);

  // Update and position the OK button if needed.  Otherwise, hide it.
  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
    [okButton_ setTitle:base::SysUTF16ToNSString(
          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK))];
    [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_];
    okButtonFrame = [okButton_ frame];

    // Position the ok button to the left of the Close button.
    okButtonFrame.origin.x = rightEdge - okButtonFrame.size.width;
    [okButton_ setFrame:okButtonFrame];

    // Update the rightEdge
    rightEdge = NSMinX(okButtonFrame);
  } else {
    [okButton_ removeFromSuperview];
    okButton_ = nil;
  }

  // Update and position the Cancel button if needed.  Otherwise, hide it.
  if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
    [cancelButton_ setTitle:base::SysUTF16ToNSString(
          delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL))];
    [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_];
    cancelButtonFrame = [cancelButton_ frame];

    // If we had a Ok button, leave space between the buttons.
    if (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK) {
      rightEdge -= spaceBetweenButtons;
    }

    // Position the Cancel button on our current right edge.
    cancelButtonFrame.origin.x = rightEdge - cancelButtonFrame.size.width;
    [cancelButton_ setFrame:cancelButtonFrame];

    // Update the rightEdge.
    rightEdge = NSMinX(cancelButtonFrame);
  } else {
    [cancelButton_ removeFromSuperview];
    cancelButton_ = nil;
  }

  // If we had either button, leave space before the edge of the textfield.
  if ((visibleButtons & ConfirmInfoBarDelegate::BUTTON_CANCEL) ||
      (visibleButtons & ConfirmInfoBarDelegate::BUTTON_OK)) {
    rightEdge -= spaceBeforeButtons;
  }

  NSRect frame = [label_.get() frame];
  DCHECK(rightEdge > NSMinX(frame))
      << "Need to make the xib larger to handle buttons with text this long";
  frame.size.width = rightEdge - NSMinX(frame);
  [label_.get() setFrame:frame];

  // Set the text and link.
  NSString* message = base::SysUTF16ToNSString(delegate->GetMessageText());
  NSString* link = base::SysUTF16ToNSString(delegate->GetLinkText());
  NSUInteger linkOffset = [message length];
  NSUInteger linkLength = [link length];
  if (linkLength != 0) {
    // Add spacing between the label and the link.
    message = [message stringByAppendingFormat:@"   %@", link];
    linkOffset = [message length] - [link length];
  }
  NSFont* font = [NSFont labelFontOfSize:
      [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
  HyperlinkTextView* view = (HyperlinkTextView*)label_.get();
  [view setMessage:message withFont:font messageColor:[NSColor blackColor]];
  if (linkLength != 0) {
    NSColor* linkColor =
        skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor());
    [view addLinkRange:NSMakeRange(linkOffset, linkLength)
               withURL:base::SysUTF8ToNSString(delegate->GetLinkURL().spec())
             linkColor:linkColor];
  }
}

// Called when someone clicks on the link in the infobar.  This method
// is called by the InfobarTextField on its delegate (the
// AlternateNavInfoBarController).
- (void)linkClicked {
  if (![self isOwned])
    return;
  WindowOpenDisposition disposition =
      ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
  if ([self delegate]->AsConfirmInfoBarDelegate()->LinkClicked(disposition))
    [self removeSelf];
}

@end

scoped_ptr<infobars::InfoBar> InfoBarService::CreateConfirmInfoBar(
    scoped_ptr<ConfirmInfoBarDelegate> delegate) {
  scoped_ptr<InfoBarCocoa> infobar(new InfoBarCocoa(delegate.Pass()));
  base::scoped_nsobject<ConfirmInfoBarController> controller(
      [[ConfirmInfoBarController alloc] initWithInfoBar:infobar.get()]);
  infobar->set_controller(controller);
  return infobar.Pass();
}