<commit_before>// Copyright (c) 2011 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/views/fullscreen_exit_bubble_views.h"

#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/views/bubble/bubble.h"
#include "grit/generated_resources.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/screen.h"
#include "views/bubble/bubble_border.h"
#include "views/controls/button/text_button.h"
#include "views/controls/link.h"
#include "views/widget/widget.h"

#if defined(OS_WIN)
#include "ui/base/l10n/l10n_util_win.h"
#endif

// FullscreenExitView ----------------------------------------------------------

namespace {
// Space between the site info label and the buttons / link.
const int kMiddlePaddingPx = 30;
}  // namespace

class FullscreenExitBubbleViews::FullscreenExitView
    : public views::View,
      public views::ButtonListener {
 public:
  FullscreenExitView(FullscreenExitBubbleViews* bubble,
                     const string16& accelerator,
                     const GURL& url,
                     bool ask_permission);
  virtual ~FullscreenExitView();

  // views::View
  virtual gfx::Size GetPreferredSize();

  // views::ButtonListener
  virtual void ButtonPressed(views::Button* sender, const views::Event& event);

  // Hide the accept and deny buttons, exposing the exit link.
  void HideButtons();

 private:
  string16 GetMessage(const GURL& url);

  // views::View
  virtual void Layout();

  FullscreenExitBubbleViews* bubble_;

  // Clickable hint text to show in the bubble.
  views::Link link_;
  views::Label message_label_;
  views::NativeTextButton* accept_button_;
  views::NativeTextButton* deny_button_;

  bool show_buttons_;
};

FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
    FullscreenExitBubbleViews* bubble,
    const string16& accelerator,
    const GURL& url,
    bool ask_permission)
    : bubble_(bubble),
      accept_button_(NULL),
      deny_button_(NULL),
      show_buttons_(ask_permission) {
  views::BubbleBorder* bubble_border =
      new views::BubbleBorder(views::BubbleBorder::NONE);
  bubble_border->set_background_color(Bubble::kBackgroundColor);
  set_background(new views::BubbleBackground(bubble_border));
  set_border(bubble_border);
  set_focusable(false);

  message_label_.set_parent_owned(false);
  message_label_.SetText(GetMessage(url));
  message_label_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
      ResourceBundle::MediumFont));

  link_.set_parent_owned(false);
  link_.set_collapse_when_hidden(false);
  link_.set_focusable(false);
#if !defined(OS_CHROMEOS)
  link_.SetText(
      l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE,
                                 accelerator));
#else
  link_.SetText(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
#endif
  link_.set_listener(bubble);
  link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
      ResourceBundle::MediumFont));
  link_.SetPressedColor(message_label_.enabled_color());
  link_.SetEnabledColor(message_label_.enabled_color());
  link_.SetVisible(false);

  link_.SetBackgroundColor(background()->get_color());
  message_label_.SetBackgroundColor(background()->get_color());
  AddChildView(&message_label_);
  AddChildView(&link_);

  accept_button_ = new views::NativeTextButton(this,
      UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_ALLOW)));
  accept_button_->set_focusable(false);
  AddChildView(accept_button_);

  deny_button_ = new views::NativeTextButton(this,
      UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_DENY)));
  deny_button_->set_focusable(false);
  AddChildView(deny_button_);

  if (!show_buttons_)
    HideButtons();
}

string16 FullscreenExitBubbleViews::FullscreenExitView::GetMessage(
    const GURL& url) {
  if (url.is_empty()) {
    return l10n_util::GetStringUTF16(
        IDS_FULLSCREEN_INFOBAR_USER_ENTERED_FULLSCREEN);
  }
  if (url.SchemeIsFile())
    return l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_FILE_PAGE_NAME);
  return l10n_util::GetStringFUTF16(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMISSION,
      UTF8ToUTF16(url.host()));
}

FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
}

void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
    views::Button* sender, const views::Event& event) {
  if (sender == accept_button_)
    bubble_->OnAcceptFullscreen();
  else
    bubble_->OnCancelFullscreen();
}

void FullscreenExitBubbleViews::FullscreenExitView::HideButtons() {
  show_buttons_ = false;
  accept_button_->SetVisible(false);
  deny_button_->SetVisible(false);
  link_.SetVisible(true);
}

gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() {
  gfx::Size link_size(link_.GetPreferredSize());
  gfx::Size message_label_size(message_label_.GetPreferredSize());
  gfx::Size accept_size(accept_button_->GetPreferredSize());
  gfx::Size deny_size(deny_button_->GetPreferredSize());
  gfx::Insets insets(GetInsets());

  int buttons_width = accept_size.width() + kPaddingPx +
      deny_size.width();
  int button_box_width = std::max(buttons_width, link_size.width());
  int width = kPaddingPx + message_label_size.width() + kMiddlePaddingPx +
      button_box_width + kPaddingPx;

  gfx::Size result(width + insets.width(),
      kPaddingPx * 2 + accept_size.height() + insets.height());
  return result;
}

void FullscreenExitBubbleViews::FullscreenExitView::Layout() {
  gfx::Size link_size(link_.GetPreferredSize());
  gfx::Size message_label_size(message_label_.GetPreferredSize());
  gfx::Size accept_size(accept_button_->GetPreferredSize());
  gfx::Size deny_size(deny_button_->GetPreferredSize());
  gfx::Insets insets(GetInsets());

  int inner_height = height() - insets.height();
  int button_box_x = insets.left() + kPaddingPx +
      message_label_size.width() + kMiddlePaddingPx;
  int message_label_y = insets.top() +
      (inner_height - message_label_size.height()) / 2;
  int link_x = width() - insets.right() - kPaddingPx -
      link_size.width();
  int link_y = insets.top() + (inner_height - link_size.height()) / 2;

  message_label_.SetPosition(gfx::Point(insets.left() + kPaddingPx,
                             message_label_y));
  link_.SetPosition(gfx::Point(link_x, link_y));
  if (show_buttons_) {
    accept_button_->SetPosition(gfx::Point(button_box_x,
        insets.top() + kPaddingPx));
    deny_button_->SetPosition(gfx::Point(
        button_box_x + accept_size.width() + kPaddingPx,
        insets.top() + kPaddingPx));
  }
}

// FullscreenExitBubbleViews ---------------------------------------------------

FullscreenExitBubbleViews::FullscreenExitBubbleViews(views::Widget* frame,
                                                     Browser* browser,
                                                     const GURL& url,
                                                     bool ask_permission)
    : FullscreenExitBubble(browser),
      root_view_(frame->GetRootView()),
      popup_(NULL),
      size_animation_(new ui::SlideAnimation(this)),
      url_(url) {
  size_animation_->Reset(1);

  // Create the contents view.
  views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
  bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
  DCHECK(got_accelerator);
  view_ = new FullscreenExitView(this,
      accelerator.GetShortcutText(), url, ask_permission);

  // Initialize the popup.
  popup_ = new views::Widget;
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.transparent = true;
  params.can_activate = false;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.parent = frame->GetNativeView();
  params.bounds = GetPopupRect(false);
  popup_->Init(params);
  gfx::Size size = GetPopupRect(true).size();
  popup_->SetContentsView(view_);
  // We set layout manager to NULL to prevent the widget from sizing its
  // contents to the same size as itself. This prevents the widget contents from
  // shrinking while we animate the height of the popup to give the impression
  // that it is sliding off the top of the screen.
  popup_->GetRootView()->SetLayoutManager(NULL);
  view_->SetBounds(0, 0, size.width(), size.height());
  popup_->Show();  // This does not activate the popup.

  if (!ask_permission)
    StartWatchingMouse();
}

FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
  // This is tricky.  We may be in an ATL message handler stack, in which case
  // the popup cannot be deleted yet.  We also can't set the popup's ownership
  // model to NATIVE_WIDGET_OWNS_WIDGET because if the user closed the last tab
  // while in fullscreen mode, Windows has already destroyed the popup HWND by
  // the time we get here, and thus either the popup will already have been
  // deleted (if we set this in our constructor) or the popup will never get
  // another OnFinalMessage() call (if not, as currently).  So instead, we tell
  // the popup to synchronously hide, and then asynchronously close and delete
  // itself.
  popup_->Close();
  MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
}

void FullscreenExitBubbleViews::LinkClicked(
    views::Link* source, int event_flags) {
  ToggleFullscreen();
}

void FullscreenExitBubbleViews::OnAcceptFullscreen() {
  AcceptFullscreen(url_);
  view_->HideButtons();
  StartWatchingMouse();
}

void FullscreenExitBubbleViews::OnCancelFullscreen() {
  CancelFullscreen();
}

void FullscreenExitBubbleViews::AnimationProgressed(
    const ui::Animation* animation) {
  gfx::Rect popup_rect(GetPopupRect(false));
  if (popup_rect.IsEmpty()) {
    popup_->Hide();
  } else {
    popup_->SetBounds(popup_rect);
    view_->SetY(popup_rect.height() - view_->height());
    popup_->Show();
  }
}

void FullscreenExitBubbleViews::AnimationEnded(
    const ui::Animation* animation) {
  AnimationProgressed(animation);
}

void FullscreenExitBubbleViews::Hide() {
  size_animation_->SetSlideDuration(kSlideOutDurationMs);
  size_animation_->Hide();
}

void FullscreenExitBubbleViews::Show() {
  size_animation_->SetSlideDuration(kSlideInDurationMs);
  size_animation_->Show();
}

bool FullscreenExitBubbleViews::IsAnimating() {
  return size_animation_->GetCurrentValue() != 0;
}

bool FullscreenExitBubbleViews::IsWindowActive() {
  return root_view_->GetWidget()->IsActive();
}

bool FullscreenExitBubbleViews::WindowContainsPoint(gfx::Point pos) {
  return root_view_->HitTest(pos);
}

gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() {
  gfx::Point cursor_pos = gfx::Screen::GetCursorScreenPoint();
  gfx::Point transformed_pos(cursor_pos);
  views::View::ConvertPointToView(NULL, root_view_, &transformed_pos);
  return transformed_pos;
}

