<commit_before>#include "pch.h"

#include "GameAnalyticsInterface.h"

#include <ppltasks.h>

using namespace GameAnalytics;

using namespace concurrency;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Security::Cryptography;
using namespace Windows::Security::Cryptography::Core;
using namespace Windows::Web::Http;
using namespace Windows::Web::Http::Headers;

GameAnalyticsInterface::GameAnalyticsInterface(const std::wstring & gameKey, const std::wstring & secretKey)
	: httpClient(ref new Windows::Web::Http::HttpClient()),
	gameKey(gameKey),
	secretKey(secretKey),
	build(this->GetAppVersion()),
	sessionId(this->GenerateSessionId()),
	userId(this->GetHardwareId())
{
}

void GameAnalyticsInterface::SendBusinessEvent(const std::wstring & eventId, const std::wstring & currency, const int amount) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"event_id", eventId));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"currency", currency));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"amount", std::to_wstring(amount)));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"business", parameters);
}

void GameAnalyticsInterface::SendDesignEvent(const std::wstring & eventId) const
{
	// Build parameter map.
	auto parameters = this->BuildDesignParameterMap(eventId);

	// Send event.
	this->SendGameAnalyticsEvent(L"design", parameters);
}

void GameAnalyticsInterface::SendDesignEvent(const std::wstring & eventId, const float value) const
{
	// Build parameter map.
	auto parameters = this->BuildDesignParameterMap(eventId);
	parameters.insert(std::pair<std::wstring, std::wstring>(L"value", std::to_wstring(value)));

	// Send event.
	this->SendGameAnalyticsEvent(L"design", parameters);
}

void GameAnalyticsInterface::SendErrorEvent(const std::wstring & message, const Severity::Severity severity) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"message", message));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"severity", Severity::ToWString(severity)));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"error", parameters);
}

void GameAnalyticsInterface::SendUserEvent(const User & user) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();

	if (user.gender != Gender::Unknown)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"gender", Gender::ToWString(user.gender)));
	}

	if (user.birthYear >= 0)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"birth_year", std::to_wstring(user.birthYear)));
	}

	if (user.friendCount >= 0)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"friend_count", std::to_wstring(user.friendCount)));
	}

	if (!user.facebookId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"facebook_id", user.facebookId));
	}

	if (!user.googlePlusId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"googleplus_id", user.googlePlusId));
	}

	if (!user.iOSId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"ios_id", user.iOSId));
	}

	if (!user.androidId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"android_id", user.androidId));
	}

	if (!user.adTruthId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"adtruth_id", user.adTruthId));
	}

	if (!user.platform.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"platform", user.platform));
	}

	if (!user.device.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"device", user.device));
	}

	if (!user.osMajor.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"os_major", user.osMajor));
	}

	if (!user.osMinor.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"os_minor", user.osMinor));
	}

	if (!user.installPublisher.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_publisher", user.installPublisher));
	}

	if (!user.installSite.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_site", user.installSite));
	}

	if (!user.installCampaign.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_campaign", user.installCampaign));
	}

	if (!user.installAdGroup.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_adgroup", user.installAdGroup));
	}

	if (!user.installAd.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_ad", user.installAd));
	}

	if (!user.installKeyword.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_keyword", user.installKeyword));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"user", parameters);
}

void GameAnalyticsInterface::SetArea(const std::wstring & area)
{
	this->area = area;
}

void GameAnalyticsInterface::SetBuild(const std::wstring & build)
{
	this->build = build;
}

void GameAnalyticsInterface::SetUserId(const std::wstring & userId)
{
	this->userId = userId;
}

std::map<std::wstring, std::wstring> GameAnalyticsInterface::BuildDesignParameterMap(const std::wstring & eventId) const
{
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"eventId", eventId));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	return parameters;
}

std::wstring GameAnalyticsInterface::GenerateSessionId() const
{
	GUID result;
	HRESULT hr = CoCreateGuid(&result);

	if (SUCCEEDED(hr))
	{
		// Generate new GUID.
		Guid guid(result);
		auto guidString = std::wstring(guid.ToString()->Data());

		// Remove curly brackets.
		auto sessionId = guidString.substr(1, guidString.length() - 2);
		return sessionId;
	}

	throw Exception::CreateException(hr);
}

std::wstring GameAnalyticsInterface::GetAppVersion() const
{
	auto thisPackage = Windows::ApplicationModel::Package::Current;
	auto version = thisPackage->Id->Version;
	return std::wstring(std::to_wstring(version.Major)
		+ L"." + std::to_wstring(version.Minor)
		+ L"." + std::to_wstring(version.Build)
		+ L"." + std::to_wstring(version.Revision));
}

std::wstring GameAnalyticsInterface::GetHardwareId() const
{
	auto packageSpecificToken = Windows::System::Profile::HardwareIdentification::GetPackageSpecificToken(nullptr);
	auto hardwareId = packageSpecificToken->Id;
	auto hardwareIdString = CryptographicBuffer::EncodeToHexString(hardwareId);
	return std::wstring(hardwareIdString->Data());
}

void GameAnalyticsInterface::SendGameAnalyticsEvent(const std::wstring & category, const std::map<std::wstring, std::wstring> & parameters) const
{
	// Build event JSON.
	// http://support.gameanalytics.com/hc/en-us/articles/200841486-General-event-structure
	// http://support.gameanalytics.com/hc/en-us/articles/200841506-Design-event-structure

	std::wstring json = L"[";
	json.append(L"{");

	// Add header.
	json.append(L"\"user_id\":\"" + this->userId + L"\",");
	json.append(L"\"session_id\":\"" + this->sessionId + L"\",");
	json.append(L"\"build\":\"" + this->build + L"\"");

	// Add category specific parameters.
	for (auto it = parameters.begin(); it != parameters.end(); ++it)
	{
		json.append(L",\"" + it->first + L"\":\"" + it->second + L"\"");
	}

	json.append(L"}");
	json.append(L"]");

	// Generate MD5 of event data and secret key.
	auto jsonAndSecretKey = json + this->secretKey;
	auto jsonAndSecretKeyString = ref new String(jsonAndSecretKey.c_str());

	auto alg = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Md5);
	auto buff = CryptographicBuffer::ConvertStringToBinary(jsonAndSecretKeyString, BinaryStringEncoding::Utf8);
	auto hashed = alg->HashData(buff);
	auto digest = CryptographicBuffer::EncodeToHexString(hashed);

	// Build category URL.
	std::wstring relativeUrl = this->gameKey + L"/" + category;
	std::wstring absoluteUrl = L"http://api.gameanalytics.com/1/" + relativeUrl;
	auto absoluteUrlString = ref new String(absoluteUrl.c_str());

	// Send event to GameAnalytics.
	auto message = ref new HttpRequestMessage();

	message->RequestUri = ref new Uri(absoluteUrlString);
	message->Method = HttpMethod::Post;
	message->Content = ref new HttpStringContent
		(ref new Platform::String(json.c_str()),
		Windows::Storage::Streams::UnicodeEncoding::Utf8,
		ref new Platform::String(L"application/json"));
	message->Headers->TryAppendWithoutValidation(L"Authorization", digest);

	auto response = ref new HttpResponseMessage();

	create_task(httpClient->SendRequestAsync(message)).then([=](HttpResponseMessage^ response)
	{
		// Validate HTTP status code.
		response->EnsureSuccessStatusCode();
		return create_task(response->Content->ReadAsStringAsync());
	}).then([=](String^ responseBodyAsText){
		// Verify response.
		auto responseString = std::wstring(responseBodyAsText->Data());

		if (responseString.find(L"{\"status\":\"ok\"}") == std::string::npos)
		{
			auto message = L"Error sending analytics event: " + responseString;
			auto messageString = ref new Platform::String(message.c_str());
			throw ref new Platform::FailureException(messageString);
		}
	});
}
<commit_msg>FIXED: Event Data - Invalid design event header.<commit_after>#include "pch.h"

#include "GameAnalyticsInterface.h"

#include <ppltasks.h>

using namespace GameAnalytics;

using namespace concurrency;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Security::Cryptography;
using namespace Windows::Security::Cryptography::Core;
using namespace Windows::Web::Http;
using namespace Windows::Web::Http::Headers;

GameAnalyticsInterface::GameAnalyticsInterface(const std::wstring & gameKey, const std::wstring & secretKey)
	: httpClient(ref new Windows::Web::Http::HttpClient()),
	gameKey(gameKey),
	secretKey(secretKey),
	build(this->GetAppVersion()),
	sessionId(this->GenerateSessionId()),
	userId(this->GetHardwareId())
{
}

void GameAnalyticsInterface::SendBusinessEvent(const std::wstring & eventId, const std::wstring & currency, const int amount) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"event_id", eventId));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"currency", currency));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"amount", std::to_wstring(amount)));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"business", parameters);
}

void GameAnalyticsInterface::SendDesignEvent(const std::wstring & eventId) const
{
	// Build parameter map.
	auto parameters = this->BuildDesignParameterMap(eventId);

	// Send event.
	this->SendGameAnalyticsEvent(L"design", parameters);
}

void GameAnalyticsInterface::SendDesignEvent(const std::wstring & eventId, const float value) const
{
	// Build parameter map.
	auto parameters = this->BuildDesignParameterMap(eventId);
	parameters.insert(std::pair<std::wstring, std::wstring>(L"value", std::to_wstring(value)));

	// Send event.
	this->SendGameAnalyticsEvent(L"design", parameters);
}

void GameAnalyticsInterface::SendErrorEvent(const std::wstring & message, const Severity::Severity severity) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"message", message));
	parameters.insert(std::pair<std::wstring, std::wstring>(L"severity", Severity::ToWString(severity)));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"error", parameters);
}

void GameAnalyticsInterface::SendUserEvent(const User & user) const
{
	// Build parameter map.
	auto parameters = std::map<std::wstring, std::wstring>();

	if (user.gender != Gender::Unknown)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"gender", Gender::ToWString(user.gender)));
	}

	if (user.birthYear >= 0)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"birth_year", std::to_wstring(user.birthYear)));
	}

	if (user.friendCount >= 0)
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"friend_count", std::to_wstring(user.friendCount)));
	}

	if (!user.facebookId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"facebook_id", user.facebookId));
	}

	if (!user.googlePlusId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"googleplus_id", user.googlePlusId));
	}

	if (!user.iOSId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"ios_id", user.iOSId));
	}

	if (!user.androidId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"android_id", user.androidId));
	}

	if (!user.adTruthId.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"adtruth_id", user.adTruthId));
	}

	if (!user.platform.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"platform", user.platform));
	}

	if (!user.device.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"device", user.device));
	}

	if (!user.osMajor.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"os_major", user.osMajor));
	}

	if (!user.osMinor.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"os_minor", user.osMinor));
	}

	if (!user.installPublisher.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_publisher", user.installPublisher));
	}

	if (!user.installSite.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_site", user.installSite));
	}

	if (!user.installCampaign.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_campaign", user.installCampaign));
	}

	if (!user.installAdGroup.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_adgroup", user.installAdGroup));
	}

	if (!user.installAd.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_ad", user.installAd));
	}

	if (!user.installKeyword.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"install_keyword", user.installKeyword));
	}

	// Send event.
	this->SendGameAnalyticsEvent(L"user", parameters);
}

