Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

extension_install_prompt_controller.mm

// Copyright (c) 2010 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.

#import "chrome/browser/cocoa/extensions/extension_install_prompt_controller.h"

#include "app/l10n_util.h"
#include "app/l10n_util_mac.h"
#include "base/mac_util.h"
#include "base/string_util.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/common/extensions/extension.h"
#include "grit/generated_resources.h"
#include "skia/ext/skia_utils_mac.h"

namespace {

// Maximum height we will adjust controls to when trying to accomodate their
// contents.
const CGFloat kMaxControlHeight = 400;

// Adjust a control's height so that its content its not clipped. Returns the
// amount the control's height had to be adjusted.
CGFloat AdjustControlHeightToFitContent(NSControl* control) {
  NSRect currentRect = [control frame];
  NSRect fitRect = currentRect;
  fitRect.size.height = kMaxControlHeight;
  CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height;
  CGFloat offset = desiredHeight - currentRect.size.height;

  [control setFrameSize:NSMakeSize(currentRect.size.width,
                                   currentRect.size.height + offset)];
  return offset;
}

// Moves the control vertically by the specified amount.
void OffsetControlVertically(NSControl* control, CGFloat amount) {
  NSPoint origin = [control frame].origin;
  origin.y += amount;
  [control setFrameOrigin:origin];
}

}

@implementation ExtensionInstallPromptController

@synthesize iconView = iconView_;
@synthesize titleField = titleField_;
@synthesize subtitleField = subtitleField_;
@synthesize warningsField = warningsField_;
@synthesize warningsBox= warningsBox_;
@synthesize cancelButton = cancelButton_;
@synthesize okButton = okButton_;

- (id)initWithParentWindow:(NSWindow*)window
                   profile:(Profile*)profile
                 extension:(Extension*)extension
                  delegate:(ExtensionInstallUI::Delegate*)delegate
                      icon:(SkBitmap*)icon
                  warnings:(const std::vector<string16>&)warnings {
  NSString* nibpath = nil;

  // We use a different XIB in the case of no warnings, that is a little bit
  // more nicely laid out.
  if (warnings.empty()) {
    nibpath = [mac_util::MainAppBundle()
               pathForResource:@"ExtensionInstallPromptNoWarnings"
                        ofType:@"nib"];
  } else {
   nibpath = [mac_util::MainAppBundle()
              pathForResource:@"ExtensionInstallPrompt"
                       ofType:@"nib"];
  }

  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
    parentWindow_ = window;
    profile_ = profile;
    icon_ = *icon;
    delegate_ = delegate;

    title_.reset(
        [l10n_util::GetNSStringF(IDS_EXTENSION_INSTALL_PROMPT_HEADING,
                                 UTF8ToUTF16(extension->name())) retain]);

    // We display the warnings as a simple text string, separated by newlines.
    if (!warnings.empty()) {
      string16 joined_warnings;
      for (size_t i = 0; i < warnings.size(); ++i) {
        if (i > 0)
          joined_warnings += UTF8ToUTF16("\n\n");

        joined_warnings += warnings[i];
      }

      warnings_.reset(
          [base::SysUTF16ToNSString(joined_warnings) retain]);
    }
  }
  return self;
}

- (void)runAsModalSheet {
  [NSApp beginSheet:[self window]
     modalForWindow:parentWindow_
      modalDelegate:self
     didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
        contextInfo:nil];
}

- (IBAction)cancel:(id)sender {
  delegate_->InstallUIAbort();
  [NSApp endSheet:[self window]];
}

- (IBAction)ok:(id)sender {
  delegate_->InstallUIProceed(false);  // Don't create shortcut.
  [NSApp endSheet:[self window]];
}

- (void)awakeFromNib {
  [titleField_ setStringValue:title_.get()];

  NSImage* image = gfx::SkBitmapToNSImage(icon_);
  [iconView_ setImage:image];

  // Make sure we're the window's delegate as set in the nib.
  DCHECK_EQ(self, static_cast<ExtensionInstallPromptController*>(
                      [[self window] delegate]));

  // If there are any warnings, then we have to do some special layout.
  if ([warnings_.get() length] > 0) {
    [warningsField_ setStringValue:warnings_.get()];

    // The dialog is laid out in the NIB exactly how we want it assuming that
    // each label fits on one line. However, for each label, we want to allow
    // wrapping onto multiple lines. So we accumulate an offset by measuring how
    // big each label wants to be, and comparing it to how bit it actually is.
    // Then we shift each label down and resize by the appropriate amount, then
    // finally resize the window.
    CGFloat totalOffset = 0.0;

    // Text fields.
    totalOffset += AdjustControlHeightToFitContent(titleField_);
    OffsetControlVertically(titleField_, -totalOffset);

    totalOffset += AdjustControlHeightToFitContent(subtitleField_);
    OffsetControlVertically(subtitleField_, -totalOffset);

    CGFloat warningsOffset = AdjustControlHeightToFitContent(warningsField_);
    OffsetControlVertically(warningsField_, -warningsOffset);
    totalOffset += warningsOffset;

    NSRect warningsBoxRect = [warningsBox_ frame];
    warningsBoxRect.origin.y -= totalOffset;
    warningsBoxRect.size.height += warningsOffset;
    [warningsBox_ setFrame:warningsBoxRect];

    // buttons are positioned automatically in the XIB.

    // Finally, adjust the window size.
    NSRect currentRect = [[self window] frame];
    [[self window] setFrame:NSMakeRect(currentRect.origin.x,
                                       currentRect.origin.y - totalOffset,
                                       currentRect.size.width,
                                       currentRect.size.height + totalOffset)
                    display:NO];
  }
}

- (void)didEndSheet:(NSWindow*)sheet
         returnCode:(int)returnCode
        contextInfo:(void*)contextInfo {
  [sheet close];
}

- (void)windowWillClose:(NSNotification*)notification {
  [self autorelease];
}

@end  // ExtensionInstallPromptController


void ExtensionInstallUI::ShowExtensionInstallUIPrompt2Impl(
    Profile* profile, Delegate* delegate, Extension* extension, SkBitmap* icon,
    const std::vector<string16>& warnings) {
  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
  if (!browser) {
    delegate->InstallUIAbort();
    return;
  }

  BrowserWindow* window = browser->window();
  if (!window) {
    delegate->InstallUIAbort();
    return;
  }

  gfx::NativeWindow native_window = window->GetNativeHandle();

  ExtensionInstallPromptController* controller =
      [[ExtensionInstallPromptController alloc]
        initWithParentWindow:native_window
                     profile:profile
                   extension:extension
                    delegate:delegate
                        icon:icon
                   warnings:warnings];

  [controller runAsModalSheet];
}

Generated by  Doxygen 1.6.0   Back to index