gfx::Rect FullscreenExitBubbleViews::GetPopupRect(
    bool ignore_animation_state) const {
  gfx::Size size(view_->GetPreferredSize());
  // NOTE: don't use the bounds of the root_view_. On linux changing window
  // size is async. Instead we use the size of the screen.
  gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow(
      root_view_->GetWidget()->GetNativeView());
  gfx::Point origin(screen_bounds.x() +
                    (screen_bounds.width() - size.width()) / 2,
                    kPopupTopPx + screen_bounds.y());
  if (!ignore_animation_state) {
    int total_height = size.height() + kPopupTopPx;
    int popup_bottom = size_animation_->CurrentValueBetween(
        static_cast<double>(total_height), 0.0f);
    int y_offset = std::min(popup_bottom, kPopupTopPx);
    size.set_height(size.height() - popup_bottom + y_offset);
    origin.set_y(origin.y() - y_offset);
  }
  return gfx::Rect(origin, size);
}
<commit_msg>Change SetPosition() to SetBounds() in FullscreenExitView::Layout().<commit_after>// Copyright (c) 2011 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/views/fullscreen_exit_bubble_views.h"

#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/views/bubble/bubble.h"
#include "grit/generated_resources.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/screen.h"
#include "views/bubble/bubble_border.h"
#include "views/controls/button/text_button.h"
#include "views/controls/link.h"
#include "views/widget/widget.h"

#if defined(OS_WIN)
#include "ui/base/l10n/l10n_util_win.h"
#endif

// FullscreenExitView ----------------------------------------------------------

namespace {
// Space between the site info label and the buttons / link.
const int kMiddlePaddingPx = 30;
}  // namespace

class FullscreenExitBubbleViews::FullscreenExitView
    : public views::View,
      public views::ButtonListener {
 public:
  FullscreenExitView(FullscreenExitBubbleViews* bubble,
                     const string16& accelerator,
                     const GURL& url,
                     bool ask_permission);
  virtual ~FullscreenExitView();

  // views::View
  virtual gfx::Size GetPreferredSize();

  // views::ButtonListener
  virtual void ButtonPressed(views::Button* sender, const views::Event& event);

  // Hide the accept and deny buttons, exposing the exit link.
  void HideButtons();

 private:
  string16 GetMessage(const GURL& url);

  // views::View
  virtual void Layout();

  FullscreenExitBubbleViews* bubble_;

  // Clickable hint text to show in the bubble.
  views::Link link_;
  views::Label message_label_;
  views::NativeTextButton* accept_button_;
  views::NativeTextButton* deny_button_;

  bool show_buttons_;
};

FullscreenExitBubbleViews::FullscreenExitView::FullscreenExitView(
    FullscreenExitBubbleViews* bubble,
    const string16& accelerator,
    const GURL& url,
    bool ask_permission)
    : bubble_(bubble),
      accept_button_(NULL),
      deny_button_(NULL),
      show_buttons_(ask_permission) {
  views::BubbleBorder* bubble_border =
      new views::BubbleBorder(views::BubbleBorder::NONE);
  bubble_border->set_background_color(Bubble::kBackgroundColor);
  set_background(new views::BubbleBackground(bubble_border));
  set_border(bubble_border);
  set_focusable(false);

  message_label_.set_parent_owned(false);
  message_label_.SetText(GetMessage(url));
  message_label_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
      ResourceBundle::MediumFont));

  link_.set_parent_owned(false);
  link_.set_collapse_when_hidden(false);
  link_.set_focusable(false);
#if !defined(OS_CHROMEOS)
  link_.SetText(
      l10n_util::GetStringFUTF16(IDS_EXIT_FULLSCREEN_MODE,
                                 accelerator));
#else
  link_.SetText(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
#endif
  link_.set_listener(bubble);
  link_.SetFont(ResourceBundle::GetSharedInstance().GetFont(
      ResourceBundle::MediumFont));
  link_.SetPressedColor(message_label_.enabled_color());
  link_.SetEnabledColor(message_label_.enabled_color());
  link_.SetVisible(false);

  link_.SetBackgroundColor(background()->get_color());
  message_label_.SetBackgroundColor(background()->get_color());
  AddChildView(&message_label_);
  AddChildView(&link_);

  accept_button_ = new views::NativeTextButton(this,
      UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_ALLOW)));
  accept_button_->set_focusable(false);
  AddChildView(accept_button_);

  deny_button_ = new views::NativeTextButton(this,
      UTF16ToWide(l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_DENY)));
  deny_button_->set_focusable(false);
  AddChildView(deny_button_);

  if (!show_buttons_)
    HideButtons();
}

string16 FullscreenExitBubbleViews::FullscreenExitView::GetMessage(
    const GURL& url) {
  if (url.is_empty()) {
    return l10n_util::GetStringUTF16(
        IDS_FULLSCREEN_INFOBAR_USER_ENTERED_FULLSCREEN);
  }
  if (url.SchemeIsFile())
    return l10n_util::GetStringUTF16(IDS_FULLSCREEN_INFOBAR_FILE_PAGE_NAME);
  return l10n_util::GetStringFUTF16(IDS_FULLSCREEN_INFOBAR_REQUEST_PERMISSION,
      UTF8ToUTF16(url.host()));
}

FullscreenExitBubbleViews::FullscreenExitView::~FullscreenExitView() {
}

void FullscreenExitBubbleViews::FullscreenExitView::ButtonPressed(
    views::Button* sender, const views::Event& event) {
  if (sender == accept_button_)
    bubble_->OnAcceptFullscreen();
  else
    bubble_->OnCancelFullscreen();
}

void FullscreenExitBubbleViews::FullscreenExitView::HideButtons() {
  show_buttons_ = false;
  accept_button_->SetVisible(false);
  deny_button_->SetVisible(false);
  link_.SetVisible(true);
}

gfx::Size FullscreenExitBubbleViews::FullscreenExitView::GetPreferredSize() {
  gfx::Size link_size(link_.GetPreferredSize());
  gfx::Size message_label_size(message_label_.GetPreferredSize());
  gfx::Size accept_size(accept_button_->GetPreferredSize());
  gfx::Size deny_size(deny_button_->GetPreferredSize());
  gfx::Insets insets(GetInsets());

  int buttons_width = accept_size.width() + kPaddingPx +
      deny_size.width();
  int button_box_width = std::max(buttons_width, link_size.width());
  int width = kPaddingPx + message_label_size.width() + kMiddlePaddingPx +
      button_box_width + kPaddingPx;

  gfx::Size result(width + insets.width(),
      kPaddingPx * 2 + accept_size.height() + insets.height());
  return result;
}

void FullscreenExitBubbleViews::FullscreenExitView::Layout() {
  gfx::Size link_size(link_.GetPreferredSize());
  gfx::Size message_label_size(message_label_.GetPreferredSize());
  gfx::Size accept_size(accept_button_->GetPreferredSize());
  gfx::Size deny_size(deny_button_->GetPreferredSize());
  gfx::Insets insets(GetInsets());

  int inner_height = height() - insets.height();
  int button_box_x = insets.left() + kPaddingPx +
      message_label_size.width() + kMiddlePaddingPx;
  int message_label_y = insets.top() +
      (inner_height - message_label_size.height()) / 2;
  int link_x = width() - insets.right() - kPaddingPx -
      link_size.width();
  int link_y = insets.top() + (inner_height - link_size.height()) / 2;

  message_label_.SetBounds(insets.left() + kPaddingPx,
                           message_label_y,
                           message_label_size.width(),
                           message_label_size.height());
  link_.SetBounds(link_x,
                  link_y,
                  link_size.width(),
                  link_size.height());
  if (show_buttons_) {
    accept_button_->SetBounds(button_box_x,
                              insets.top() + kPaddingPx,
                              accept_size.width(),
                              accept_size.height());
    deny_button_->SetBounds(button_box_x + accept_size.width() + kPaddingPx,
                            insets.top() + kPaddingPx,
                            deny_size.width(),
                            deny_size.height());
  }
}

// FullscreenExitBubbleViews ---------------------------------------------------

FullscreenExitBubbleViews::FullscreenExitBubbleViews(views::Widget* frame,
                                                     Browser* browser,
                                                     const GURL& url,
                                                     bool ask_permission)
    : FullscreenExitBubble(browser),
      root_view_(frame->GetRootView()),
      popup_(NULL),
      size_animation_(new ui::SlideAnimation(this)),
      url_(url) {
  size_animation_->Reset(1);

  // Create the contents view.
  views::Accelerator accelerator(ui::VKEY_UNKNOWN, false, false, false);
  bool got_accelerator = frame->GetAccelerator(IDC_FULLSCREEN, &accelerator);
  DCHECK(got_accelerator);
  view_ = new FullscreenExitView(this,
      accelerator.GetShortcutText(), url, ask_permission);

  // Initialize the popup.
  popup_ = new views::Widget;
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.transparent = true;
  params.can_activate = false;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.parent = frame->GetNativeView();
  params.bounds = GetPopupRect(false);
  popup_->Init(params);
  gfx::Size size = GetPopupRect(true).size();
  popup_->SetContentsView(view_);
  // We set layout manager to NULL to prevent the widget from sizing its
  // contents to the same size as itself. This prevents the widget contents from
  // shrinking while we animate the height of the popup to give the impression
  // that it is sliding off the top of the screen.
  popup_->GetRootView()->SetLayoutManager(NULL);
  view_->SetBounds(0, 0, size.width(), size.height());
  popup_->Show();  // This does not activate the popup.

  if (!ask_permission)
    StartWatchingMouse();
}

FullscreenExitBubbleViews::~FullscreenExitBubbleViews() {
  // This is tricky.  We may be in an ATL message handler stack, in which case
  // the popup cannot be deleted yet.  We also can't set the popup's ownership
  // model to NATIVE_WIDGET_OWNS_WIDGET because if the user closed the last tab
  // while in fullscreen mode, Windows has already destroyed the popup HWND by
  // the time we get here, and thus either the popup will already have been
  // deleted (if we set this in our constructor) or the popup will never get
  // another OnFinalMessage() call (if not, as currently).  So instead, we tell
  // the popup to synchronously hide, and then asynchronously close and delete
  // itself.
  popup_->Close();
  MessageLoop::current()->DeleteSoon(FROM_HERE, popup_);
}

void FullscreenExitBubbleViews::LinkClicked(
    views::Link* source, int event_flags) {
  ToggleFullscreen();
}

void FullscreenExitBubbleViews::OnAcceptFullscreen() {
  AcceptFullscreen(url_);
  view_->HideButtons();
  StartWatchingMouse();
}