void GameAnalyticsInterface::SetArea(const std::wstring & area)
{
	this->area = area;
}

void GameAnalyticsInterface::SetBuild(const std::wstring & build)
{
	this->build = build;
}

void GameAnalyticsInterface::SetUserId(const std::wstring & userId)
{
	this->userId = userId;
}

std::map<std::wstring, std::wstring> GameAnalyticsInterface::BuildDesignParameterMap(const std::wstring & eventId) const
{
	auto parameters = std::map<std::wstring, std::wstring>();
	parameters.insert(std::pair<std::wstring, std::wstring>(L"event_id", eventId));

	if (!this->area.empty())
	{
		parameters.insert(std::pair<std::wstring, std::wstring>(L"area", area));
	}

	return parameters;
}

std::wstring GameAnalyticsInterface::GenerateSessionId() const
{
	GUID result;
	HRESULT hr = CoCreateGuid(&result);

	if (SUCCEEDED(hr))
	{
		// Generate new GUID.
		Guid guid(result);
		auto guidString = std::wstring(guid.ToString()->Data());

		// Remove curly brackets.
		auto sessionId = guidString.substr(1, guidString.length() - 2);
		return sessionId;
	}

	throw Exception::CreateException(hr);
}

std::wstring GameAnalyticsInterface::GetAppVersion() const
{
	auto thisPackage = Windows::ApplicationModel::Package::Current;
	auto version = thisPackage->Id->Version;
	return std::wstring(std::to_wstring(version.Major)
		+ L"." + std::to_wstring(version.Minor)
		+ L"." + std::to_wstring(version.Build)
		+ L"." + std::to_wstring(version.Revision));
}

std::wstring GameAnalyticsInterface::GetHardwareId() const
{
	auto packageSpecificToken = Windows::System::Profile::HardwareIdentification::GetPackageSpecificToken(nullptr);
	auto hardwareId = packageSpecificToken->Id;
	auto hardwareIdString = CryptographicBuffer::EncodeToHexString(hardwareId);
	return std::wstring(hardwareIdString->Data());
}

void GameAnalyticsInterface::SendGameAnalyticsEvent(const std::wstring & category, const std::map<std::wstring, std::wstring> & parameters) const
{
	// Build event JSON.
	// http://support.gameanalytics.com/hc/en-us/articles/200841486-General-event-structure
	// http://support.gameanalytics.com/hc/en-us/articles/200841506-Design-event-structure

	std::wstring json = L"[";
	json.append(L"{");

	// Add header.
	json.append(L"\"user_id\":\"" + this->userId + L"\",");
	json.append(L"\"session_id\":\"" + this->sessionId + L"\",");
	json.append(L"\"build\":\"" + this->build + L"\"");

	// Add category specific parameters.
	for (auto it = parameters.begin(); it != parameters.end(); ++it)
	{
		json.append(L",\"" + it->first + L"\":\"" + it->second + L"\"");
	}

	json.append(L"}");
	json.append(L"]");

	// Generate MD5 of event data and secret key.
	auto jsonAndSecretKey = json + this->secretKey;
	auto jsonAndSecretKeyString = ref new String(jsonAndSecretKey.c_str());

	auto alg = HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Md5);
	auto buff = CryptographicBuffer::ConvertStringToBinary(jsonAndSecretKeyString, BinaryStringEncoding::Utf8);
	auto hashed = alg->HashData(buff);
	auto digest = CryptographicBuffer::EncodeToHexString(hashed);

	// Build category URL.
	std::wstring relativeUrl = this->gameKey + L"/" + category;
	std::wstring absoluteUrl = L"http://api.gameanalytics.com/1/" + relativeUrl;
	auto absoluteUrlString = ref new String(absoluteUrl.c_str());

	// Send event to GameAnalytics.
	auto message = ref new HttpRequestMessage();

	message->RequestUri = ref new Uri(absoluteUrlString);
	message->Method = HttpMethod::Post;
	message->Content = ref new HttpStringContent
		(ref new Platform::String(json.c_str()),
		Windows::Storage::Streams::UnicodeEncoding::Utf8,
		ref new Platform::String(L"application/json"));
	message->Headers->TryAppendWithoutValidation(L"Authorization", digest);

	auto response = ref new HttpResponseMessage();

	create_task(httpClient->SendRequestAsync(message)).then([=](HttpResponseMessage^ response)
	{
		// Validate HTTP status code.
		response->EnsureSuccessStatusCode();
		return create_task(response->Content->ReadAsStringAsync());
	}).then([=](String^ responseBodyAsText){
		// Verify response.
		auto responseString = std::wstring(responseBodyAsText->Data());

		if (responseString.find(L"{\"status\":\"ok\"}") == std::string::npos)
		{
			auto message = L"Error sending analytics event: " + responseString;
			auto messageString = ref new Platform::String(message.c_str());
			throw ref new Platform::FailureException(messageString);
		}
	});
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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/gtk/gtk_chrome_link_button.h"

#include <stdlib.h>

#include "base/logging.h"
#include "chrome/common/gtk_util.h"

static const gchar* kLinkMarkup = "%s";

namespace {

// Set the GTK style on our custom link button. We don't want any border around
// the link text.
void SetLinkButtonStyle() {
  static bool style_was_set = false;

  if (style_was_set)
    return;
  style_was_set = true;

  gtk_rc_parse_string(
      "style \"chrome-link-button\" {"
      "  GtkButton::inner-border = {0, 0, 0, 0}"
      "  GtkButton::child-displacement-x = 0"
      "  GtkButton::child-displacement-y = 0"
      "  xthickness = 0"
      "  ythickness = 0"
      "}"
      "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
}

static void gtk_chrome_link_button_destroy_text_resources(
    GtkChromeLinkButton* button) {
  g_free(button->native_markup);
  button->native_markup = NULL;
  g_free(button->normal_markup);
  button->normal_markup = NULL;
  g_free(button->pressed_markup);
  button->pressed_markup = NULL;

  g_free(button->text);
  button->text = NULL;
}

}  // namespace

G_BEGIN_DECLS
G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)

// Should be called after we are realized so that the "link-color" property
// can be read.
static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
  // We only set the markup once.
  if (button->normal_markup)
    return;

  gchar* text = button->text;
  gboolean uses_markup = button->uses_markup;

  if (!uses_markup) {
    button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
                                                    button->normal_color,
                                                    text);
    button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
  } else {
    button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
                                            text);

    button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
  }

  // Get the current GTK theme's link button text color.
  GdkColor* native_color = NULL;
  gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);

  if (native_color) {
    gchar color_spec[9];
    snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
             native_color->green / 257, native_color->blue / 257);
    gdk_color_free(native_color);

    if (!uses_markup) {
      button->native_markup = g_markup_printf_escaped(kLinkMarkup,
          color_spec, text);
    } else {
      button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
    }
  } else {
    // If the theme doesn't have a link color, just use blue. This matches the
    // default for GtkLinkButton.
    button->native_markup = g_strdup(button->normal_markup);
  }

  gtk_label_set_markup(GTK_LABEL(button->label),
      button->using_native_theme ? button->native_markup :
      button->normal_markup);
}

static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
                                              GdkEventExpose* event) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
  GtkWidget* label = button->label;

  gtk_chrome_link_button_set_text(button);

  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_normal) {
    gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup);
    button->is_normal = FALSE;
  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE &&
             !button->is_normal) {
    gtk_label_set_markup(GTK_LABEL(label),
        button->using_native_theme ? button->native_markup :
                                     button->normal_markup);
    button->is_normal = TRUE;
  }

  // Draw the link inside the button.
  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);

  // Draw the focus rectangle.
  if (GTK_WIDGET_HAS_FOCUS(widget)) {
    gtk_paint_focus(widget->style, widget->window,
                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
                    &event->area, widget, NULL,
                    widget->allocation.x, widget->allocation.y,
                    widget->allocation.width, widget->allocation.height);
  }

  return TRUE;
}

static void gtk_chrome_link_button_enter(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
}

static void gtk_chrome_link_button_leave(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  gdk_window_set_cursor(widget->window, NULL);
}

static void gtk_chrome_link_button_destroy(GtkObject* object) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);

  gtk_chrome_link_button_destroy_text_resources(button);

  if (button->hand_cursor) {
    gdk_cursor_unref(button->hand_cursor);
    button->hand_cursor = NULL;
  }

  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
}

static void gtk_chrome_link_button_class_init(
    GtkChromeLinkButtonClass* link_button_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(link_button_class);
  GtkButtonClass* button_class =
      reinterpret_cast<GtkButtonClass*>(link_button_class);
  GtkObjectClass* object_class =
      reinterpret_cast<GtkObjectClass*>(link_button_class);
  widget_class->expose_event = &gtk_chrome_link_button_expose;
  button_class->enter = &gtk_chrome_link_button_enter;
  button_class->leave = &gtk_chrome_link_button_leave;
  object_class->destroy = &gtk_chrome_link_button_destroy;
}

static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
  SetLinkButtonStyle();

  // We put a label in a button so we can connect to the click event. We don't
  // let the button draw itself; catch all expose events to the button and pass
  // them through to the label.
  button->label = gtk_label_new(NULL);
  button->normal_markup = NULL;
  button->pressed_markup = NULL;
  button->is_normal = TRUE;
  strncpy(button->normal_color, "blue", 9);
  button->native_markup = NULL;
  button->using_native_theme = TRUE;
  button->hand_cursor = gtk_util::GetCursor(GDK_HAND2);
  button->text = NULL;

  gtk_container_add(GTK_CONTAINER(button), button->label);
  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
}

GtkWidget* gtk_chrome_link_button_new(const char* text) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
  return lb;
}

GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
  return lb;
}

void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
                                              gboolean use_gtk) {
  if (use_gtk != button->using_native_theme) {
    button->using_native_theme = use_gtk;
    if (GTK_WIDGET_VISIBLE(button))
      gtk_widget_queue_draw(GTK_WIDGET(button));
  }
}

