Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9350)

Unified Diff: chrome_frame/infobars/internal/infobar_window.cc

Issue 4766003: Preview CL for adding an Infobar facility to Google Chrome Frame.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome_frame/infobars/internal/infobar_window.cc
===================================================================
--- chrome_frame/infobars/internal/infobar_window.cc (revision 0)
+++ chrome_frame/infobars/internal/infobar_window.cc (revision 0)
@@ -0,0 +1,224 @@
+// 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.
+//
+// Implementation of the manager for infobar windows.
+
+#include "chrome_frame/infobars/internal/infobar_window.h"
+
grt (UTC plus 2) 2010/11/25 18:00:13 Include <algorithm> to explicitly pull in std::min
erikwright (departed) 2010/12/01 20:05:52 Awesome catch!
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+
+#include "chrome_frame/infobars/content.h"
+
+namespace {
+const UINT_PTR kInfobarSlidingTimerId = 1U;
+const UINT kInfobarSlidingTimerIntervalMs = 50U;
+// The step when the infobar is sliding, in pixels.
+const int kInfobarSlideOpenStep = 2;
+const int kInfobarSlideCloseStep = 6;
+} // namespace
+
+InfobarWindow::InfobarWindow(InfobarType type, InfobarHost* host)
+ : type_(type),
+ host_(host),
+ target_height_(0),
+ initial_height_(0),
+ content_(NULL),
+ frame_impl_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ DCHECK(type_ >= FIRST_INFOBAR_TYPE);
+ DCHECK(type_ < END_OF_INFOBAR_TYPE);
+ DCHECK(host_);
+}
+
+InfobarWindow::~InfobarWindow() {
+ ResetContent();
+}
+
+bool InfobarWindow::InitializeWindow() {
+ RECT dimensions = {0, 0, 0, 0};
+ if (!Create(host_->GetContainerWindow())) {
+ DPLOG(ERROR) << "Failure to create InfobarWindow.";
+ return false;
+ }
+
+ if (!::GetClientRect(host_->GetContainerWindow(), &dimensions)) {
+ DPLOG(ERROR) << "Failure in GetClientRect.";
+ DestroyWindow();
+ return false;
+ }
+
+ if (type_ == TOP_INFOBAR) {
+ dimensions.bottom = dimensions.top;
+ } else {
+ DCHECK(type_ == BOTTOM_INFOBAR);
+ dimensions.top = dimensions.bottom;
+ }
+
+ if (!MoveWindow(&dimensions, FALSE)) {
+ DPLOG(ERROR) << "Failure in MoveWindow.";
+ DestroyWindow();
+ return false;
+ }
+
+ return true;
+}
+
+bool InfobarWindow::Show(InfobarContent *content) {
+ ResetContent();
+
+ // Create the window if not created.
+ if (!IsWindow() && !InitializeWindow()) {
+ content->Reset();
+ return false;
+ }
+
+ if (!InstallContent(content))
+ return false;
+
+ return true;
+}
+
+void InfobarWindow::Hide() {
+ if (!IsWindow()) {
+ ResetContent();
+ } else if (!StartSlidingTowards(0)) {
+ // Failed to trigger a layout - seems our environment is going away or gone.
+ // Just hide immediately.
+ RECT empty = {0, 0, 0, 0};
+ MoveWindow(&empty, TRUE);
+ KillTimer(kInfobarSlidingTimerId);
+ ResetContent();
+ }
+}
+
+void InfobarWindow::ReserveSpace(RECT* rect) {
+ DCHECK(rect);
+ if (rect == NULL || !IsWindow())
+ return;
+
+ int current_height = CalculateHeight();
+
+ RECT infobar_rect = *rect;
+
+ switch (type_) {
+ case TOP_INFOBAR:
+ rect->top = std::min(rect->bottom,
+ infobar_rect.bottom = rect->top + current_height);
+ break;
+ case BOTTOM_INFOBAR:
+ rect->bottom = std::max(rect->top,
+ infobar_rect.top = rect->bottom - current_height);
+ break;
+ default:
+ NOTREACHED() << "Unknown InfobarType value.";
+ break;
+ }
+
+ if (!MoveWindow(&infobar_rect, TRUE))
+ DPLOG(ERROR) << "Failure in MoveWindow.";
+
+ if (!SetWindowPos(HWND_TOP,
+ &infobar_rect,
+ current_height != 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)) {
+ DPLOG(ERROR) << "Failure in SetWindowPos.";
+ }
+
+ if (content_ != NULL)
+ content_->SetDimensions(infobar_rect);
+
+ // Done sliding?
+ if (current_height == target_height_) {
+ KillTimer(kInfobarSlidingTimerId);
+ if (current_height == 0)
+ ResetContent();
+ }
+}
+
+bool InfobarWindow::StartSlidingTowards(int target_height) {
+ if (!IsWindow())
+ return false;
+
+ RECT dimensions = {0, 0, 0, 0};
+ if (!GetClientRect(&dimensions)) {
+ DPLOG(ERROR) << "Failure in GetClientRect.";
+ return false;
+ }
+
+ if (!SetTimer(kInfobarSlidingTimerId, kInfobarSlidingTimerIntervalMs, NULL)) {
+ DPLOG(ERROR) << "Failure in SetTimer.";
+ return false;
+ }
+
+ slide_start_ = base::Time::Now();
+ initial_height_ = dimensions.bottom - dimensions.top;
+ target_height_ = target_height;
+
+ // Trigger an immediate re-laying out. The timer will handle remaining steps.
+ host_->UpdateLayout();
+ return true;
+}
+
+int InfobarWindow::CalculateHeight() {
+ if (slide_start_.is_null())
+ return target_height_;
+
+ base::TimeDelta elapsed = base::Time::Now() - slide_start_;
+ int elapsed_steps = static_cast<int>(elapsed.InMilliseconds()) /
+ kInfobarSlidingTimerIntervalMs;
+
+ if (initial_height_ < target_height_) {
+ return std::min(initial_height_ + elapsed_steps * kInfobarSlideOpenStep,
+ target_height_);
+ } else if (initial_height_ > target_height_) {
+ return std::max(initial_height_ - elapsed_steps * kInfobarSlideCloseStep,
+ target_height_);
+ } else {
+ return target_height_;
+ }
+}
+
+bool InfobarWindow::InstallContent(InfobarContent* content) {
+ // Clear existing content, if any
+ ResetContent();
+
+ content_ = content;
+
+ if (!content_->InstallInFrame(&frame_impl_)) {
+ ResetContent();
grt (UTC plus 2) 2010/11/25 18:00:13 Multiple exits that require the same DoStuffBefore
erikwright (departed) 2010/12/01 20:05:52 Yeah, I didn't like it either. Moved to Show(), B
+ return false;
+ }
+
+ RECT dimensions = {0, 0, 0, 0};
+ if (!GetClientRect(&dimensions)) {
+ DPLOG(INFO) << "Failure in GetClientRect.";
+ ResetContent();
+ return false;
+ }
+
+ int infobar_width = dimensions.right - dimensions.left;
+ int content_height = content_->GetDesiredSize(infobar_width, 0);
+
+ if (!StartSlidingTowards(content_height)) {
+ ResetContent();
+ return false;
+ }
+
+ return true;
+}
+
+void InfobarWindow::ResetContent() {
+ if (content_ != NULL) {
+ content_->Reset();
+ content_ = NULL;
+ }
+}
+
+LRESULT InfobarWindow::OnTimer(UINT_PTR nIDEvent) {
+ DCHECK(nIDEvent == kInfobarSlidingTimerId);
+
+ // Might fail if the host is not able to update right now. Expect it to
+ // eventually succeed (on a future OnTimer invocation).
+ host_->UpdateLayout();
+ return S_OK;
+}
Property changes on: chrome_frame\infobars\internal\infobar_window.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698