void FullscreenExitBubbleViews::OnCancelFullscreen() {
  CancelFullscreen();
}

void FullscreenExitBubbleViews::AnimationProgressed(
    const ui::Animation* animation) {
  gfx::Rect popup_rect(GetPopupRect(false));
  if (popup_rect.IsEmpty()) {
    popup_->Hide();
  } else {
    popup_->SetBounds(popup_rect);
    view_->SetY(popup_rect.height() - view_->height());
    popup_->Show();
  }
}

void FullscreenExitBubbleViews::AnimationEnded(
    const ui::Animation* animation) {
  AnimationProgressed(animation);
}

void FullscreenExitBubbleViews::Hide() {
  size_animation_->SetSlideDuration(kSlideOutDurationMs);
  size_animation_->Hide();
}

void FullscreenExitBubbleViews::Show() {
  size_animation_->SetSlideDuration(kSlideInDurationMs);
  size_animation_->Show();
}

bool FullscreenExitBubbleViews::IsAnimating() {
  return size_animation_->GetCurrentValue() != 0;
}

bool FullscreenExitBubbleViews::IsWindowActive() {
  return root_view_->GetWidget()->IsActive();
}

bool FullscreenExitBubbleViews::WindowContainsPoint(gfx::Point pos) {
  return root_view_->HitTest(pos);
}

gfx::Point FullscreenExitBubbleViews::GetCursorScreenPoint() {
  gfx::Point cursor_pos = gfx::Screen::GetCursorScreenPoint();
  gfx::Point transformed_pos(cursor_pos);
  views::View::ConvertPointToView(NULL, root_view_, &transformed_pos);
  return transformed_pos;
}

gfx::Rect FullscreenExitBubbleViews::GetPopupRect(
    bool ignore_animation_state) const {
  gfx::Size size(view_->GetPreferredSize());
  // NOTE: don't use the bounds of the root_view_. On linux changing window
  // size is async. Instead we use the size of the screen.
  gfx::Rect screen_bounds = gfx::Screen::GetMonitorAreaNearestWindow(
      root_view_->GetWidget()->GetNativeView());
  gfx::Point origin(screen_bounds.x() +
                    (screen_bounds.width() - size.width()) / 2,
                    kPopupTopPx + screen_bounds.y());
  if (!ignore_animation_state) {
    int total_height = size.height() + kPopupTopPx;
    int popup_bottom = size_animation_->CurrentValueBetween(
        static_cast<double>(total_height), 0.0f);
    int y_offset = std::min(popup_bottom, kPopupTopPx);
    size.set_height(size.height() - popup_bottom + y_offset);
    origin.set_y(origin.y() - y_offset);
  }
  return gfx::Rect(origin, size);
}
<|endoftext|>


<commit_before>// 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_unpacker.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace errors = extension_manifest_errors;
namespace keys = extension_manifest_keys;

class ExtensionUnpackerTest : public testing::Test {
public:
  void SetupUnpacker(const std::string& crx_name) {
    FilePath original_path;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &original_path));
    original_path = original_path.AppendASCII("extensions")
        .AppendASCII("unpacker")
        .AppendASCII(crx_name);
    ASSERT_TRUE(file_util::PathExists(original_path)) << original_path.value();

    // Try bots won't let us write into DIR_TEST_DATA, so we have to create
    // a temp folder to play in.
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    FilePath crx_path = temp_dir_.path().AppendASCII(crx_name);
    ASSERT_TRUE(file_util::CopyFile(original_path, crx_path)) <<
        "Original path " << original_path.value() <<
        ", Crx path " << crx_path.value();

    unpacker_.reset(
        new ExtensionUnpacker(
            crx_path, Extension::INTERNAL, Extension::NO_FLAGS));
  }

 protected:
  ScopedTempDir temp_dir_;
  scoped_ptr<ExtensionUnpacker> unpacker_;
};

// Crashes intermittently on Windows, see http://crbug.com/109238
#if defined(OS_WIN)
#define MAYBE_EmptyDefaultLocale DISABLED_EmptyDefaultLocale
#else
#define MAYBE_EmptyDefaultLocale EmptyDefaultLocale
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_EmptyDefaultLocale) {
  SetupUnpacker("empty_default_locale.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kInvalidDefaultLocale),
            unpacker_->error_message());
}

// Crashes intermittently on Vista, see http://crbug.com/109385
#if defined(OS_WIN)
#define MAYBE_HasDefaultLocaleMissingLocalesFolder \
  DISABLED_HasDefaultLocaleMissingLocalesFolder
#else
#define MAYBE_HasDefaultLocaleMissingLocalesFolder \
  HasDefaultLocaleMissingLocalesFolder
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_HasDefaultLocaleMissingLocalesFolder) {
  SetupUnpacker("has_default_missing_locales.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesTreeMissing),
            unpacker_->error_message());
}

// Crashes intermittently on Windows, see http://crbug.com/109238
#if defined(OS_WIN)
#define MAYBE_InvalidDefaultLocale DISABLED_InvalidDefaultLocale
#else
#define MAYBE_InvalidDefaultLocale InvalidDefaultLocale
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_InvalidDefaultLocale) {
  SetupUnpacker("invalid_default_locale.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kInvalidDefaultLocale),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, InvalidMessagesFile) {
  SetupUnpacker("invalid_messages_file.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_TRUE(MatchPattern(unpacker_->error_message(),
    ASCIIToUTF16("*_locales?en_US?messages.json: Line: 2, column: 3,"
                " Dictionary keys must be quoted.")));
}

TEST_F(ExtensionUnpackerTest, MissingDefaultData) {
  SetupUnpacker("missing_default_data.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultMessages),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, MissingDefaultLocaleHasLocalesFolder) {
  SetupUnpacker("missing_default_has_locales.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultLocaleSpecified),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, MissingMessagesFile) {
  SetupUnpacker("missing_messages_file.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_TRUE(MatchPattern(unpacker_->error_message(),
    ASCIIToUTF16(errors::kLocalesMessagesFileMissing) +
    ASCIIToUTF16("*_locales?en_US?messages.json")));
}

TEST_F(ExtensionUnpackerTest, NoLocaleData) {
  SetupUnpacker("no_locale_data.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultMessages),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, GoodL10n) {
  SetupUnpacker("good_l10n.crx");
  EXPECT_TRUE(unpacker_->Run());
  EXPECT_TRUE(unpacker_->error_message().empty());
  ASSERT_EQ(2U, unpacker_->parsed_catalogs()->size());
}

TEST_F(ExtensionUnpackerTest, NoL10n) {
  SetupUnpacker("no_l10n.crx");
  EXPECT_TRUE(unpacker_->Run());
  EXPECT_TRUE(unpacker_->error_message().empty());
  EXPECT_EQ(0U, unpacker_->parsed_catalogs()->size());
}
<commit_msg>ExtensionUnpackerTest.InvalidMessagesFile is flaky on Windows<commit_after>// 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_unpacker.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace errors = extension_manifest_errors;
namespace keys = extension_manifest_keys;

class ExtensionUnpackerTest : public testing::Test {
public:
  void SetupUnpacker(const std::string& crx_name) {
    FilePath original_path;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &original_path));
    original_path = original_path.AppendASCII("extensions")
        .AppendASCII("unpacker")
        .AppendASCII(crx_name);
    ASSERT_TRUE(file_util::PathExists(original_path)) << original_path.value();

    // Try bots won't let us write into DIR_TEST_DATA, so we have to create
    // a temp folder to play in.
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    FilePath crx_path = temp_dir_.path().AppendASCII(crx_name);
    ASSERT_TRUE(file_util::CopyFile(original_path, crx_path)) <<
        "Original path " << original_path.value() <<
        ", Crx path " << crx_path.value();

    unpacker_.reset(
        new ExtensionUnpacker(
            crx_path, Extension::INTERNAL, Extension::NO_FLAGS));
  }

 protected:
  ScopedTempDir temp_dir_;
  scoped_ptr<ExtensionUnpacker> unpacker_;
};

// Crashes intermittently on Windows, see http://crbug.com/109238
#if defined(OS_WIN)
#define MAYBE_EmptyDefaultLocale DISABLED_EmptyDefaultLocale
#else
#define MAYBE_EmptyDefaultLocale EmptyDefaultLocale
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_EmptyDefaultLocale) {
  SetupUnpacker("empty_default_locale.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kInvalidDefaultLocale),
            unpacker_->error_message());
}

// Crashes intermittently on Vista, see http://crbug.com/109385
#if defined(OS_WIN)
#define MAYBE_HasDefaultLocaleMissingLocalesFolder \
  DISABLED_HasDefaultLocaleMissingLocalesFolder
#else
#define MAYBE_HasDefaultLocaleMissingLocalesFolder \
  HasDefaultLocaleMissingLocalesFolder
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_HasDefaultLocaleMissingLocalesFolder) {
  SetupUnpacker("has_default_missing_locales.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesTreeMissing),
            unpacker_->error_message());
}

// Crashes intermittently on Windows, see http://crbug.com/109238
#if defined(OS_WIN)
#define MAYBE_InvalidDefaultLocale DISABLED_InvalidDefaultLocale
#else
#define MAYBE_InvalidDefaultLocale InvalidDefaultLocale
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_InvalidDefaultLocale) {
  SetupUnpacker("invalid_default_locale.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kInvalidDefaultLocale),
            unpacker_->error_message());
}

// Crashes intermittently on Windows, see http://crbug.com/109738
#if defined(OS_WIN)
#define MAYBE_InvalidMessagesFile DISABLE_InvalidMessagesFile
#else
#define MAYBE_InvalidMessagesFile InvalidMessagesFile
#endif
TEST_F(ExtensionUnpackerTest, MAYBE_InvalidMessagesFile) {
  SetupUnpacker("invalid_messages_file.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_TRUE(MatchPattern(unpacker_->error_message(),
    ASCIIToUTF16("*_locales?en_US?messages.json: Line: 2, column: 3,"
                " Dictionary keys must be quoted.")));
}