void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
                                      const char* text) {
  // Clear the markup so we can redraw.
  gtk_chrome_link_button_destroy_text_resources(button);
  button->text = g_strdup(text);

  if (GTK_WIDGET_VISIBLE(button))
    gtk_widget_queue_draw(GTK_WIDGET(button));
}

void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
                                             const GdkColor* color) {
  g_free(button->normal_markup);
  button->normal_markup = NULL;

  if (color) {
    snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
             color->green / 257, color->blue / 257);
  } else {
    strncpy(button->normal_color, "blue", 9);
  }

  if (GTK_WIDGET_VISIBLE(button))
    gtk_widget_queue_draw(GTK_WIDGET(button));
}

G_END_DECLS
<commit_msg>Set the label for a chrome link button when the text is set, not when the expose event fires.  This avoids a relayout that happens when the label is set the first time the link is exposed.<commit_after>// Copyright (c) 2009 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/gtk/gtk_chrome_link_button.h"

#include <stdlib.h>

#include "base/logging.h"
#include "chrome/common/gtk_util.h"

static const gchar* kLinkMarkup = "%s";

namespace {

// Set the GTK style on our custom link button. We don't want any border around
// the link text.
void SetLinkButtonStyle() {
  static bool style_was_set = false;

  if (style_was_set)
    return;
  style_was_set = true;

  gtk_rc_parse_string(
      "style \"chrome-link-button\" {"
      "  GtkButton::inner-border = {0, 0, 0, 0}"
      "  GtkButton::child-displacement-x = 0"
      "  GtkButton::child-displacement-y = 0"
      "  xthickness = 0"
      "  ythickness = 0"
      "}"
      "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
}

static void gtk_chrome_link_button_destroy_text_resources(
    GtkChromeLinkButton* button) {
  g_free(button->native_markup);
  button->native_markup = NULL;
  g_free(button->normal_markup);
  button->normal_markup = NULL;
  g_free(button->pressed_markup);
  button->pressed_markup = NULL;

  g_free(button->text);
  button->text = NULL;
}

}  // namespace

G_BEGIN_DECLS
G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)

// Should be called after we are realized so that the "link-color" property
// can be read.
static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
  // We only set the markup once.
  if (button->normal_markup)
    return;

  gchar* text = button->text;
  gboolean uses_markup = button->uses_markup;

  if (!uses_markup) {
    button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
                                                    button->normal_color,
                                                    text);
    button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
  } else {
    button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
                                            text);

    button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
  }

  // Get the current GTK theme's link button text color.
  GdkColor* native_color = NULL;
  gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);

  if (native_color) {
    gchar color_spec[9];
    snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
             native_color->green / 257, native_color->blue / 257);
    gdk_color_free(native_color);

    if (!uses_markup) {
      button->native_markup = g_markup_printf_escaped(kLinkMarkup,
          color_spec, text);
    } else {
      button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
    }
  } else {
    // If the theme doesn't have a link color, just use blue. This matches the
    // default for GtkLinkButton.
    button->native_markup = g_strdup(button->normal_markup);
  }

  gtk_label_set_markup(GTK_LABEL(button->label),
      button->using_native_theme ? button->native_markup :
      button->normal_markup);
}

static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
                                              GdkEventExpose* event) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
  GtkWidget* label = button->label;

  if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_normal) {
    gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup);
    button->is_normal = FALSE;
  } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE &&
             !button->is_normal) {
    gtk_label_set_markup(GTK_LABEL(label),
        button->using_native_theme ? button->native_markup :
                                     button->normal_markup);
    button->is_normal = TRUE;
  }

  // Draw the link inside the button.
  gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);

  // Draw the focus rectangle.
  if (GTK_WIDGET_HAS_FOCUS(widget)) {
    gtk_paint_focus(widget->style, widget->window,
                    static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
                    &event->area, widget, NULL,
                    widget->allocation.x, widget->allocation.y,
                    widget->allocation.width, widget->allocation.height);
  }

  return TRUE;
}

static void gtk_chrome_link_button_enter(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
  gdk_window_set_cursor(widget->window, link_button->hand_cursor);
}

static void gtk_chrome_link_button_leave(GtkButton* button) {
  GtkWidget* widget = GTK_WIDGET(button);
  gdk_window_set_cursor(widget->window, NULL);
}

static void gtk_chrome_link_button_destroy(GtkObject* object) {
  GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);

  gtk_chrome_link_button_destroy_text_resources(button);

  if (button->hand_cursor) {
    gdk_cursor_unref(button->hand_cursor);
    button->hand_cursor = NULL;
  }

  GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
}

static void gtk_chrome_link_button_class_init(
    GtkChromeLinkButtonClass* link_button_class) {
  GtkWidgetClass* widget_class =
      reinterpret_cast<GtkWidgetClass*>(link_button_class);
  GtkButtonClass* button_class =
      reinterpret_cast<GtkButtonClass*>(link_button_class);
  GtkObjectClass* object_class =
      reinterpret_cast<GtkObjectClass*>(link_button_class);
  widget_class->expose_event = &gtk_chrome_link_button_expose;
  button_class->enter = &gtk_chrome_link_button_enter;
  button_class->leave = &gtk_chrome_link_button_leave;
  object_class->destroy = &gtk_chrome_link_button_destroy;
}

static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
  SetLinkButtonStyle();

  // We put a label in a button so we can connect to the click event. We don't
  // let the button draw itself; catch all expose events to the button and pass
  // them through to the label.
  button->label = gtk_label_new(NULL);
  button->normal_markup = NULL;
  button->pressed_markup = NULL;
  button->is_normal = TRUE;
  strncpy(button->normal_color, "blue", 9);
  button->native_markup = NULL;
  button->using_native_theme = TRUE;
  button->hand_cursor = gtk_util::GetCursor(GDK_HAND2);
  button->text = NULL;

  gtk_container_add(GTK_CONTAINER(button), button->label);
  gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
}

GtkWidget* gtk_chrome_link_button_new(const char* text) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;

  gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb));

  return lb;
}

GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
  GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
  GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
  GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;

  gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb));

  return lb;
}

void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
                                              gboolean use_gtk) {
  if (use_gtk != button->using_native_theme) {
    button->using_native_theme = use_gtk;
    if (GTK_WIDGET_VISIBLE(button))
      gtk_widget_queue_draw(GTK_WIDGET(button));
  }
}

void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
                                      const char* text) {
  // Clear the markup so we can redraw.
  gtk_chrome_link_button_destroy_text_resources(button);
  button->text = g_strdup(text);

  gtk_chrome_link_button_set_text(button);

  if (GTK_WIDGET_VISIBLE(button))
    gtk_widget_queue_draw(GTK_WIDGET(button));
}

void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
                                             const GdkColor* color) {
  g_free(button->native_markup);
  button->native_markup = NULL;
  g_free(button->normal_markup);
  button->normal_markup = NULL;
  g_free(button->pressed_markup);
  button->pressed_markup = NULL;

  if (color) {
    snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
             color->green / 257, color->blue / 257);
  } else {
    strncpy(button->normal_color, "blue", 9);
  }

  gtk_chrome_link_button_set_text(button);

  if (GTK_WIDGET_VISIBLE(button))
    gtk_widget_queue_draw(GTK_WIDGET(button));
}

G_END_DECLS
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// library configuration
#include "libmesh_config.h"

// C++ includes
#include <algorithm> // for std::min
#include <map>       // for std::multimap
#include <sstream>   // for std::ostringstream

// Local includes
#include "boundary_info.h"
#include "elem.h"
#include "mesh_base.h"
#include "parallel.h"
#include "partitioner.h"
#include "point_locator_base.h"
#include "threads.h"

namespace libMesh
{

// ------------------------------------------------------------
// MeshBase class member functions
MeshBase::MeshBase (unsigned int d) :
  boundary_info  (new BoundaryInfo(*this)),
  _n_parts       (1),
  _dim           (d),
  _is_prepared   (false),
  _point_locator (NULL),
  _partitioner   (NULL),
  _skip_partitioning(false),
  _skip_renumber_nodes_and_elements(false)
{
  libmesh_assert (LIBMESH_DIM <= 3);
  libmesh_assert (LIBMESH_DIM >= _dim);
  libmesh_assert (libMesh::initialized());
}

MeshBase::MeshBase (const MeshBase& other_mesh) :
  boundary_info  (new BoundaryInfo(*this)),
  _n_parts       (other_mesh._n_parts),
  _dim           (other_mesh._dim),
  _is_prepared   (other_mesh._is_prepared),
  _point_locator (NULL),
  _partitioner   (other_mesh._partitioner->clone()),
  _skip_partitioning(other_mesh._skip_partitioning),
  _skip_renumber_nodes_and_elements(false)
{
}

MeshBase::~MeshBase()
{
  this->clear();

  libmesh_assert (!libMesh::closed());
}

void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements)
{
  parallel_only();

  // Renumber the nodes and elements so that they in contiguous
  // blocks.  By default, skip_renumber_nodes_and_elements is false,
  // however we may skip this step by passing
  // skip_renumber_nodes_and_elements==true to this function.
  //
  // Instances where you if prepare_for_use() should not renumber the nodes
  // and elements include reading in e.g. an xda/r or gmv file. In
  // this case, the ordering of the nodes may depend on an accompanying
  // solution, and the node ordering cannot be changed.
  _skip_renumber_nodes_and_elements = skip_renumber_nodes_and_elements;

  if(!skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();

  // Let all the elements find their neighbors
  this->find_neighbors();

  // Partition the mesh.
  this->partition();

  // If we're using ParallelMesh, we'll want it parallelized.
  this->delete_remote_elements();

  if(!skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();

  // Reset our PointLocator.  This needs to happen any time the elements
  // in the underlying elements in the mesh have changed, so we do it here.
  this->clear_point_locator();

  // The mesh is now prepared for use.
  _is_prepared = true;
}

void MeshBase::clear ()
{
  // Reset the number of partitions
  _n_parts = 1;

  // Reset the _is_prepared flag
  _is_prepared = false;

  // Clear boundary information
  this->boundary_info->clear();

  // Clear our point locator.
  this->clear_point_locator();
}

unsigned int MeshBase::n_subdomains() const
{
  // This requires an inspection on every processor
  parallel_only();

  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  std::set<unsigned int> subdomain_ids;

  for (; el!=end; ++el)
    subdomain_ids.insert((*el)->subdomain_id());

  // Some subdomains may only live on other processors
  Parallel::set_union(subdomain_ids, 0);

  unsigned int n_sbd_ids = subdomain_ids.size();
  Parallel::broadcast(n_sbd_ids);

  return n_sbd_ids;
}

unsigned int MeshBase::n_nodes_on_proc (const unsigned int proc_id) const
{
  // We're either counting a processor's nodes or unpartitioned
  // nodes
  libmesh_assert (proc_id < libMesh::n_processors() ||
	  proc_id == DofObject::invalid_processor_id);

  return static_cast<unsigned int>(std::distance (this->pid_nodes_begin(proc_id),
						  this->pid_nodes_end  (proc_id)));
}

unsigned int MeshBase::n_elem_on_proc (const unsigned int proc_id) const
{
  // We're either counting a processor's elements or unpartitioned
  // elements
  libmesh_assert (proc_id < libMesh::n_processors() ||
	  proc_id == DofObject::invalid_processor_id);

  return static_cast<unsigned int>(std::distance (this->pid_elements_begin(proc_id),
						  this->pid_elements_end  (proc_id)));
}

unsigned int MeshBase::n_active_elem_on_proc (const unsigned int proc_id) const
{
  libmesh_assert (proc_id < libMesh::n_processors());
  return static_cast<unsigned int>(std::distance (this->active_pid_elements_begin(proc_id),
						  this->active_pid_elements_end  (proc_id)));
}

unsigned int MeshBase::n_sub_elem () const
{
  unsigned int ne=0;

  const_element_iterator       el  = this->elements_begin();
  const const_element_iterator end = this->elements_end();

  for (; el!=end; ++el)
    ne += (*el)->n_sub_elem();

  return ne;
}

unsigned int MeshBase::n_active_sub_elem () const
{
  unsigned int ne=0;

  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  for (; el!=end; ++el)
    ne += (*el)->n_sub_elem();

  return ne;
}

std::string MeshBase::get_info() const
{
  std::ostringstream out;

  out << " Mesh Information:"                                  << '\n'
      << "  mesh_dimension()="    << this->mesh_dimension()    << '\n'
      << "  spatial_dimension()=" << this->spatial_dimension() << '\n'
      << "  n_nodes()="           << this->n_nodes()           << '\n'
      << "    n_local_nodes()="   << this->n_local_nodes()     << '\n'
      << "  n_elem()="            << this->n_elem()            << '\n'
      << "    n_local_elem()="    << this->n_local_elem()      << '\n'
#ifdef LIBMESH_ENABLE_AMR
      << "    n_active_elem()="   << this->n_active_elem()     << '\n'
#endif
      << "  n_subdomains()="      << this->n_subdomains()      << '\n'
      << "  n_partitions()="      << this->n_partitions()      << '\n'
      << "  n_processors()="      << libMesh::n_processors()   << '\n'
      << "  n_threads()="         << libMesh::n_threads()      << '\n'
      << "  processor_id()="      << this->processor_id()      << '\n';

  return out.str();
}

void MeshBase::print_info(std::ostream& os) const
{
  os << this->get_info()
     << std::endl;
}

std::ostream& operator << (std::ostream& os, const MeshBase& m)
{
  m.print_info(os);
  return os;
}

void MeshBase::partition (const unsigned int n_parts)
{
  // NULL partitioner means don't partition
  // Non-serial meshes aren't ready for partitioning yet.
  if(!skip_partitioning() &&
     partitioner().get() &&
     this->is_serial())
  {
    partitioner()->partition (*this, n_parts);
  }
  else
  {
    // Make sure locally cached partition count
    this->recalculate_n_partitions();

    // Make sure any other locally cached data is correct
    this->update_post_partitioning();
  }
}

unsigned int MeshBase::recalculate_n_partitions()
{
  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  unsigned int max_proc_id=0;

  for (; el!=end; ++el)
    max_proc_id = std::max(max_proc_id, static_cast<unsigned int>((*el)->processor_id()));

  // The number of partitions is one more than the max processor ID.
  _n_parts = max_proc_id+1;

  Parallel::max(_n_parts);

  return _n_parts;
}

const PointLocatorBase& MeshBase::point_locator () const
{
  libmesh_deprecated();

  if (_point_locator.get() == NULL)
    {
      // PointLocator construction may not be safe within threads
      libmesh_assert(!Threads::in_threads);

      _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
    }

  return *_point_locator;
}

AutoPtr<PointLocatorBase> MeshBase::sub_point_locator () const
{
  if (_point_locator.get() == NULL)
    {
      // PointLocator construction may not be safe within threads
      libmesh_assert(!Threads::in_threads);

      _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
    }

  return PointLocatorBase::build(TREE, *this, _point_locator.get());
}

void MeshBase::clear_point_locator ()
{
  _point_locator.reset(NULL);
}

} // namespace libMesh

std::string& MeshBase::subdomain_name(subdomain_id_type id)
{
  return _block_id_to_name[id];
}

const std::string& MeshBase::subdomain_name(subdomain_id_type id) const
{
  std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.find(id);
  if (iter == _block_id_to_name.end())
    return empty;
  else
    return iter->second;
}

subdomain_id_type MeshBase::get_id_by_name(const std::string& name) const
{
  // This function is searching the keys of the map
  // We might want to make this more efficient
  std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.begin();
  std::map<subdomain_id_type, std::string>::const_iterator end_iter = _block_id_to_name.end();

  for ( ; iter != end_iter; ++iter)
  {
    if (iter->second == name)
      return iter->first;
  }
  std::cerr << "Block name does not exist in mesh";
  libmesh_error();
}

<commit_msg>We should probably support consistent MeshBase::mesh_dimension() even on distributed meshes with empty subpartitions<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// library configuration
#include "libmesh_config.h"

// C++ includes
#include <algorithm> // for std::min
#include <map>       // for std::multimap
#include <sstream>   // for std::ostringstream

// Local includes
#include "boundary_info.h"
#include "elem.h"
#include "mesh_base.h"
#include "parallel.h"
#include "partitioner.h"
#include "point_locator_base.h"
#include "threads.h"

namespace libMesh
{

// ------------------------------------------------------------
// MeshBase class member functions
MeshBase::MeshBase (unsigned int d) :
  boundary_info  (new BoundaryInfo(*this)),
  _n_parts       (1),
  _dim           (d),
  _is_prepared   (false),
  _point_locator (NULL),
  _partitioner   (NULL),
  _skip_partitioning(false),
  _skip_renumber_nodes_and_elements(false)
{
  libmesh_assert (LIBMESH_DIM <= 3);
  libmesh_assert (LIBMESH_DIM >= _dim);
  libmesh_assert (libMesh::initialized());
}

MeshBase::MeshBase (const MeshBase& other_mesh) :
  boundary_info  (new BoundaryInfo(*this)),
  _n_parts       (other_mesh._n_parts),
  _dim           (other_mesh._dim),
  _is_prepared   (other_mesh._is_prepared),
  _point_locator (NULL),
  _partitioner   (other_mesh._partitioner->clone()),
  _skip_partitioning(other_mesh._skip_partitioning),
  _skip_renumber_nodes_and_elements(false)
{
}

MeshBase::~MeshBase()
{
  this->clear();

  libmesh_assert (!libMesh::closed());
}

void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements)
{
  parallel_only();

  // A distributed mesh may have processors with no elements (or
  // processors with no elements of higher dimension, if we ever
  // support mixed-dimension meshes), but we want consistent
  // mesh_dimension anyways.
  libmesh_assert(Parallel::verify(this->is_serial()));

  if (!this->is_serial())
    {
      unsigned int dim = this->mesh_dimension();
      Parallel::max(dim);
      this->set_mesh_dimension(dim);
    }

  // Renumber the nodes and elements so that they in contiguous
  // blocks.  By default, skip_renumber_nodes_and_elements is false,
  // however we may skip this step by passing
  // skip_renumber_nodes_and_elements==true to this function.
  //
  // Instances where you if prepare_for_use() should not renumber the nodes
  // and elements include reading in e.g. an xda/r or gmv file. In
  // this case, the ordering of the nodes may depend on an accompanying
  // solution, and the node ordering cannot be changed.
  _skip_renumber_nodes_and_elements = skip_renumber_nodes_and_elements;

  if(!skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();

  // Let all the elements find their neighbors
  this->find_neighbors();

  // Partition the mesh.
  this->partition();

  // If we're using ParallelMesh, we'll want it parallelized.
  this->delete_remote_elements();

  if(!skip_renumber_nodes_and_elements)
    this->renumber_nodes_and_elements();

  // Reset our PointLocator.  This needs to happen any time the elements
  // in the underlying elements in the mesh have changed, so we do it here.
  this->clear_point_locator();

  // The mesh is now prepared for use.
  _is_prepared = true;
}

void MeshBase::clear ()
{
  // Reset the number of partitions
  _n_parts = 1;

  // Reset the _is_prepared flag
  _is_prepared = false;

  // Clear boundary information
  this->boundary_info->clear();

  // Clear our point locator.
  this->clear_point_locator();
}

unsigned int MeshBase::n_subdomains() const
{
  // This requires an inspection on every processor
  parallel_only();

  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  std::set<unsigned int> subdomain_ids;

  for (; el!=end; ++el)
    subdomain_ids.insert((*el)->subdomain_id());

  // Some subdomains may only live on other processors
  Parallel::set_union(subdomain_ids, 0);

  unsigned int n_sbd_ids = subdomain_ids.size();
  Parallel::broadcast(n_sbd_ids);

  return n_sbd_ids;
}

unsigned int MeshBase::n_nodes_on_proc (const unsigned int proc_id) const
{
  // We're either counting a processor's nodes or unpartitioned
  // nodes
  libmesh_assert (proc_id < libMesh::n_processors() ||
	  proc_id == DofObject::invalid_processor_id);

  return static_cast<unsigned int>(std::distance (this->pid_nodes_begin(proc_id),
						  this->pid_nodes_end  (proc_id)));
}

unsigned int MeshBase::n_elem_on_proc (const unsigned int proc_id) const
{
  // We're either counting a processor's elements or unpartitioned
  // elements
  libmesh_assert (proc_id < libMesh::n_processors() ||
	  proc_id == DofObject::invalid_processor_id);

  return static_cast<unsigned int>(std::distance (this->pid_elements_begin(proc_id),
						  this->pid_elements_end  (proc_id)));
}

unsigned int MeshBase::n_active_elem_on_proc (const unsigned int proc_id) const
{
  libmesh_assert (proc_id < libMesh::n_processors());
  return static_cast<unsigned int>(std::distance (this->active_pid_elements_begin(proc_id),
						  this->active_pid_elements_end  (proc_id)));
}

unsigned int MeshBase::n_sub_elem () const
{
  unsigned int ne=0;

  const_element_iterator       el  = this->elements_begin();
  const const_element_iterator end = this->elements_end();

  for (; el!=end; ++el)
    ne += (*el)->n_sub_elem();

  return ne;
}

unsigned int MeshBase::n_active_sub_elem () const
{
  unsigned int ne=0;

  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  for (; el!=end; ++el)
    ne += (*el)->n_sub_elem();

  return ne;
}

std::string MeshBase::get_info() const
{
  std::ostringstream out;

  out << " Mesh Information:"                                  << '\n'
      << "  mesh_dimension()="    << this->mesh_dimension()    << '\n'
      << "  spatial_dimension()=" << this->spatial_dimension() << '\n'
      << "  n_nodes()="           << this->n_nodes()           << '\n'
      << "    n_local_nodes()="   << this->n_local_nodes()     << '\n'
      << "  n_elem()="            << this->n_elem()            << '\n'
      << "    n_local_elem()="    << this->n_local_elem()      << '\n'
#ifdef LIBMESH_ENABLE_AMR
      << "    n_active_elem()="   << this->n_active_elem()     << '\n'
#endif
      << "  n_subdomains()="      << this->n_subdomains()      << '\n'
      << "  n_partitions()="      << this->n_partitions()      << '\n'
      << "  n_processors()="      << libMesh::n_processors()   << '\n'
      << "  n_threads()="         << libMesh::n_threads()      << '\n'
      << "  processor_id()="      << this->processor_id()      << '\n';

  return out.str();
}

void MeshBase::print_info(std::ostream& os) const
{
  os << this->get_info()
     << std::endl;
}

std::ostream& operator << (std::ostream& os, const MeshBase& m)
{
  m.print_info(os);
  return os;
}

void MeshBase::partition (const unsigned int n_parts)
{
  // NULL partitioner means don't partition
  // Non-serial meshes aren't ready for partitioning yet.
  if(!skip_partitioning() &&
     partitioner().get() &&
     this->is_serial())
  {
    partitioner()->partition (*this, n_parts);
  }
  else
  {
    // Make sure locally cached partition count
    this->recalculate_n_partitions();

    // Make sure any other locally cached data is correct
    this->update_post_partitioning();
  }
}

unsigned int MeshBase::recalculate_n_partitions()
{
  const_element_iterator       el  = this->active_elements_begin();
  const const_element_iterator end = this->active_elements_end();

  unsigned int max_proc_id=0;

  for (; el!=end; ++el)
    max_proc_id = std::max(max_proc_id, static_cast<unsigned int>((*el)->processor_id()));

  // The number of partitions is one more than the max processor ID.
  _n_parts = max_proc_id+1;

  Parallel::max(_n_parts);

  return _n_parts;
}

const PointLocatorBase& MeshBase::point_locator () const
{
  libmesh_deprecated();

  if (_point_locator.get() == NULL)
    {
      // PointLocator construction may not be safe within threads
      libmesh_assert(!Threads::in_threads);

      _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
    }

  return *_point_locator;
}

AutoPtr<PointLocatorBase> MeshBase::sub_point_locator () const
{
  if (_point_locator.get() == NULL)
    {
      // PointLocator construction may not be safe within threads
      libmesh_assert(!Threads::in_threads);

      _point_locator.reset (PointLocatorBase::build(TREE, *this).release());
    }

  return PointLocatorBase::build(TREE, *this, _point_locator.get());
}

void MeshBase::clear_point_locator ()
{
  _point_locator.reset(NULL);
}

} // namespace libMesh

std::string& MeshBase::subdomain_name(subdomain_id_type id)
{
  return _block_id_to_name[id];
}

const std::string& MeshBase::subdomain_name(subdomain_id_type id) const
{
  std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.find(id);
  if (iter == _block_id_to_name.end())
    return empty;
  else
    return iter->second;
}

subdomain_id_type MeshBase::get_id_by_name(const std::string& name) const
{
  // This function is searching the keys of the map
  // We might want to make this more efficient
  std::map<subdomain_id_type, std::string>::const_iterator iter = _block_id_to_name.begin();
  std::map<subdomain_id_type, std::string>::const_iterator end_iter = _block_id_to_name.end();

  for ( ; iter != end_iter; ++iter)
  {
    if (iter->second == name)
      return iter->first;
  }
  std::cerr << "Block name does not exist in mesh";
  libmesh_error();
}

<|endoftext|>


<commit_before>#include "dlib/bed_util.h"
#include <time.h>

int main(int argc, char *argv[]) {
    samFile *fp = sam_open("test.bam", "r");
    bam_hdr_t *hdr = sam_hdr_read(fp);
    khash_t(bed) *cbed = dlib::parse_bed_hash("test.bed", hdr, 0);
    dlib::ParsedBed cppbed = dlib::ParsedBed("test.bed", hdr, 0);
    clock_t startc, afterc, startcpp, aftercpp;
    startc = clock();
    int c;
    bam1_t *b = bam_init1();
    const size_t n_iter = 1uL << 16;
    for(size_t j = 0; j < 2816; ++j) {
        sam_read1(fp, hdr, b);
        for(uint64_t i = 0; i < n_iter; ++i)
            c = dlib::bed_test(b, cbed);
    }
    afterc = clock();
    sam_close(fp);
    fprintf(stderr, "#s for c style: %f\n", ((double)afterc - startc) / CLOCKS_PER_SEC);
    fp = sam_open("test.bam", "r");
    startcpp = clock();
    for(size_t j = 0; j < 2816; ++j) {
        sam_read1(fp, hdr, b);
        for(uint64_t i = 0; i < n_iter; ++i)
            c = cppbed.bam1_test(b);
    }
    aftercpp = clock();
    fprintf(stderr, "#s for cpp style: %f\n", ((double)aftercpp - startcpp) / CLOCKS_PER_SEC);
    dlib::bed_destroy_hash(cbed);
    bam_destroy1(b);
    return 0;
}
<commit_msg>More comparison.<commit_after>#include "dlib/bed_util.h"
#include <time.h>

int main(int argc, char *argv[]) {
    samFile *fp = sam_open("test.bam", "r");
    bam_hdr_t *hdr = sam_hdr_read(fp);
    khash_t(bed) *cbed = dlib::parse_bed_hash("test.bed", hdr, 0);
    dlib::ParsedBed cppbed = dlib::ParsedBed("test.bed", hdr, 0);
    clock_t startc, afterc, startcpp, aftercpp;
    startc = clock();
    int c;
    bam1_t *b = bam_init1();
    const size_t n_iter = 1uL << 16;
    while(sam_read1(fp, hdr, b) >= 0)
        for(uint64_t i = 0; i < n_iter; ++i)
            dlib::bed_test(b, cbed);
    afterc = clock();
    sam_close(fp);
    bam_hdr_destroy(hdr);
    fp = sam_open("test.bam", "r");
    hdr = sam_hdr_read(fp);
    fprintf(stderr, "#s for c style: %f\n", ((double)afterc - startc) / CLOCKS_PER_SEC);
    startcpp = clock();
    while(sam_read1(fp, hdr, b) >= 0)
        for(uint64_t i = 0; i < n_iter; ++i)
            cppbed.bam1_test(b);
    aftercpp = clock();
    fprintf(stderr, "#s for cpp style: %f\n", ((double)aftercpp - startcpp) / CLOCKS_PER_SEC);
    dlib::bed_destroy_hash(cbed);
    bam_destroy1(b);
    return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017-2020 the rbfx project.
//
// 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 OR COPYRIGHT HOLDERS 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 <Urho3D/Scene/Scene.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Texture2D.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/Graphics/Renderer.h>
#include <Urho3D/Graphics/RenderPath.h>
#include <Toolbox/Scene/DebugCameraController.h>

#include "SceneView.h"

namespace Urho3D
{

SceneView::SceneView(Context* context, const IntRect& rect)
    : rect_(rect)
{
    scene_ = SharedPtr<Scene>(new Scene(context));
    scene_->CreateComponent<Octree>();
    viewport_ = SharedPtr<Viewport>(new Viewport(context, scene_, nullptr));
    viewport_->SetRect(IntRect(IntVector2::ZERO, rect_.Size()));
    CreateObjects();
    texture_ = SharedPtr<Texture2D>(new Texture2D(context));
    // Make sure viewport is not using default renderpath. That would cause issues when renderpath
    // is shared with other viewports (like in resource inspector).
    viewport_->SetRenderPath(viewport_->GetRenderPath()->Clone());
    SetSize(rect);
}

void SceneView::SetSize(const IntRect& rect)
{
    if (rect_ == rect)
        return;

    rect_ = rect;
    viewport_->SetRect(IntRect(IntVector2::ZERO, rect.Size()));
    texture_->SetSize(rect.Width(), rect.Height(), Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET);
    texture_->GetRenderSurface()->SetViewport(0, viewport_);
    texture_->GetRenderSurface()->SetUpdateMode(SURFACE_UPDATEALWAYS);
}

void SceneView::CreateObjects()
{
    Node* parent = scene_->GetChild("EditorObjects");
    if (parent == nullptr)
    {
        parent = scene_->CreateChild("EditorObjects", LOCAL, 0, true);
        parent->AddTag("__EDITOR_OBJECT__");
    }
    Node* camera = parent->GetChild("EditorCamera");
    if (camera == nullptr)
    {
        camera = parent->CreateChild("EditorCamera", LOCAL);
        camera->CreateComponent<Camera>()->SetFarClip(160000);
        camera->AddTag("__EDITOR_OBJECT__");
    }
    auto* debug = scene_->GetOrCreateComponent<DebugRenderer>(LOCAL);
    debug->SetView(GetCamera());
    debug->SetTemporary(true);
    debug->SetLineAntiAlias(true);
    viewport_->SetCamera(GetCamera());
}

Camera* SceneView::GetCamera() const
{
    return scene_->GetChild("EditorObjects")->GetChild("EditorCamera")->GetComponent<Camera>();
}

}
<commit_msg>Fix SetSize returning too early in constructor<commit_after>//
// Copyright (c) 2017-2020 the rbfx project.
//
// 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 OR COPYRIGHT HOLDERS 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 <Urho3D/Scene/Scene.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Texture2D.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/Graphics/Renderer.h>
#include <Urho3D/Graphics/RenderPath.h>
#include <Toolbox/Scene/DebugCameraController.h>

#include "SceneView.h"

namespace Urho3D
{

SceneView::SceneView(Context* context, const IntRect& rect)
    : rect_()
{
    scene_ = SharedPtr<Scene>(new Scene(context));
    scene_->CreateComponent<Octree>();
    viewport_ = SharedPtr<Viewport>(new Viewport(context, scene_, nullptr));
    CreateObjects();
    texture_ = SharedPtr<Texture2D>(new Texture2D(context));
    // Make sure viewport is not using default renderpath. That would cause issues when renderpath
    // is shared with other viewports (like in resource inspector).
    viewport_->SetRenderPath(viewport_->GetRenderPath()->Clone());
    SetSize(rect);
}

void SceneView::SetSize(const IntRect& rect)
{
    if (rect_ == rect)
        return;

    rect_ = rect;
    viewport_->SetRect(IntRect(IntVector2::ZERO, rect.Size()));
    texture_->SetSize(rect.Width(), rect.Height(), Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET);
    texture_->GetRenderSurface()->SetViewport(0, viewport_);
    texture_->GetRenderSurface()->SetUpdateMode(SURFACE_UPDATEALWAYS);
}

void SceneView::CreateObjects()
{
    Node* parent = scene_->GetChild("EditorObjects");
    if (parent == nullptr)
    {
        parent = scene_->CreateChild("EditorObjects", LOCAL, 0, true);
        parent->AddTag("__EDITOR_OBJECT__");
    }
    Node* camera = parent->GetChild("EditorCamera");
    if (camera == nullptr)
    {
        camera = parent->CreateChild("EditorCamera", LOCAL);
        camera->CreateComponent<Camera>()->SetFarClip(160000);
        camera->AddTag("__EDITOR_OBJECT__");
    }
    auto* debug = scene_->GetOrCreateComponent<DebugRenderer>(LOCAL);
    debug->SetView(GetCamera());
    debug->SetTemporary(true);
    debug->SetLineAntiAlias(true);
    viewport_->SetCamera(GetCamera());
}

Camera* SceneView::GetCamera() const
{
    return scene_->GetChild("EditorObjects")->GetChild("EditorCamera")->GetComponent<Camera>();
}

}
<|endoftext|>


<commit_before>// 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.

#include "chrome/browser/prefs/session_startup_pref.h"

#include <string>

#include "base/string_piece.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"

namespace {

// For historical reasons the enum and value registered in the prefs don't line
// up. These are the values registered in prefs.
const int kPrefValueDefault = 0;
const int kPrefValueLast = 1;
const int kPrefValueURLs = 4;

// Converts a SessionStartupPref::Type to an integer written to prefs.
int TypeToPrefValue(SessionStartupPref::Type type) {
  switch (type) {
    case SessionStartupPref::LAST:   return kPrefValueLast;
    case SessionStartupPref::URLS:   return kPrefValueURLs;
    default:                         return kPrefValueDefault;
  }
}

// Converts an integer pref value to a SessionStartupPref::Type.
SessionStartupPref::Type PrefValueToType(int pref_value) {
  switch (pref_value) {
    case kPrefValueLast:  return SessionStartupPref::LAST;
    case kPrefValueURLs:  return SessionStartupPref::URLS;
    default:              return SessionStartupPref::DEFAULT;
  }
}

}  // namespace

// static
void SessionStartupPref::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterIntegerPref(prefs::kRestoreOnStartup,
      TypeToPrefValue(browser_defaults::kDefaultSessionStartupType));
  prefs->RegisterListPref(prefs::kURLsToRestoreOnStartup);
}

// static
void SessionStartupPref::SetStartupPref(
    Profile* profile,
    const SessionStartupPref& pref) {
  DCHECK(profile);
  SetStartupPref(profile->GetPrefs(), pref);
}

// static
void SessionStartupPref::SetStartupPref(PrefService* prefs,
                                        const SessionStartupPref& pref) {
  DCHECK(prefs);

  if (!SessionStartupPref::TypeIsManaged(prefs))
    prefs->SetInteger(prefs::kRestoreOnStartup, TypeToPrefValue(pref.type));

  if (!SessionStartupPref::URLsAreManaged(prefs)) {
    // Always save the URLs, that way the UI can remain consistent even if the
    // user changes the startup type pref.
    // Ownership of the ListValue retains with the pref service.
    ScopedUserPrefUpdate update(prefs, prefs::kURLsToRestoreOnStartup);
    ListValue* url_pref_list =
        prefs->GetMutableList(prefs::kURLsToRestoreOnStartup);
    DCHECK(url_pref_list);
    url_pref_list->Clear();
    for (size_t i = 0; i < pref.urls.size(); ++i) {
      url_pref_list->Set(static_cast<int>(i),
                         new StringValue(pref.urls[i].spec()));
    }
  }
}

// static
SessionStartupPref SessionStartupPref::GetStartupPref(Profile* profile) {
  DCHECK(profile);
  return GetStartupPref(profile->GetPrefs());
}

// static
SessionStartupPref SessionStartupPref::GetStartupPref(PrefService* prefs) {
  DCHECK(prefs);
  SessionStartupPref pref(
      PrefValueToType(prefs->GetInteger(prefs::kRestoreOnStartup)));

  // Always load the urls, even if the pref type isn't URLS. This way the
  // preferences panels can show the user their last choice.
  const ListValue* url_pref_list = prefs->GetList(
      prefs::kURLsToRestoreOnStartup);
  if (url_pref_list) {
    for (size_t i = 0; i < url_pref_list->GetSize(); ++i) {
      Value* value = NULL;
      if (url_pref_list->Get(i, &value)) {
        std::string url_text;
        if (value->GetAsString(&url_text)) {
          GURL fixed_url = URLFixerUpper::FixupURL(url_text, "");
          pref.urls.push_back(fixed_url);
        }
      }
    }
  }
  return pref;
}

// static
bool SessionStartupPref::TypeIsManaged(PrefService* prefs) {
  DCHECK(prefs);
  const PrefService::Preference* pref_restore =
      prefs->FindPreference(prefs::kRestoreOnStartup);
  DCHECK(pref_restore);
  return pref_restore->IsManaged();
}

// static
bool SessionStartupPref::URLsAreManaged(PrefService* prefs) {
  DCHECK(prefs);
  const PrefService::Preference* pref_urls =
      prefs->FindPreference(prefs::kURLsToRestoreOnStartup);
  DCHECK(pref_urls);
  return pref_urls->IsManaged();
}

SessionStartupPref::SessionStartupPref() : type(DEFAULT) {}

SessionStartupPref::SessionStartupPref(Type type) : type(type) {}

SessionStartupPref::~SessionStartupPref() {}
<commit_msg>Get rid of PrefService::GetMutableDictionary/GetMutableList<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/prefs/session_startup_pref.h"

#include <string>

#include "base/string_piece.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"

namespace {

// For historical reasons the enum and value registered in the prefs don't line
// up. These are the values registered in prefs.
const int kPrefValueDefault = 0;
const int kPrefValueLast = 1;
const int kPrefValueURLs = 4;

// Converts a SessionStartupPref::Type to an integer written to prefs.
int TypeToPrefValue(SessionStartupPref::Type type) {
  switch (type) {
    case SessionStartupPref::LAST:   return kPrefValueLast;
    case SessionStartupPref::URLS:   return kPrefValueURLs;
    default:                         return kPrefValueDefault;
  }
}

// Converts an integer pref value to a SessionStartupPref::Type.
SessionStartupPref::Type PrefValueToType(int pref_value) {
  switch (pref_value) {
    case kPrefValueLast:  return SessionStartupPref::LAST;
    case kPrefValueURLs:  return SessionStartupPref::URLS;
    default:              return SessionStartupPref::DEFAULT;
  }
}

}  // namespace

// static
void SessionStartupPref::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterIntegerPref(prefs::kRestoreOnStartup,
      TypeToPrefValue(browser_defaults::kDefaultSessionStartupType));
  prefs->RegisterListPref(prefs::kURLsToRestoreOnStartup);
}