TEST_F(ExtensionUnpackerTest, MissingDefaultData) {
  SetupUnpacker("missing_default_data.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultMessages),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, MissingDefaultLocaleHasLocalesFolder) {
  SetupUnpacker("missing_default_has_locales.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultLocaleSpecified),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, MissingMessagesFile) {
  SetupUnpacker("missing_messages_file.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_TRUE(MatchPattern(unpacker_->error_message(),
    ASCIIToUTF16(errors::kLocalesMessagesFileMissing) +
    ASCIIToUTF16("*_locales?en_US?messages.json")));
}

TEST_F(ExtensionUnpackerTest, NoLocaleData) {
  SetupUnpacker("no_locale_data.crx");
  EXPECT_FALSE(unpacker_->Run());
  EXPECT_EQ(ASCIIToUTF16(errors::kLocalesNoDefaultMessages),
            unpacker_->error_message());
}

TEST_F(ExtensionUnpackerTest, GoodL10n) {
  SetupUnpacker("good_l10n.crx");
  EXPECT_TRUE(unpacker_->Run());
  EXPECT_TRUE(unpacker_->error_message().empty());
  ASSERT_EQ(2U, unpacker_->parsed_catalogs()->size());
}

TEST_F(ExtensionUnpackerTest, NoL10n) {
  SetupUnpacker("no_l10n.crx");
  EXPECT_TRUE(unpacker_->Run());
  EXPECT_TRUE(unpacker_->error_message().empty());
  EXPECT_EQ(0U, unpacker_->parsed_catalogs()->size());
}
<|endoftext|>


<commit_before>/*
 * NotebookPlots.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookPlots.hpp"
#include "NotebookOutput.hpp"
#include "../SessionPlots.hpp"

#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/signals/connection.hpp>

#include <core/system/FileMonitor.hpp>
#include <core/StringUtils.hpp>
#include <core/Exec.hpp>

#include <session/SessionModuleContext.hpp>

#include <r/RExec.hpp>
#include <r/RSexp.hpp>
#include <r/session/RGraphics.hpp>
#include <r/ROptions.hpp>

#define kPlotPrefix "_rs_chunk_plot_"
#define kGoldenRatio 1.618

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {
namespace {

bool isPlotPath(const FilePath& path)
{
   return path.hasExtensionLowerCase(".png") &&
          string_utils::isPrefixOf(path.stem(), kPlotPrefix);
}

} // anonymous namespace

PlotCapture::PlotCapture() :
   hasPlots_(false),
   plotPending_(false),
   lastOrdinal_(0)
{
}

PlotCapture::~PlotCapture()
{
}

void PlotCapture::processPlots(bool ignoreEmpty)
{
   // ensure plot folder exists
   if (!plotFolder_.exists())
      return;

   // collect plots from the folder
   std::vector<FilePath> folderContents;
   Error error = plotFolder_.children(&folderContents);
   if (error)
      LOG_ERROR(error);

   BOOST_FOREACH(const FilePath& path, folderContents)
   {
      if (isPlotPath(path))
      {
         // we might find an empty plot file if it hasn't been flushed to disk
         // yet--ignore these
         if (ignoreEmpty && path.size() == 0)
            continue;

         // emit the plot and the snapshot file
         events().onPlotOutput(path, snapshotFile_, lastOrdinal_);

         // we've consumed the snapshot file, so clear it
         snapshotFile_ = FilePath();
         lastOrdinal_ = 0;

         // clean up the plot so it isn't emitted twice
         error = path.removeIfExists();
         if (error)
            LOG_ERROR(error);
      }
   }
}

void PlotCapture::saveSnapshot()
{
   // no work to do if we don't have a display list to write
   if (lastPlot_.isNil())
      return;

   // if there's a plot on the device, write its display list before it's
   // cleared for the next page
   FilePath outputFile = plotFolder_.complete(
         core::system::generateUuid(false) + kDisplayListExt);

   Error error = r::exec::RFunction(".rs.saveNotebookGraphics",
         lastPlot_.get(), outputFile.absolutePath()).call();
   if (error)
      LOG_ERROR(error);
   else
      snapshotFile_ = outputFile;
}

void PlotCapture::onExprComplete()
{
   r::sexp::Protect protect;

   // no action if no plots were created in this chunk
   if (!hasPlots_)
      return;

   // no action if nothing on device list (implies no graphics output)
   if (!isGraphicsDeviceActive())
      return;

   // if we were expecting a new plot to be produced by the previous
   // expression, process the plot folder
   if (plotPending_)
   {
      plotPending_ = false;
      processPlots(true);
   }

   // check the current state of the graphics device against the last known
   // state
   SEXP plot = R_NilValue;
   Error error = r::exec::RFunction("recordPlot").call(&plot, &protect);
   if (error)
   {
      LOG_ERROR(error);
      return;
   }

   // detect changes and save last state
   bool unchanged = false;
   if (!lastPlot_.isNil())
      r::exec::RFunction("identical", plot, lastPlot_.get()).call(&unchanged);
   lastPlot_.set(plot);

   // if the state changed, reserve an ordinal at this position
   if (!unchanged)
   {
      OutputPair pair = lastChunkOutput(docId_, chunkId_, nbCtxId_);
      lastOrdinal_ = ++pair.ordinal;
      pair.outputType = ChunkOutputPlot;
      updateLastChunkOutput(docId_, chunkId_, pair);

      // notify the client so it can create a placeholder
      json::Object unit;
      unit[kChunkOutputType]    = static_cast<int>(ChunkOutputOrdinal);
      unit[kChunkOutputValue]   = static_cast<int>(lastOrdinal_);
      unit[kChunkOutputOrdinal] = static_cast<int>(lastOrdinal_);
      json::Object placeholder;
      placeholder[kChunkId]         = chunkId_;
      placeholder[kChunkDocId]      = docId_;
      placeholder[kChunkOutputPath] = unit;

      module_context::enqueClientEvent(ClientEvent(
               client_events::kChunkOutput, placeholder));
   }

}

void PlotCapture::removeGraphicsDevice()
{
   // take a snapshot of the last plot's display list before we turn off the
   // device (if we haven't emitted it yet)
   if (hasPlots_ &&
       sizeBehavior_ == PlotSizeAutomatic &&
       snapshotFile_.empty())
      saveSnapshot();

   // turn off the graphics device, if it was ever turned on -- this has the
   // side effect of writing the device's remaining output to files
   if (isGraphicsDeviceActive())
   {
      Error error = r::exec::RFunction("dev.off").call();
      if (error)
         LOG_ERROR(error);
      isGraphicsDeviceActive();

      processPlots(false);
   }
   hasPlots_ = false;
}

void PlotCapture::onBeforeNewPlot()
{
   if (!lastPlot_.isNil())
   {
      // save the snapshot of the plot to disk
      if (sizeBehavior_ == PlotSizeAutomatic)
         saveSnapshot();
   }
   plotPending_ = true;
   hasPlots_ = true;
}

void PlotCapture::onNewPlot()
{
   hasPlots_ = true;
   processPlots(true);
}

// begins capturing plot output
core::Error PlotCapture::connectPlots(const std::string& docId,
      const std::string& chunkId, const std::string& nbCtxId,
      double height, double width, PlotSizeBehavior sizeBehavior,
      const FilePath& plotFolder)
{
   // save identifiers
   docId_ = docId;
   chunkId_ = chunkId;
   nbCtxId_ = nbCtxId;

   // clean up any stale plots from the folder
   plotFolder_ = plotFolder;
   std::vector<FilePath> folderContents;
   Error error = plotFolder.children(&folderContents);
   if (error)
      return error;

   BOOST_FOREACH(const core::FilePath& file, folderContents)
   {
      // remove if it looks like a plot
      if (isPlotPath(file))
      {
         error = file.remove();
         if (error)
         {
            // this is non-fatal
            LOG_ERROR(error);
         }
      }
   }

   // infer height/width if only one is given
   if (height == 0 && width > 0)
      height = width / kGoldenRatio;
   else if (height > 0 && width == 0)
      width = height * kGoldenRatio;
   width_ = width;
   height_ = height;
   sizeBehavior_ = sizeBehavior;

   // save old device option
   deviceOption_.set(r::options::getOption("device"));

   // set option for notebook graphics device (must succeed)
   error = setGraphicsOption();
   if (error)
      return error;

   onBeforeNewPlot_ = plots::events().onBeforeNewPlot.connect(
         boost::bind(&PlotCapture::onBeforeNewPlot, this));

   onBeforeNewGridPage_ = plots::events().onBeforeNewGridPage.connect(
         boost::bind(&PlotCapture::onBeforeNewPlot, this));

   onNewPlot_ = plots::events().onNewPlot.connect(
         boost::bind(&PlotCapture::onNewPlot, this));

   NotebookCapture::connect();
   return Success();
}

void PlotCapture::disconnect()
{
   if (connected())
   {
      // remove the graphics device if we created it
      removeGraphicsDevice();

      // restore the graphics device option
      r::options::setOption("device", deviceOption_.get());

      onNewPlot_.disconnect();
      onBeforeNewPlot_.disconnect();
      onBeforeNewGridPage_.disconnect();
   }
   NotebookCapture::disconnect();
}

core::Error PlotCapture::setGraphicsOption()
{
   Error error;

   // create the notebook graphics device
   r::exec::RFunction setOption(".rs.setNotebookGraphicsOption");

   // the folder in which to place the rendered plots (this is a sibling of the
   // main chunk output folder)
   setOption.addParam(
         plotFolder_.absolutePath() + "/" kPlotPrefix "%03d.png");

   // device dimensions
   setOption.addParam(height_);
   setOption.addParam(width_);

   // sizing behavior drives units -- user specified units are in inches but
   // we use pixels when scaling automatically
   setOption.addParam(sizeBehavior_ == PlotSizeManual ? "in" : "px");

   // device parameters
   setOption.addParam(r::session::graphics::device::devicePixelRatio());

   // other args (OS dependent)
   setOption.addParam(r::session::graphics::extraBitmapParams());

   return setOption.call();
}

bool PlotCapture::isGraphicsDeviceActive()
{
   r::sexp::Protect protect;
   SEXP devlist = R_NilValue;
   Error error = r::exec::RFunction("dev.list").call(&devlist, &protect);
   if (error)
      LOG_ERROR(error);
   if (r::sexp::isNull(devlist))
      return false;
   return true;
}

core::Error initPlots()
{
   ExecBlock initBlock;
   initBlock.addFunctions()
      (boost::bind(module_context::sourceModuleRFile, "NotebookPlots.R"));

   return initBlock.execute();
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio

<commit_msg>notebook: skip plot processing for empty graphics device<commit_after>/*
 * NotebookPlots.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookPlots.hpp"
#include "NotebookOutput.hpp"
#include "../SessionPlots.hpp"

#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/signals/connection.hpp>

#include <core/system/FileMonitor.hpp>
#include <core/StringUtils.hpp>
#include <core/Exec.hpp>

#include <session/SessionModuleContext.hpp>

#include <r/RExec.hpp>
#include <r/RSexp.hpp>
#include <r/session/RGraphics.hpp>
#include <r/ROptions.hpp>

#define kPlotPrefix "_rs_chunk_plot_"
#define kGoldenRatio 1.618

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {
namespace {

bool isPlotPath(const FilePath& path)
{
   return path.hasExtensionLowerCase(".png") &&
          string_utils::isPrefixOf(path.stem(), kPlotPrefix);
}

} // anonymous namespace

PlotCapture::PlotCapture() :
   hasPlots_(false),
   plotPending_(false),
   lastOrdinal_(0)
{
}

PlotCapture::~PlotCapture()
{
}

void PlotCapture::processPlots(bool ignoreEmpty)
{
   // ensure plot folder exists
   if (!plotFolder_.exists())
      return;

   // collect plots from the folder
   std::vector<FilePath> folderContents;
   Error error = plotFolder_.children(&folderContents);
   if (error)
      LOG_ERROR(error);

   BOOST_FOREACH(const FilePath& path, folderContents)
   {
      if (isPlotPath(path))
      {
         // we might find an empty plot file if it hasn't been flushed to disk
         // yet--ignore these
         if (ignoreEmpty && path.size() == 0)
            continue;

         // emit the plot and the snapshot file
         events().onPlotOutput(path, snapshotFile_, lastOrdinal_);

         // we've consumed the snapshot file, so clear it
         snapshotFile_ = FilePath();
         lastOrdinal_ = 0;

         // clean up the plot so it isn't emitted twice
         error = path.removeIfExists();
         if (error)
            LOG_ERROR(error);
      }
   }
}

void PlotCapture::saveSnapshot()
{
   // no work to do if we don't have a display list to write
   if (lastPlot_.isNil())
      return;

   // if there's a plot on the device, write its display list before it's
   // cleared for the next page
   FilePath outputFile = plotFolder_.complete(
         core::system::generateUuid(false) + kDisplayListExt);

   Error error = r::exec::RFunction(".rs.saveNotebookGraphics",
         lastPlot_.get(), outputFile.absolutePath()).call();
   if (error)
      LOG_ERROR(error);
   else
      snapshotFile_ = outputFile;
}

void PlotCapture::onExprComplete()
{
   r::sexp::Protect protect;

   // no action if no plots were created in this chunk
   if (!hasPlots_)
      return;

   // no action if nothing on device list (implies no graphics output)
   if (!isGraphicsDeviceActive())
      return;

   // if we were expecting a new plot to be produced by the previous
   // expression, process the plot folder
   if (plotPending_)
   {
      plotPending_ = false;
      processPlots(true);
   }

   // check the current state of the graphics device against the last known
   // state
   SEXP plot = R_NilValue;
   Error error = r::exec::RFunction("recordPlot").call(&plot, &protect);
   if (error)
   {
      LOG_ERROR(error);
      return;
   }

   // detect changes and save last state
   bool unchanged = false;
   if (!lastPlot_.isNil())
      r::exec::RFunction("identical", plot, lastPlot_.get()).call(&unchanged);
   lastPlot_.set(plot);

   // if the state changed, reserve an ordinal at this position
   if (!unchanged)
   {
      OutputPair pair = lastChunkOutput(docId_, chunkId_, nbCtxId_);
      lastOrdinal_ = ++pair.ordinal;
      pair.outputType = ChunkOutputPlot;
      updateLastChunkOutput(docId_, chunkId_, pair);

      // notify the client so it can create a placeholder
      json::Object unit;
      unit[kChunkOutputType]    = static_cast<int>(ChunkOutputOrdinal);
      unit[kChunkOutputValue]   = static_cast<int>(lastOrdinal_);
      unit[kChunkOutputOrdinal] = static_cast<int>(lastOrdinal_);
      json::Object placeholder;
      placeholder[kChunkId]         = chunkId_;
      placeholder[kChunkDocId]      = docId_;
      placeholder[kChunkOutputPath] = unit;

      module_context::enqueClientEvent(ClientEvent(
               client_events::kChunkOutput, placeholder));
   }

}

void PlotCapture::removeGraphicsDevice()
{
   // take a snapshot of the last plot's display list before we turn off the
   // device (if we haven't emitted it yet)
   if (hasPlots_ &&
       sizeBehavior_ == PlotSizeAutomatic &&
       snapshotFile_.empty())
      saveSnapshot();

   // turn off the graphics device, if it was ever turned on -- this has the
   // side effect of writing the device's remaining output to files
   if (isGraphicsDeviceActive())
   {
      Error error = r::exec::RFunction("dev.off").call();
      if (error)
         LOG_ERROR(error);

      // some operations may trigger the graphics device without actually
      // writing a plot; ignore these
      if (hasPlots_)
         processPlots(false);
   }
   hasPlots_ = false;
}

void PlotCapture::onBeforeNewPlot()
{
   if (!lastPlot_.isNil())
   {
      // save the snapshot of the plot to disk
      if (sizeBehavior_ == PlotSizeAutomatic)
         saveSnapshot();
   }
   plotPending_ = true;
   hasPlots_ = true;
}

void PlotCapture::onNewPlot()
{
   hasPlots_ = true;
   processPlots(true);
}

// begins capturing plot output
core::Error PlotCapture::connectPlots(const std::string& docId,
      const std::string& chunkId, const std::string& nbCtxId,
      double height, double width, PlotSizeBehavior sizeBehavior,
      const FilePath& plotFolder)
{
   // save identifiers
   docId_ = docId;
   chunkId_ = chunkId;
   nbCtxId_ = nbCtxId;

   // clean up any stale plots from the folder
   plotFolder_ = plotFolder;
   std::vector<FilePath> folderContents;
   Error error = plotFolder.children(&folderContents);
   if (error)
      return error;

   BOOST_FOREACH(const core::FilePath& file, folderContents)
   {
      // remove if it looks like a plot
      if (isPlotPath(file))
      {
         error = file.remove();
         if (error)
         {
            // this is non-fatal
            LOG_ERROR(error);
         }
      }
   }

   // infer height/width if only one is given
   if (height == 0 && width > 0)
      height = width / kGoldenRatio;
   else if (height > 0 && width == 0)
      width = height * kGoldenRatio;
   width_ = width;
   height_ = height;
   sizeBehavior_ = sizeBehavior;

   // save old device option
   deviceOption_.set(r::options::getOption("device"));

   // set option for notebook graphics device (must succeed)
   error = setGraphicsOption();
   if (error)
      return error;

   onBeforeNewPlot_ = plots::events().onBeforeNewPlot.connect(
         boost::bind(&PlotCapture::onBeforeNewPlot, this));

   onBeforeNewGridPage_ = plots::events().onBeforeNewGridPage.connect(
         boost::bind(&PlotCapture::onBeforeNewPlot, this));

   onNewPlot_ = plots::events().onNewPlot.connect(
         boost::bind(&PlotCapture::onNewPlot, this));

   NotebookCapture::connect();
   return Success();
}

void PlotCapture::disconnect()
{
   if (connected())
   {
      // remove the graphics device if we created it
      removeGraphicsDevice();

      // restore the graphics device option
      r::options::setOption("device", deviceOption_.get());

      onNewPlot_.disconnect();
      onBeforeNewPlot_.disconnect();
      onBeforeNewGridPage_.disconnect();
   }
   NotebookCapture::disconnect();
}

core::Error PlotCapture::setGraphicsOption()
{
   Error error;

   // create the notebook graphics device
   r::exec::RFunction setOption(".rs.setNotebookGraphicsOption");

   // the folder in which to place the rendered plots (this is a sibling of the
   // main chunk output folder)
   setOption.addParam(
         plotFolder_.absolutePath() + "/" kPlotPrefix "%03d.png");

   // device dimensions
   setOption.addParam(height_);
   setOption.addParam(width_);

   // sizing behavior drives units -- user specified units are in inches but
   // we use pixels when scaling automatically
   setOption.addParam(sizeBehavior_ == PlotSizeManual ? "in" : "px");

   // device parameters
   setOption.addParam(r::session::graphics::device::devicePixelRatio());

   // other args (OS dependent)
   setOption.addParam(r::session::graphics::extraBitmapParams());

   return setOption.call();
}

bool PlotCapture::isGraphicsDeviceActive()
{
   r::sexp::Protect protect;
   SEXP devlist = R_NilValue;
   Error error = r::exec::RFunction("dev.list").call(&devlist, &protect);
   if (error)
      LOG_ERROR(error);
   if (r::sexp::isNull(devlist))
      return false;
   return true;
}

core::Error initPlots()
{
   ExecBlock initBlock;
   initBlock.addFunctions()
      (boost::bind(module_context::sourceModuleRFile, "NotebookPlots.R"));

   return initBlock.execute();
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio

<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/ContingencyTableEvaluation.h>
#include <shogun/evaluation/StratifiedCrossValidationSplitting.h>
#include <shogun/modelselection/GridSearchModelSelection.h>
#include <shogun/modelselection/ModelSelectionParameters.h>
#include <shogun/modelselection/ParameterCombination.h>
#include <shogun/features/Labels.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/classifier/svm/LibLinear.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

CModelSelectionParameters* create_param_tree()
{
	CModelSelectionParameters* root=new CModelSelectionParameters();

	CModelSelectionParameters* c1=new CModelSelectionParameters("C1");
	root->append_child(c1);
	c1->build_values(-15, 15, R_EXP);

	CModelSelectionParameters* c2=new CModelSelectionParameters("C2");
	root->append_child(c2);
	c2->build_values(-15, 15, R_EXP);

	return root;
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);

	int32_t num_subsets=5;
	int32_t num_features=11;

	/* create some data */
	float64_t* matrix=new float64_t[num_features*2];
	for (int32_t i=0; i<num_features*2; i++)
		matrix[i]=i;

	/* create num_feautres 2-dimensional vectors */
	CSimpleFeatures<float64_t>* features=new CSimpleFeatures<float64_t> ();
	features->set_feature_matrix(matrix, 2, num_features);

	/* create three labels */
	CLabels* labels=new CLabels(num_features);
	for (index_t i=0; i<num_features; ++i)
		labels->set_label(i, i%2==0 ? 1 : -1);

	/* create linear classifier (use -s 2 option to avoid warnings) */
	CLibLinear* classifier=new CLibLinear(L2R_L2LOSS_SVC);

	/* splitting strategy */
	CStratifiedCrossValidationSplitting* splitting_strategy=
			new CStratifiedCrossValidationSplitting(labels, num_subsets);

	/* accuracy evaluation */
	CContingencyTableEvaluation* evaluation_criterium=
			new CContingencyTableEvaluation(ACCURACY);

	/* cross validation class for evaluation in model selection */
	CCrossValidation* cross=new CCrossValidation(classifier, features, labels,
			splitting_strategy, evaluation_criterium);

	/* model parameter selection, deletion is handled by modsel class (SG_UNREF) */
	CModelSelectionParameters* param_tree=create_param_tree();

	/* this is on the stack and handles all of the above structures in memory */
	CGridSearchModelSelection grid_search(param_tree, cross);

	float64_t result;
	CParameterCombination* best_combination=grid_search.select_model(result);
	SG_SPRINT("best parameter(s):\n");
	best_combination->print_tree();
	SG_SPRINT("result: %f\n", result);

	/* clean up destroy result parameter */
	SG_UNREF(best_combination);

	SG_SPRINT("\nEND\n");
	exit_shogun();

	return 0;
}