// static
void SessionStartupPref::SetStartupPref(
    Profile* profile,
    const SessionStartupPref& pref) {
  DCHECK(profile);
  SetStartupPref(profile->GetPrefs(), pref);
}

// static
void SessionStartupPref::SetStartupPref(PrefService* prefs,
                                        const SessionStartupPref& pref) {
  DCHECK(prefs);

  if (!SessionStartupPref::TypeIsManaged(prefs))
    prefs->SetInteger(prefs::kRestoreOnStartup, TypeToPrefValue(pref.type));

  if (!SessionStartupPref::URLsAreManaged(prefs)) {
    // Always save the URLs, that way the UI can remain consistent even if the
    // user changes the startup type pref.
    // Ownership of the ListValue retains with the pref service.
    ListPrefUpdate update(prefs, prefs::kURLsToRestoreOnStartup);
    ListValue* url_pref_list = update.Get();
    DCHECK(url_pref_list);
    url_pref_list->Clear();
    for (size_t i = 0; i < pref.urls.size(); ++i) {
      url_pref_list->Set(static_cast<int>(i),
                         new StringValue(pref.urls[i].spec()));
    }
  }
}

// static
SessionStartupPref SessionStartupPref::GetStartupPref(Profile* profile) {
  DCHECK(profile);
  return GetStartupPref(profile->GetPrefs());
}

// static
SessionStartupPref SessionStartupPref::GetStartupPref(PrefService* prefs) {
  DCHECK(prefs);
  SessionStartupPref pref(
      PrefValueToType(prefs->GetInteger(prefs::kRestoreOnStartup)));

  // Always load the urls, even if the pref type isn't URLS. This way the
  // preferences panels can show the user their last choice.
  const ListValue* url_pref_list = prefs->GetList(
      prefs::kURLsToRestoreOnStartup);
  if (url_pref_list) {
    for (size_t i = 0; i < url_pref_list->GetSize(); ++i) {
      Value* value = NULL;
      if (url_pref_list->Get(i, &value)) {
        std::string url_text;
        if (value->GetAsString(&url_text)) {
          GURL fixed_url = URLFixerUpper::FixupURL(url_text, "");
          pref.urls.push_back(fixed_url);
        }
      }
    }
  }
  return pref;
}

// static
bool SessionStartupPref::TypeIsManaged(PrefService* prefs) {
  DCHECK(prefs);
  const PrefService::Preference* pref_restore =
      prefs->FindPreference(prefs::kRestoreOnStartup);
  DCHECK(pref_restore);
  return pref_restore->IsManaged();
}

// static
bool SessionStartupPref::URLsAreManaged(PrefService* prefs) {
  DCHECK(prefs);
  const PrefService::Preference* pref_urls =
      prefs->FindPreference(prefs::kURLsToRestoreOnStartup);
  DCHECK(pref_urls);
  return pref_urls->IsManaged();
}

SessionStartupPref::SessionStartupPref() : type(DEFAULT) {}

SessionStartupPref::SessionStartupPref(Type type) : type(type) {}

SessionStartupPref::~SessionStartupPref() {}
<|endoftext|>


<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/dropdown_bar_host.h"

#include <algorithm>

#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/dropdown_bar_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/gfx/path.h"
#include "ui/gfx/scrollbar_size.h"
#include "views/focus/external_focus_tracker.h"
#include "views/focus/view_storage.h"
#include "views/widget/widget.h"