<commit_msg>applied interface changes<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/base/init.h>
#include <shogun/evaluation/CrossValidation.h>
#include <shogun/evaluation/ContingencyTableEvaluation.h>
#include <shogun/evaluation/StratifiedCrossValidationSplitting.h>
#include <shogun/modelselection/GridSearchModelSelection.h>
#include <shogun/modelselection/ModelSelectionParameters.h>
#include <shogun/modelselection/ParameterCombination.h>
#include <shogun/features/Labels.h>
#include <shogun/features/SimpleFeatures.h>
#include <shogun/classifier/svm/LibLinear.h>

using namespace shogun;

void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}

CModelSelectionParameters* create_param_tree()
{
	CModelSelectionParameters* root=new CModelSelectionParameters();

	CModelSelectionParameters* c1=new CModelSelectionParameters("C1");
	root->append_child(c1);
	c1->build_values(-15, 15, R_EXP);

	CModelSelectionParameters* c2=new CModelSelectionParameters("C2");
	root->append_child(c2);
	c2->build_values(-15, 15, R_EXP);

	return root;
}

int main(int argc, char **argv)
{
	init_shogun(&print_message, &print_message, &print_message);

	int32_t num_subsets=5;
	int32_t num_features=11;

	/* create some data */
	float64_t* matrix=new float64_t[num_features*2];
	for (int32_t i=0; i<num_features*2; i++)
		matrix[i]=i;

	/* create num_feautres 2-dimensional vectors */
	CSimpleFeatures<float64_t>* features=new CSimpleFeatures<float64_t> ();
	features->set_feature_matrix(matrix, 2, num_features);

	/* create three labels */
	CLabels* labels=new CLabels(num_features);
	for (index_t i=0; i<num_features; ++i)
		labels->set_label(i, i%2==0 ? 1 : -1);

	/* create linear classifier (use -s 2 option to avoid warnings) */
	CLibLinear* classifier=new CLibLinear(L2R_L2LOSS_SVC);

	/* splitting strategy */
	CStratifiedCrossValidationSplitting* splitting_strategy=
			new CStratifiedCrossValidationSplitting(labels, num_subsets);

	/* accuracy evaluation */
	CContingencyTableEvaluation* evaluation_criterium=
			new CContingencyTableEvaluation(ACCURACY);

	/* cross validation class for evaluation in model selection */
	CCrossValidation* cross=new CCrossValidation(classifier, features, labels,
			splitting_strategy, evaluation_criterium);

	/* model parameter selection, deletion is handled by modsel class (SG_UNREF) */
	CModelSelectionParameters* param_tree=create_param_tree();

	/* this is on the stack and handles all of the above structures in memory */
	CGridSearchModelSelection grid_search(param_tree, cross);

	CParameterCombination* best_combination=grid_search.select_model();
	SG_SPRINT("best parameter(s):\n");
	best_combination->print_tree();

	best_combination->apply_to_machine(classifier);
	SG_SPRINT("result: %f\n", cross->evaluate());

	/* clean up destroy result parameter */
	SG_UNREF(best_combination);

	SG_SPRINT("\nEND\n");
	exit_shogun();

	return 0;
}

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/error_estimation_factory.h"