#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
#elif defined(OS_LINUX)
#include "ui/base/gtk/scoped_handle_gtk.h"
#endif

namespace {

#if defined(OS_WIN)
typedef base::win::ScopedRegion ScopedPlatformRegion;
#elif defined(OS_LINUX)
typedef ui::ScopedRegion ScopedPlatformRegion;
#endif

}  // namespace

using gfx::Path;

// static
bool DropdownBarHost::disable_animations_during_testing_ = false;

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, public:

DropdownBarHost::DropdownBarHost(BrowserView* browser_view)
    : browser_view_(browser_view),
      animation_offset_(0),
      esc_accel_target_registered_(false),
      is_visible_(false) {
}

void DropdownBarHost::Init(DropdownBarView* view) {
  view_ = view;

  // Initialize the host.
  host_.reset(CreateHost());
  host_->InitWithWidget(browser_view_->GetWidget(), gfx::Rect());
  host_->SetContentsView(view_);

  // Start listening to focus changes, so we can register and unregister our
  // own handler for Escape.
  focus_manager_ =
      views::FocusManager::GetFocusManagerForNativeView(host_->GetNativeView());
  if (focus_manager_) {
    focus_manager_->AddFocusChangeListener(this);
  } else {
    // In some cases (see bug http://crbug.com/17056) it seems we may not have
    // a focus manager.  Please reopen the bug if you hit this.
    NOTREACHED();
  }

  // Start the process of animating the opening of the widget.
  animation_.reset(new ui::SlideAnimation(this));
}

DropdownBarHost::~DropdownBarHost() {
  focus_manager_->RemoveFocusChangeListener(this);
  focus_tracker_.reset(NULL);
}

void DropdownBarHost::Show(bool animate) {
  // Stores the currently focused view, and tracks focus changes so that we can
  // restore focus when the dropdown widget is closed.
  focus_tracker_.reset(new views::ExternalFocusTracker(view_, focus_manager_));

  if (!animate || disable_animations_during_testing_) {
    is_visible_ = true;
    animation_->Reset(1);
    AnimationProgressed(animation_.get());
  } else {
    if (!is_visible_) {
      // Don't re-start the animation.
      is_visible_ = true;
      animation_->Reset();
      animation_->Show();
    }
  }
}

void DropdownBarHost::SetFocusAndSelection() {
  view_->SetFocusAndSelection(true);
}

bool DropdownBarHost::IsAnimating() const {
  return animation_->is_animating();
}

void DropdownBarHost::Hide(bool animate) {
  if (!IsVisible())
    return;
  if (animate && !disable_animations_during_testing_) {
    animation_->Reset(1.0);
    animation_->Hide();
  } else {
    StopAnimation();
    is_visible_ = false;
    host_->Hide();
  }
}

void DropdownBarHost::StopAnimation() {
  animation_->End();
}