// libMesh
#include "libmesh/adjoint_residual_error_estimator.h"
#include "libmesh/getpot.h"
#include "libmesh/patch_recovery_error_estimator.h"
#include "libmesh/qoi_set.h"

namespace GRINS
{

  ErrorEstimatorFactory::ErrorEstimatorFactory()
  {
    return;
  }

  ErrorEstimatorFactory::~ErrorEstimatorFactory()
  {
    return;
  }

  std::tr1::shared_ptr<libMesh::ErrorEstimator> ErrorEstimatorFactory::build( const GetPot& input,
                                                                              std::tr1::shared_ptr<QoIBase> qoi_base )
  {
    // check if qoi_base is an empty pointer (user set no QoI), in that case return empty pointer.
    if( qoi_base == std::tr1::shared_ptr<QoIBase>() )
      {
        return std::tr1::shared_ptr<libMesh::ErrorEstimator>();
      }

    std::string estimator_type = input("MeshAdaptivity/estimator_type", "none");

    ErrorEstimatorEnum estimator_enum = this->string_to_enum( estimator_type );

    std::tr1::shared_ptr<libMesh::ErrorEstimator> error_estimator;

    switch( estimator_enum )
      {
      case(ADJOINT_RESIDUAL):
        {
          error_estimator.reset( new libMesh::AdjointResidualErrorEstimator );

          libMesh::AdjointResidualErrorEstimator* adjoint_error_estimator = libmesh_cast_ptr<libMesh::AdjointResidualErrorEstimator*>( error_estimator.get() );

          libMesh::PatchRecoveryErrorEstimator *p1 = new libMesh::PatchRecoveryErrorEstimator;
          adjoint_error_estimator->primal_error_estimator().reset( p1 );

          libMesh::PatchRecoveryErrorEstimator *p2 = new libMesh::PatchRecoveryErrorEstimator;
          adjoint_error_estimator->dual_error_estimator().reset( p2 );

          bool patch_reuse = input( "MeshAdaptivity/patch_reuse", true );
          adjoint_error_estimator->primal_error_estimator()->error_norm.set_type( 0, H1_SEMINORM );
          p1->set_patch_reuse( patch_reuse );

          adjoint_error_estimator->dual_error_estimator()->error_norm.set_type( 0, H1_SEMINORM );
          p2->set_patch_reuse( patch_reuse );
        }
        break;

      case(ADJOINT_REFINEMENT):
      case(KELLY):
      case(PATCH_RECOVERY):
      case(WEIGHTED_PATCH_RECOVERY):
      case(UNIFORM_REFINEMENT):
        {
          libmesh_not_implemented();
        }
      break;

      default:
        {
          std::cerr << "Error: Invalid error estimator type " << estimator_type << std::endl;
          libmesh_error();
        }

      } // switch( estimator_enum )

    return error_estimator;
  }

  ErrorEstimatorFactory::ErrorEstimatorEnum ErrorEstimatorFactory::string_to_enum( const std::string& estimator_type ) const
  {
    ErrorEstimatorEnum value;

    if( estimator_type == std::string("adjoint_residual") )
      {
        value = ADJOINT_RESIDUAL;
      }
    else if( estimator_type == std::string("adjoint_refinement") )
      {
        value = ADJOINT_REFINEMENT;
      }
    else if( estimator_type == std::string("kelly") )
      {
        value = KELLY;
      }
    else if( estimator_type == std::string("patch_recovery") )
      {
        value = PATCH_RECOVERY;
      }
    else if( estimator_type == std::string("weighted_patch_recovery") )
      {
        value = WEIGHTED_PATCH_RECOVERY;
      }
    else if( estimator_type == std::string("uniform_refinement") )
      {
        value = UNIFORM_REFINEMENT;
      }
    else
      {
        std::cerr << "Error: Invalid error estimator type " << estimator_type << std::endl
                  << "Valid error estimator types are: adjoint_residual" << std::endl
                  << "                                 adjoint_refinement" << std::endl
                  << "                                 kelly" << std::endl
                  << "                                 patch_recovery" << std::endl
                  << "                                 weighted_patch_recovery" << std::endl
                  << "                                 uniform_refinement" << std::endl;
        libmesh_error();
      }

    return value;
  }

} // namespace GRINS
<commit_msg>Meh, no need for error message there because that should never happen.<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/error_estimation_factory.h"

// libMesh
#include "libmesh/adjoint_residual_error_estimator.h"
#include "libmesh/getpot.h"
#include "libmesh/patch_recovery_error_estimator.h"
#include "libmesh/qoi_set.h"

namespace GRINS
{

  ErrorEstimatorFactory::ErrorEstimatorFactory()
  {
    return;
  }

  ErrorEstimatorFactory::~ErrorEstimatorFactory()
  {
    return;
  }