bool DropdownBarHost::IsVisible() const {
  return is_visible_;
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, views::FocusChangeListener implementation:
void DropdownBarHost::FocusWillChange(views::View* focused_before,
                                      views::View* focused_now) {
  // First we need to determine if one or both of the views passed in are child
  // views of our view.
  bool our_view_before = focused_before && view_->Contains(focused_before);
  bool our_view_now = focused_now && view_->Contains(focused_now);

  // When both our_view_before and our_view_now are false, it means focus is
  // changing hands elsewhere in the application (and we shouldn't do anything).
  // Similarly, when both are true, focus is changing hands within the dropdown
  // widget (and again, we should not do anything). We therefore only need to
  // look at when we gain initial focus and when we loose it.
  if (!our_view_before && our_view_now) {
    // We are gaining focus from outside the dropdown widget so we must register
    // a handler for Escape.
    RegisterAccelerators();
  } else if (our_view_before && !our_view_now) {
    // We are losing focus to something outside our widget so we restore the
    // original handler for Escape.
    UnregisterAccelerators();
  }
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, ui::AnimationDelegate implementation:

void DropdownBarHost::AnimationProgressed(const ui::Animation* animation) {
  // First, we calculate how many pixels to slide the widget.
  gfx::Size pref_size = view_->GetPreferredSize();
  animation_offset_ = static_cast<int>((1.0 - animation_->GetCurrentValue()) *
                                       pref_size.height());

  // This call makes sure it appears in the right location, the size and shape
  // is correct and that it slides in the right direction.
  gfx::Rect dlg_rect = GetDialogPosition(gfx::Rect());
  SetDialogPosition(dlg_rect, false);

  // Let the view know if we are animating, and at which offset to draw the
  // edges.
  view_->set_animation_offset(animation_offset_);
  view_->SchedulePaint();
}

void DropdownBarHost::AnimationEnded(const ui::Animation* animation) {
  // Place the dropdown widget in its fully opened state.
  animation_offset_ = 0;

  if (!animation_->IsShowing()) {
    // Animation has finished closing.
    host_->Hide();
    is_visible_ = false;
  } else {
    // Animation has finished opening.
  }
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost protected:

void DropdownBarHost::ResetFocusTracker() {
  focus_tracker_.reset(NULL);
}

void DropdownBarHost::GetWidgetBounds(gfx::Rect* bounds) {
  DCHECK(bounds);
  *bounds = browser_view_->bounds();
}

void DropdownBarHost::UpdateWindowEdges(const gfx::Rect& new_pos) {
  // |w| is used to make it easier to create the part of the polygon that curves
  // the right side of the Find window. It essentially keeps track of the
  // x-pixel position of the right-most background image inside the view.
  // TODO(finnur): Let the view tell us how to draw the curves or convert
  // this to a CustomFrameWindow.
  int w = new_pos.width() - 6;  // -6 positions us at the left edge of the
                                // rightmost background image of the view.
  int h = new_pos.height();

  // This polygon array represents the outline of the background image for the
  // window. Basically, it encompasses only the visible pixels of the
  // concatenated find_dlg_LMR_bg images (where LMR = [left | middle | right]).
  const Path::Point polygon[] = {
      {0, 0}, {0, 1}, {2, 3}, {2, h - 3}, {4, h - 1},
        {4, h}, {w+0, h},
      {w+0, h - 1}, {w+1, h - 1}, {w+3, h - 3}, {w+3, 3}, {w+6, 0}
  };

  // Find the largest x and y value in the polygon.
  int max_x = 0, max_y = 0;
  for (size_t i = 0; i < arraysize(polygon); i++) {
    max_x = std::max(max_x, static_cast<int>(polygon[i].x));
    max_y = std::max(max_y, static_cast<int>(polygon[i].y));
  }

  // We then create the polygon and use SetWindowRgn to force the window to draw
  // only within that area. This region may get reduced in size below.
  Path path(polygon, arraysize(polygon));
  ScopedPlatformRegion region(path.CreateNativeRegion());
  // Are we animating?
  if (animation_offset() > 0) {
    // The animation happens in two steps: First, we clip the window and then in
    // GetWidgetPosition we offset the window position so that it still looks
    // attached to the toolbar as it grows. We clip the window by creating a
    // rectangle region (that gradually increases as the animation progresses)
    // and find the intersection between the two regions using CombineRgn.

    // |y| shrinks as the animation progresses from the height of the view down
    // to 0 (and reverses when closing).
    int y = animation_offset();
    // |y| shrinking means the animation (visible) region gets larger. In other
    // words: the rectangle grows upward (when the widget is opening).
    Path animation_path;
    SkRect animation_rect = { SkIntToScalar(0), SkIntToScalar(y),
                              SkIntToScalar(max_x), SkIntToScalar(max_y) };
    animation_path.addRect(animation_rect);
    ScopedPlatformRegion animation_region(
        animation_path.CreateNativeRegion());
    region.Set(Path::IntersectRegions(animation_region.Get(), region.Get()));

    // Next, we need to increase the region a little bit to account for the
    // curved edges that the view will draw to make it look like grows out of
    // the toolbar.
    Path::Point left_curve[] = {
      {0, y+0}, {0, y+1}, {2, y+3}, {2, y+0}, {0, y+0}
    };
    Path::Point right_curve[] = {
      {w+3, y+3}, {w+6, y+0}, {w+3, y+0}, {w+3, y+3}
    };

    // Combine the region for the curve on the left with our main region.
    Path left_path(left_curve, arraysize(left_curve));
    ScopedPlatformRegion r(left_path.CreateNativeRegion());
    region.Set(Path::CombineRegions(r.Get(), region.Get()));

    // Combine the region for the curve on the right with our main region.
    Path right_path(right_curve, arraysize(right_curve));
    region.Set(Path::CombineRegions(r.Get(), region.Get()));
  }

  // Now see if we need to truncate the region because parts of it obscures
  // the main window border.
  gfx::Rect widget_bounds;
  GetWidgetBounds(&widget_bounds);

  // Calculate how much our current position overlaps our boundaries. If we
  // overlap, it means we have too little space to draw the whole widget and
  // we allow overwriting the scrollbar before we start truncating our widget.
  //
  // TODO(brettw) this constant is evil. This is the amount of room we've added
  // to the window size, when we set the region, it can change the size.
  static const int kAddedWidth = 7;
  int difference = new_pos.right() - kAddedWidth - widget_bounds.right() -
      gfx::scrollbar_size() + 1;
  if (difference > 0) {
    Path::Point exclude[4];
    exclude[0].x = max_x - difference;  // Top left corner.
    exclude[0].y = 0;

    exclude[1].x = max_x;               // Top right corner.
    exclude[1].y = 0;

    exclude[2].x = max_x;               // Bottom right corner.
    exclude[2].y = max_y;

    exclude[3].x = max_x - difference;  // Bottom left corner.
    exclude[3].y = max_y;

    // Subtract this region from the original region.
    gfx::Path exclude_path(exclude, arraysize(exclude));
    ScopedPlatformRegion exclude_region(exclude_path.CreateNativeRegion());
    region.Set(Path::SubtractRegion(region.Get(), exclude_region.Get()));
  }

  // Window takes ownership of the region.
  host()->SetShape(region.release());
}

void DropdownBarHost::RegisterAccelerators() {
  DCHECK(!esc_accel_target_registered_);
  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
  focus_manager_->RegisterAccelerator(escape, this);
  esc_accel_target_registered_ = true;
}

void DropdownBarHost::UnregisterAccelerators() {
  DCHECK(esc_accel_target_registered_);
  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
  focus_manager_->UnregisterAccelerator(escape, this);
  esc_accel_target_registered_ = false;
}
<commit_msg>Initialize DropdownBarHost member<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/dropdown_bar_host.h"

#include <algorithm>

#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/dropdown_bar_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/gfx/path.h"
#include "ui/gfx/scrollbar_size.h"
#include "views/focus/external_focus_tracker.h"
#include "views/focus/view_storage.h"
#include "views/widget/widget.h"

#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
#elif defined(OS_LINUX)
#include "ui/base/gtk/scoped_handle_gtk.h"
#endif

namespace {

#if defined(OS_WIN)
typedef base::win::ScopedRegion ScopedPlatformRegion;
#elif defined(OS_LINUX)
typedef ui::ScopedRegion ScopedPlatformRegion;
#endif

}  // namespace

using gfx::Path;

// static
bool DropdownBarHost::disable_animations_during_testing_ = false;

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, public:

DropdownBarHost::DropdownBarHost(BrowserView* browser_view)
    : browser_view_(browser_view),
      view_(NULL),
      animation_offset_(0),
      focus_manager_(NULL),
      esc_accel_target_registered_(false),
      is_visible_(false) {
}

void DropdownBarHost::Init(DropdownBarView* view) {
  view_ = view;

  // Initialize the host.
  host_.reset(CreateHost());
  host_->InitWithWidget(browser_view_->GetWidget(), gfx::Rect());
  host_->SetContentsView(view_);

  // Start listening to focus changes, so we can register and unregister our
  // own handler for Escape.
  focus_manager_ =
      views::FocusManager::GetFocusManagerForNativeView(host_->GetNativeView());
  if (focus_manager_) {
    focus_manager_->AddFocusChangeListener(this);
  } else {
    // In some cases (see bug http://crbug.com/17056) it seems we may not have
    // a focus manager.  Please reopen the bug if you hit this.
    NOTREACHED();
  }

  // Start the process of animating the opening of the widget.
  animation_.reset(new ui::SlideAnimation(this));
}

DropdownBarHost::~DropdownBarHost() {
  focus_manager_->RemoveFocusChangeListener(this);
  focus_tracker_.reset(NULL);
}

void DropdownBarHost::Show(bool animate) {
  // Stores the currently focused view, and tracks focus changes so that we can
  // restore focus when the dropdown widget is closed.
  focus_tracker_.reset(new views::ExternalFocusTracker(view_, focus_manager_));

  if (!animate || disable_animations_during_testing_) {
    is_visible_ = true;
    animation_->Reset(1);
    AnimationProgressed(animation_.get());
  } else {
    if (!is_visible_) {
      // Don't re-start the animation.
      is_visible_ = true;
      animation_->Reset();
      animation_->Show();
    }
  }
}

void DropdownBarHost::SetFocusAndSelection() {
  view_->SetFocusAndSelection(true);
}

bool DropdownBarHost::IsAnimating() const {
  return animation_->is_animating();
}

void DropdownBarHost::Hide(bool animate) {
  if (!IsVisible())
    return;
  if (animate && !disable_animations_during_testing_) {
    animation_->Reset(1.0);
    animation_->Hide();
  } else {
    StopAnimation();
    is_visible_ = false;
    host_->Hide();
  }
}

void DropdownBarHost::StopAnimation() {
  animation_->End();
}

bool DropdownBarHost::IsVisible() const {
  return is_visible_;
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, views::FocusChangeListener implementation:
void DropdownBarHost::FocusWillChange(views::View* focused_before,
                                      views::View* focused_now) {
  // First we need to determine if one or both of the views passed in are child
  // views of our view.
  bool our_view_before = focused_before && view_->Contains(focused_before);
  bool our_view_now = focused_now && view_->Contains(focused_now);

  // When both our_view_before and our_view_now are false, it means focus is
  // changing hands elsewhere in the application (and we shouldn't do anything).
  // Similarly, when both are true, focus is changing hands within the dropdown
  // widget (and again, we should not do anything). We therefore only need to
  // look at when we gain initial focus and when we loose it.
  if (!our_view_before && our_view_now) {
    // We are gaining focus from outside the dropdown widget so we must register
    // a handler for Escape.
    RegisterAccelerators();
  } else if (our_view_before && !our_view_now) {
    // We are losing focus to something outside our widget so we restore the
    // original handler for Escape.
    UnregisterAccelerators();
  }
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost, ui::AnimationDelegate implementation:

void DropdownBarHost::AnimationProgressed(const ui::Animation* animation) {
  // First, we calculate how many pixels to slide the widget.
  gfx::Size pref_size = view_->GetPreferredSize();
  animation_offset_ = static_cast<int>((1.0 - animation_->GetCurrentValue()) *
                                       pref_size.height());

  // This call makes sure it appears in the right location, the size and shape
  // is correct and that it slides in the right direction.
  gfx::Rect dlg_rect = GetDialogPosition(gfx::Rect());
  SetDialogPosition(dlg_rect, false);

  // Let the view know if we are animating, and at which offset to draw the
  // edges.
  view_->set_animation_offset(animation_offset_);
  view_->SchedulePaint();
}

void DropdownBarHost::AnimationEnded(const ui::Animation* animation) {
  // Place the dropdown widget in its fully opened state.
  animation_offset_ = 0;

  if (!animation_->IsShowing()) {
    // Animation has finished closing.
    host_->Hide();
    is_visible_ = false;
  } else {
    // Animation has finished opening.
  }
}

////////////////////////////////////////////////////////////////////////////////
// DropdownBarHost protected:

void DropdownBarHost::ResetFocusTracker() {
  focus_tracker_.reset(NULL);
}

void DropdownBarHost::GetWidgetBounds(gfx::Rect* bounds) {
  DCHECK(bounds);
  *bounds = browser_view_->bounds();
}

void DropdownBarHost::UpdateWindowEdges(const gfx::Rect& new_pos) {
  // |w| is used to make it easier to create the part of the polygon that curves
  // the right side of the Find window. It essentially keeps track of the
  // x-pixel position of the right-most background image inside the view.
  // TODO(finnur): Let the view tell us how to draw the curves or convert
  // this to a CustomFrameWindow.
  int w = new_pos.width() - 6;  // -6 positions us at the left edge of the
                                // rightmost background image of the view.
  int h = new_pos.height();

  // This polygon array represents the outline of the background image for the
  // window. Basically, it encompasses only the visible pixels of the
  // concatenated find_dlg_LMR_bg images (where LMR = [left | middle | right]).
  const Path::Point polygon[] = {
      {0, 0}, {0, 1}, {2, 3}, {2, h - 3}, {4, h - 1},
        {4, h}, {w+0, h},
      {w+0, h - 1}, {w+1, h - 1}, {w+3, h - 3}, {w+3, 3}, {w+6, 0}
  };

  // Find the largest x and y value in the polygon.
  int max_x = 0, max_y = 0;
  for (size_t i = 0; i < arraysize(polygon); i++) {
    max_x = std::max(max_x, static_cast<int>(polygon[i].x));
    max_y = std::max(max_y, static_cast<int>(polygon[i].y));
  }

  // We then create the polygon and use SetWindowRgn to force the window to draw
  // only within that area. This region may get reduced in size below.
  Path path(polygon, arraysize(polygon));
  ScopedPlatformRegion region(path.CreateNativeRegion());
  // Are we animating?
  if (animation_offset() > 0) {
    // The animation happens in two steps: First, we clip the window and then in
    // GetWidgetPosition we offset the window position so that it still looks
    // attached to the toolbar as it grows. We clip the window by creating a
    // rectangle region (that gradually increases as the animation progresses)
    // and find the intersection between the two regions using CombineRgn.

    // |y| shrinks as the animation progresses from the height of the view down
    // to 0 (and reverses when closing).
    int y = animation_offset();
    // |y| shrinking means the animation (visible) region gets larger. In other
    // words: the rectangle grows upward (when the widget is opening).
    Path animation_path;
    SkRect animation_rect = { SkIntToScalar(0), SkIntToScalar(y),
                              SkIntToScalar(max_x), SkIntToScalar(max_y) };
    animation_path.addRect(animation_rect);
    ScopedPlatformRegion animation_region(
        animation_path.CreateNativeRegion());
    region.Set(Path::IntersectRegions(animation_region.Get(), region.Get()));

    // Next, we need to increase the region a little bit to account for the
    // curved edges that the view will draw to make it look like grows out of
    // the toolbar.
    Path::Point left_curve[] = {
      {0, y+0}, {0, y+1}, {2, y+3}, {2, y+0}, {0, y+0}
    };
    Path::Point right_curve[] = {
      {w+3, y+3}, {w+6, y+0}, {w+3, y+0}, {w+3, y+3}
    };

    // Combine the region for the curve on the left with our main region.
    Path left_path(left_curve, arraysize(left_curve));
    ScopedPlatformRegion r(left_path.CreateNativeRegion());
    region.Set(Path::CombineRegions(r.Get(), region.Get()));

    // Combine the region for the curve on the right with our main region.
    Path right_path(right_curve, arraysize(right_curve));
    region.Set(Path::CombineRegions(r.Get(), region.Get()));
  }

  // Now see if we need to truncate the region because parts of it obscures
  // the main window border.
  gfx::Rect widget_bounds;
  GetWidgetBounds(&widget_bounds);

  // Calculate how much our current position overlaps our boundaries. If we
  // overlap, it means we have too little space to draw the whole widget and
  // we allow overwriting the scrollbar before we start truncating our widget.
  //
  // TODO(brettw) this constant is evil. This is the amount of room we've added
  // to the window size, when we set the region, it can change the size.
  static const int kAddedWidth = 7;
  int difference = new_pos.right() - kAddedWidth - widget_bounds.right() -
      gfx::scrollbar_size() + 1;
  if (difference > 0) {
    Path::Point exclude[4];
    exclude[0].x = max_x - difference;  // Top left corner.
    exclude[0].y = 0;

    exclude[1].x = max_x;               // Top right corner.
    exclude[1].y = 0;

    exclude[2].x = max_x;               // Bottom right corner.
    exclude[2].y = max_y;

    exclude[3].x = max_x - difference;  // Bottom left corner.
    exclude[3].y = max_y;

    // Subtract this region from the original region.
    gfx::Path exclude_path(exclude, arraysize(exclude));
    ScopedPlatformRegion exclude_region(exclude_path.CreateNativeRegion());
    region.Set(Path::SubtractRegion(region.Get(), exclude_region.Get()));
  }

  // Window takes ownership of the region.
  host()->SetShape(region.release());
}

void DropdownBarHost::RegisterAccelerators() {
  DCHECK(!esc_accel_target_registered_);
  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
  focus_manager_->RegisterAccelerator(escape, this);
  esc_accel_target_registered_ = true;
}

void DropdownBarHost::UnregisterAccelerators() {
  DCHECK(esc_accel_target_registered_);
  views::Accelerator escape(ui::VKEY_ESCAPE, false, false, false);
  focus_manager_->UnregisterAccelerator(escape, this);
  esc_accel_target_registered_ = false;
}
<|endoftext|>