  std::tr1::shared_ptr<libMesh::ErrorEstimator> ErrorEstimatorFactory::build( const GetPot& input,
                                                                              std::tr1::shared_ptr<QoIBase> qoi_base )
  {
    // check if qoi_base is an empty pointer (user set no QoI), in that case return empty pointer.
    if( qoi_base == std::tr1::shared_ptr<QoIBase>() )
      {
        return std::tr1::shared_ptr<libMesh::ErrorEstimator>();
      }

    std::string estimator_type = input("MeshAdaptivity/estimator_type", "none");

    ErrorEstimatorEnum estimator_enum = this->string_to_enum( estimator_type );

    std::tr1::shared_ptr<libMesh::ErrorEstimator> error_estimator;

    switch( estimator_enum )
      {
      case(ADJOINT_RESIDUAL):
        {
          error_estimator.reset( new libMesh::AdjointResidualErrorEstimator );

          libMesh::AdjointResidualErrorEstimator* adjoint_error_estimator = libmesh_cast_ptr<libMesh::AdjointResidualErrorEstimator*>( error_estimator.get() );

          libMesh::PatchRecoveryErrorEstimator *p1 = new libMesh::PatchRecoveryErrorEstimator;
          adjoint_error_estimator->primal_error_estimator().reset( p1 );

          libMesh::PatchRecoveryErrorEstimator *p2 = new libMesh::PatchRecoveryErrorEstimator;
          adjoint_error_estimator->dual_error_estimator().reset( p2 );

          bool patch_reuse = input( "MeshAdaptivity/patch_reuse", true );
          adjoint_error_estimator->primal_error_estimator()->error_norm.set_type( 0, H1_SEMINORM );
          p1->set_patch_reuse( patch_reuse );

          adjoint_error_estimator->dual_error_estimator()->error_norm.set_type( 0, H1_SEMINORM );
          p2->set_patch_reuse( patch_reuse );
        }
        break;

      case(ADJOINT_REFINEMENT):
      case(KELLY):
      case(PATCH_RECOVERY):
      case(WEIGHTED_PATCH_RECOVERY):
      case(UNIFORM_REFINEMENT):
        {
          libmesh_not_implemented();
        }
      break;

      // wat?!
      default:
        {
          libmesh_error();
        }

      } // switch( estimator_enum )

    return error_estimator;
  }

  ErrorEstimatorFactory::ErrorEstimatorEnum ErrorEstimatorFactory::string_to_enum( const std::string& estimator_type ) const
  {
    ErrorEstimatorEnum value;

    if( estimator_type == std::string("adjoint_residual") )
      {
        value = ADJOINT_RESIDUAL;
      }
    else if( estimator_type == std::string("adjoint_refinement") )
      {
        value = ADJOINT_REFINEMENT;
      }
    else if( estimator_type == std::string("kelly") )
      {
        value = KELLY;
      }
    else if( estimator_type == std::string("patch_recovery") )
      {
        value = PATCH_RECOVERY;
      }
    else if( estimator_type == std::string("weighted_patch_recovery") )
      {
        value = WEIGHTED_PATCH_RECOVERY;
      }
    else if( estimator_type == std::string("uniform_refinement") )
      {
        value = UNIFORM_REFINEMENT;
      }
    else
      {
        std::cerr << "Error: Invalid error estimator type " << estimator_type << std::endl
                  << "Valid error estimator types are: adjoint_residual" << std::endl
                  << "                                 adjoint_refinement" << std::endl
                  << "                                 kelly" << std::endl
                  << "                                 patch_recovery" << std::endl
                  << "                                 weighted_patch_recovery" << std::endl
                  << "                                 uniform_refinement" << std::endl;
        libmesh_error();
      }

    return value;
  }

} // namespace GRINS
<|endoftext|>


<commit_before>//
// Copyright 2012 Francisco Jerez
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include "core/resource.hpp"
#include "pipe/p_screen.h"
#include "util/u_sampler.h"
#include "util/u_format.h"

using namespace clover;

namespace {
   class box {
   public:
      box(const resource::point &origin, const resource::point &size) :
         pipe({ (int)origin[0], (int)origin[1],
                (int)origin[2], (int)size[0],
                (int)size[1], (int)size[2] }) {
      }

      operator const pipe_box *() {
         return &pipe;
      }

   protected:
      pipe_box pipe;
   };
}

resource::resource(clover::device &dev, clover::memory_obj &obj) :
   dev(dev), obj(obj), pipe(NULL), offset{0} {
}

resource::~resource() {
}

void
resource::copy(command_queue &q, const point &origin, const point &region,
               resource &src_res, const point &src_origin) {
   point p = offset + origin;

   q.pipe->resource_copy_region(q.pipe, pipe, 0, p[0], p[1], p[2],
                                src_res.pipe, 0,
                                box(src_res.offset + src_origin, region));
}

void *
resource::add_map(command_queue &q, cl_map_flags flags, bool blocking,
                  const point &origin, const point &region) {
   maps.emplace_back(q, *this, flags, blocking, origin, region);
   return maps.back();
}

void
resource::del_map(void *p) {
   auto it = std::find(maps.begin(), maps.end(), p);
   if (it != maps.end())
      maps.erase(it);
}

unsigned
resource::map_count() const {
   return maps.size();
}

pipe_sampler_view *
resource::bind_sampler_view(clover::command_queue &q) {
   pipe_sampler_view info;

   u_sampler_view_default_template(&info, pipe, pipe->format);
   return q.pipe->create_sampler_view(q.pipe, pipe, &info);
}

void
resource::unbind_sampler_view(clover::command_queue &q,
                              pipe_sampler_view *st) {
   q.pipe->sampler_view_destroy(q.pipe, st);
}

pipe_surface *
resource::bind_surface(clover::command_queue &q, bool rw) {
   pipe_surface info {};

   info.format = pipe->format;
   info.usage = pipe->bind;
   info.writable = rw;

   if (pipe->target == PIPE_BUFFER)
      info.u.buf.last_element = pipe->width0 - 1;

   return q.pipe->create_surface(q.pipe, pipe, &info);
}

void
resource::unbind_surface(clover::command_queue &q, pipe_surface *st) {
   q.pipe->surface_destroy(q.pipe, st);
}

root_resource::root_resource(clover::device &dev, clover::memory_obj &obj,
                             clover::command_queue &q,
                             const std::string &data) :
   resource(dev, obj) {
   pipe_resource info {};

   if (image *img = dynamic_cast<image *>(&obj)) {
      info.format = translate_format(img->format());
      info.width0 = img->width();
      info.height0 = img->height();
      info.depth0 = img->depth();
   } else {
      info.width0 = obj.size();
      info.height0 = 1;
      info.depth0 = 1;
   }

   info.target = translate_target(obj.type());
   info.bind = (PIPE_BIND_SAMPLER_VIEW |
                PIPE_BIND_COMPUTE_RESOURCE |
                PIPE_BIND_GLOBAL |
                PIPE_BIND_TRANSFER_READ |
                PIPE_BIND_TRANSFER_WRITE);

   pipe = dev.pipe->resource_create(dev.pipe, &info);
   if (!pipe)
      throw error(CL_OUT_OF_RESOURCES);

   if (!data.empty()) {
      box rect { { 0, 0, 0 }, { info.width0, info.height0, info.depth0 } };
      unsigned cpp = util_format_get_blocksize(info.format);

      q.pipe->transfer_inline_write(q.pipe, pipe, 0, PIPE_TRANSFER_WRITE,
                                    rect, data.data(), cpp * info.width0,
                                    cpp * info.width0 * info.height0);
   }
}

root_resource::root_resource(clover::device &dev, clover::memory_obj &obj,
                             clover::root_resource &r) :
   resource(dev, obj) {
   assert(0); // XXX -- resource shared among dev and r.dev
}

root_resource::~root_resource() {
   dev.pipe->resource_destroy(dev.pipe, pipe);
}

sub_resource::sub_resource(clover::resource &r, point offset) :
   resource(r.dev, r.obj) {
   pipe = r.pipe;
   offset = r.offset + offset;
}

mapping::mapping(command_queue &q, resource &r,
                 cl_map_flags flags, bool blocking,
                 const resource::point &origin,
                 const resource::point &region) :
   pctx(q.pipe) {
   unsigned usage = ((flags & CL_MAP_WRITE ? PIPE_TRANSFER_WRITE : 0 ) |
                     (flags & CL_MAP_READ ? PIPE_TRANSFER_READ : 0 ) |
                     (blocking ? PIPE_TRANSFER_UNSYNCHRONIZED : 0));

   p = pctx->transfer_map(pctx, r.pipe, 0, usage,
                          box(origin + r.offset, region), &pxfer);
   if (!p) {
      pxfer = NULL;
      throw error(CL_OUT_OF_RESOURCES);
   }
}

mapping::mapping(mapping &&m) :
   pctx(m.pctx), pxfer(m.pxfer), p(m.p) {
   m.p = NULL;
   m.pxfer = NULL;
}

mapping::~mapping() {
   if (pxfer) {
      pctx->transfer_unmap(pctx, pxfer);
   }
}
<commit_msg>clover: Fix build since removal of pipe_surface::usage<commit_after>//
// Copyright 2012 Francisco Jerez
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#include "core/resource.hpp"
#include "pipe/p_screen.h"
#include "util/u_sampler.h"
#include "util/u_format.h"

using namespace clover;

namespace {
   class box {
   public:
      box(const resource::point &origin, const resource::point &size) :
         pipe({ (int)origin[0], (int)origin[1],
                (int)origin[2], (int)size[0],
                (int)size[1], (int)size[2] }) {
      }

      operator const pipe_box *() {
         return &pipe;
      }

   protected:
      pipe_box pipe;
   };
}

resource::resource(clover::device &dev, clover::memory_obj &obj) :
   dev(dev), obj(obj), pipe(NULL), offset{0} {
}

resource::~resource() {
}

void
resource::copy(command_queue &q, const point &origin, const point &region,
               resource &src_res, const point &src_origin) {
   point p = offset + origin;

   q.pipe->resource_copy_region(q.pipe, pipe, 0, p[0], p[1], p[2],
                                src_res.pipe, 0,
                                box(src_res.offset + src_origin, region));
}

void *
resource::add_map(command_queue &q, cl_map_flags flags, bool blocking,
                  const point &origin, const point &region) {
   maps.emplace_back(q, *this, flags, blocking, origin, region);
   return maps.back();
}

void
resource::del_map(void *p) {
   auto it = std::find(maps.begin(), maps.end(), p);
   if (it != maps.end())
      maps.erase(it);
}

unsigned
resource::map_count() const {
   return maps.size();
}

pipe_sampler_view *
resource::bind_sampler_view(clover::command_queue &q) {
   pipe_sampler_view info;

   u_sampler_view_default_template(&info, pipe, pipe->format);
   return q.pipe->create_sampler_view(q.pipe, pipe, &info);
}

void
resource::unbind_sampler_view(clover::command_queue &q,
                              pipe_sampler_view *st) {
   q.pipe->sampler_view_destroy(q.pipe, st);
}

pipe_surface *
resource::bind_surface(clover::command_queue &q, bool rw) {
   pipe_surface info {};

   info.format = pipe->format;
   info.writable = rw;

   if (pipe->target == PIPE_BUFFER)
      info.u.buf.last_element = pipe->width0 - 1;

   return q.pipe->create_surface(q.pipe, pipe, &info);
}

void
resource::unbind_surface(clover::command_queue &q, pipe_surface *st) {
   q.pipe->surface_destroy(q.pipe, st);
}

root_resource::root_resource(clover::device &dev, clover::memory_obj &obj,
                             clover::command_queue &q,
                             const std::string &data) :
   resource(dev, obj) {
   pipe_resource info {};

   if (image *img = dynamic_cast<image *>(&obj)) {
      info.format = translate_format(img->format());
      info.width0 = img->width();
      info.height0 = img->height();
      info.depth0 = img->depth();
   } else {
      info.width0 = obj.size();
      info.height0 = 1;
      info.depth0 = 1;
   }

   info.target = translate_target(obj.type());
   info.bind = (PIPE_BIND_SAMPLER_VIEW |
                PIPE_BIND_COMPUTE_RESOURCE |
                PIPE_BIND_GLOBAL |
                PIPE_BIND_TRANSFER_READ |
                PIPE_BIND_TRANSFER_WRITE);

   pipe = dev.pipe->resource_create(dev.pipe, &info);
   if (!pipe)
      throw error(CL_OUT_OF_RESOURCES);

   if (!data.empty()) {
      box rect { { 0, 0, 0 }, { info.width0, info.height0, info.depth0 } };
      unsigned cpp = util_format_get_blocksize(info.format);

      q.pipe->transfer_inline_write(q.pipe, pipe, 0, PIPE_TRANSFER_WRITE,
                                    rect, data.data(), cpp * info.width0,
                                    cpp * info.width0 * info.height0);
   }
}

root_resource::root_resource(clover::device &dev, clover::memory_obj &obj,
                             clover::root_resource &r) :
   resource(dev, obj) {
   assert(0); // XXX -- resource shared among dev and r.dev
}

root_resource::~root_resource() {
   dev.pipe->resource_destroy(dev.pipe, pipe);
}

sub_resource::sub_resource(clover::resource &r, point offset) :
   resource(r.dev, r.obj) {
   pipe = r.pipe;
   offset = r.offset + offset;
}

mapping::mapping(command_queue &q, resource &r,
                 cl_map_flags flags, bool blocking,
                 const resource::point &origin,
                 const resource::point &region) :
   pctx(q.pipe) {
   unsigned usage = ((flags & CL_MAP_WRITE ? PIPE_TRANSFER_WRITE : 0 ) |
                     (flags & CL_MAP_READ ? PIPE_TRANSFER_READ : 0 ) |
                     (blocking ? PIPE_TRANSFER_UNSYNCHRONIZED : 0));

   p = pctx->transfer_map(pctx, r.pipe, 0, usage,
                          box(origin + r.offset, region), &pxfer);
   if (!p) {
      pxfer = NULL;
      throw error(CL_OUT_OF_RESOURCES);
   }
}

mapping::mapping(mapping &&m) :
   pctx(m.pctx), pxfer(m.pxfer), p(m.p) {
   m.p = NULL;
   m.pxfer = NULL;
}

mapping::~mapping() {
   if (pxfer) {
      pctx->transfer_unmap(pctx, pxfer);
   }
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "referencefieldvalue.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <cassert>

using vespalib::IllegalArgumentException;
using vespalib::make_string;

namespace document {

IMPLEMENT_IDENTIFIABLE(ReferenceFieldValue, FieldValue);

ReferenceFieldValue::ReferenceFieldValue()
    : _dataType(nullptr),
      _documentId(),
      _altered(true)
{
}

ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType)
    : _dataType(&dataType),
      _documentId(),
      _altered(true)
{
}

ReferenceFieldValue::ReferenceFieldValue(
        const ReferenceDataType& dataType,
        const DocumentId& documentId)
    : _dataType(&dataType),
      _documentId(documentId),
      _altered(true)
{
    requireIdOfMatchingType(_documentId, _dataType->getTargetType());
}

ReferenceFieldValue::~ReferenceFieldValue() {
}

void ReferenceFieldValue::requireIdOfMatchingType(
        const DocumentId& id, const DocumentType& type)
{
    if (id.getDocType() != type.getName()) {
        throw IllegalArgumentException(
                make_string("Can't assign document ID '%s' (of type '%s') to "
                            "reference of document type '%s'",
                            id.toString().c_str(),
                            id.getDocType().c_str(),
                            type.getName().c_str()),
                VESPA_STRLOC);
    }
}

FieldValue& ReferenceFieldValue::assign(const FieldValue& rhs) {
    const auto* refValueRhs(dynamic_cast<const ReferenceFieldValue*>(&rhs));
    if (refValueRhs != nullptr) {
        if (refValueRhs == this) {
            return *this;
        }
        _documentId = refValueRhs->_documentId;
        _dataType = refValueRhs->_dataType;
        _altered = true;
    } else {
        throw IllegalArgumentException(
                make_string("Can't assign field value of type %s to "
                            "a ReferenceFieldValue",
                            rhs.getDataType()->getName().c_str()),
                VESPA_STRLOC);
    }
    return *this;
}

void ReferenceFieldValue::setDeserializedDocumentId(const DocumentId& id) {
    assert(_dataType != nullptr);
    requireIdOfMatchingType(id, _dataType->getTargetType());
    _documentId = id;
    _altered = false;
}

ReferenceFieldValue* ReferenceFieldValue::clone() const {
    assert(_dataType != nullptr);
    return new ReferenceFieldValue(*_dataType, _documentId);
}

int ReferenceFieldValue::compare(const FieldValue& rhs) const {
    const int parentCompare = FieldValue::compare(rhs);
    if (parentCompare != 0) {
        return parentCompare;
    }
    // Type equality is checked by the parent.
    const auto& refValueRhs(dynamic_cast<const ReferenceFieldValue&>(rhs));
    // TODO PERF: DocumentId does currently _not_ expose any methods that
    // cheaply allow an ordering to be established. Only (in)equality operators.
    // IdString::operator== is already implemented in the same way as this, so
    // don't put this code in your inner loops, kids!
    return _documentId.toString().compare(refValueRhs._documentId.toString());
}

void ReferenceFieldValue::print(std::ostream& os, bool verbose, const std::string& indent) const {
    (void) verbose;
    (void) indent;
    assert(_dataType != nullptr);
    os << "ReferenceFieldValue(" << *_dataType << ", DocumentId(";
    _documentId.print(os, false, "");
    os << "))";
}

bool ReferenceFieldValue::hasChanged() const {
    return _altered;
}

void ReferenceFieldValue::accept(FieldValueVisitor& visitor) {
    visitor.visit(*this);
}

void ReferenceFieldValue::accept(ConstFieldValueVisitor& visitor) const {
    visitor.visit(*this);
}

} // document
<commit_msg>Simplify branching<commit_after>// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "referencefieldvalue.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <cassert>

using vespalib::IllegalArgumentException;
using vespalib::make_string;

namespace document {

IMPLEMENT_IDENTIFIABLE(ReferenceFieldValue, FieldValue);

ReferenceFieldValue::ReferenceFieldValue()
    : _dataType(nullptr),
      _documentId(),
      _altered(true)
{
}

ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType)
    : _dataType(&dataType),
      _documentId(),
      _altered(true)
{
}

ReferenceFieldValue::ReferenceFieldValue(
        const ReferenceDataType& dataType,
        const DocumentId& documentId)
    : _dataType(&dataType),
      _documentId(documentId),
      _altered(true)
{
    requireIdOfMatchingType(_documentId, _dataType->getTargetType());
}

ReferenceFieldValue::~ReferenceFieldValue() {
}

void ReferenceFieldValue::requireIdOfMatchingType(
        const DocumentId& id, const DocumentType& type)
{
    if (id.getDocType() != type.getName()) {
        throw IllegalArgumentException(
                make_string("Can't assign document ID '%s' (of type '%s') to "
                            "reference of document type '%s'",
                            id.toString().c_str(),
                            id.getDocType().c_str(),
                            type.getName().c_str()),
                VESPA_STRLOC);
    }
}

FieldValue& ReferenceFieldValue::assign(const FieldValue& rhs) {
    const auto* refValueRhs(dynamic_cast<const ReferenceFieldValue*>(&rhs));
    if (refValueRhs == nullptr) {
        throw IllegalArgumentException(
                make_string("Can't assign field value of type %s to "
                            "a ReferenceFieldValue",
                            rhs.getDataType()->getName().c_str()),
                VESPA_STRLOC);
    }
    if (refValueRhs == this) {
        return *this;
    }
    _documentId = refValueRhs->_documentId;
    _dataType = refValueRhs->_dataType;
    _altered = true;
    return *this;
}

void ReferenceFieldValue::setDeserializedDocumentId(const DocumentId& id) {
    assert(_dataType != nullptr);
    requireIdOfMatchingType(id, _dataType->getTargetType());
    _documentId = id;
    _altered = false;
}

ReferenceFieldValue* ReferenceFieldValue::clone() const {
    assert(_dataType != nullptr);
    return new ReferenceFieldValue(*_dataType, _documentId);
}

int ReferenceFieldValue::compare(const FieldValue& rhs) const {
    const int parentCompare = FieldValue::compare(rhs);
    if (parentCompare != 0) {
        return parentCompare;
    }
    // Type equality is checked by the parent.
    const auto& refValueRhs(dynamic_cast<const ReferenceFieldValue&>(rhs));
    // TODO PERF: DocumentId does currently _not_ expose any methods that
    // cheaply allow an ordering to be established. Only (in)equality operators.
    // IdString::operator== is already implemented in the same way as this, so
    // don't put this code in your inner loops, kids!
    return _documentId.toString().compare(refValueRhs._documentId.toString());
}

void ReferenceFieldValue::print(std::ostream& os, bool verbose, const std::string& indent) const {
    (void) verbose;
    (void) indent;
    assert(_dataType != nullptr);
    os << "ReferenceFieldValue(" << *_dataType << ", DocumentId(";
    _documentId.print(os, false, "");
    os << "))";
}

bool ReferenceFieldValue::hasChanged() const {
    return _altered;
}

void ReferenceFieldValue::accept(FieldValueVisitor& visitor) {
    visitor.visit(*this);
}

void ReferenceFieldValue::accept(ConstFieldValueVisitor& visitor) const {
    visitor.visit(*this);
}

} // document
<|endoftext|>