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

Unified Diff: chrome_frame/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/infobar_window.cc
===================================================================
--- chrome_frame/infobar_window.cc (revision 0)
+++ chrome_frame/infobar_window.cc (revision 0)
@@ -0,0 +1,197 @@
+// 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/infobar_window.h"
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+
+namespace {
+
+const UINT_PTR kInfobarSlidingTimerId = 1U;
+// In milliseconds.
+const UINT kInfobarSlidingTimerInterval = 50U;
grt (UTC plus 2) 2010/11/10 17:59:29 Consider putting "ms" in the constant name so that
erikwright (departed) 2010/11/24 06:24:56 Agreed.
+// The step when the infobar is sliding, in pixels.
+const int kInfobarSlidingStep = 1;
+// The default height of the infobar.
+const int kInfobarDefaultHeight = 39;
+
+} // namespace
+
+InfobarWindow::InfobarWindow(InfobarType type, InfobarHost* host)
+ : type_(type),
grt (UTC plus 2) 2010/11/10 17:59:29 Although I like spreading the initializer list out
erikwright (departed) 2010/11/24 06:24:56 It does prefer to avoid unnecessary whitespace, bu
+ host_(host),
+ show_(false),
+ target_height_(1),
+ initial_height_(1),
+ content_(NULL),
+ frame_impl_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ DCHECK(host_);
+}
+
+InfobarWindow::~InfobarWindow() {
+ Reset();
+
+ if (IsWindow()) {
+ DestroyWindow();
+ }
+}
+
+HRESULT InfobarWindow::Show(InfobarContent *content,
+ int max_height) {
+ if (content_) {
+ content_->Reset();
+ content_ = NULL;
+ }
+
+ // Create the window if not created.
+ if (!IsWindow()) {
+ Create(host_->GetContainerWindow());
+ RECT dimensions = {0, 0, 0, 0};
+ GetClientRect(&dimensions);
+ dimensions.bottom = 1;
+ MoveWindow(&dimensions, TRUE);
+ }
+ if (!IsWindow())
+ return E_UNEXPECTED;
+
+ HRESULT hr = content->InstallInFrame(&frame_impl_);
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ StartUpdatingLayout(true, max_height, true);
+
+ // We only keep the pointer in case of success. At this point, we promise to
+ // call Reset at some future point on the content.
+ content_ = content;
+ return S_OK;
+}
+
+HRESULT InfobarWindow::Hide() {
+ StartUpdatingLayout(false, 0, false);
+
+ return S_OK;
+}
+
+void InfobarWindow::ReserveSpace(RECT* rect) {
+ DCHECK(rect);
+ if (rect == NULL || !show_ || !IsWindow())
+ return;
+
+ RECT infobar_rect = *rect;
+
+ int height = CalculateHeight();
+
+ switch (type_) {
+ case TOP_INFOBAR:
+ infobar_rect.bottom = rect->top = std::min(rect->bottom,
+ rect->top + height);
+ break;
+ case BOTTOM_INFOBAR:
+ infobar_rect.top = rect->bottom = std::max(rect->top,
+ rect->bottom - height);
+ break;
+ default:
+ NOTREACHED() << "Unknown InfobarType value.";
+ break;
+ }
+
+
+ MoveWindow(&infobar_rect, TRUE);
+
+ SetWindowPos(HWND_TOP,
+ &infobar_rect,
+ show_ || height != target_height_ ?
+ SWP_SHOWWINDOW : SWP_HIDEWINDOW);
+
+ if (content_ != NULL) {
+ content_->SetDimensions(infobar_rect);
+ }
+
+ if (height == target_height_) {
+ KillTimer(kInfobarSlidingTimerId);
+ if (!show_ && content_) {
+ // Content is responsible for freeing itself.
+ content_->Reset();
+ content_ = NULL;
+ }
+ }
+}
+
+void InfobarWindow::StartUpdatingLayout(bool show, int max_height, bool slide) {
+ if (!IsWindow()) {
+ return;
+ }
+
+ show_ = show;
+ if (show) {
+ // TODO(erikwright): ask our widget for its height
+ target_height_ = (max_height == 0 || kInfobarDefaultHeight < max_height) ?
+ kInfobarDefaultHeight : max_height;
+ if (target_height_ <= 0) {
+ target_height_ = 1;
+ }
+ } else {
+ target_height_ = 1;
+ }
+
+ // Trigger an deferred call to ReserveSpace, in which we will do the actual
+ // MoveWindow
+ if (!host_->UpdateLayout()) {
+ // Failed to trigger a layout - seems our environment is going away or gone.
+ // Let's get out of here.
+ RECT empty = {0, 0, 0, 0};
+ MoveWindow(&empty, TRUE);
+ KillTimer(kInfobarSlidingTimerId);
+ if (content_) {
+ // Content is responsible for freeing itself.
+ content_->Reset();
+ content_ = NULL;
+ }
+ return;
+ }
+
+ if (!slide || !show) {
+ slide_start_ = base::Time();
+ KillTimer(kInfobarSlidingTimerId);
+ } else {
+ RECT dimensions = {0, 0, 0, 0};
+ GetClientRect(&dimensions);
+ slide_start_ = base::Time::Now();
+ initial_height_ = dimensions.bottom;
+ SetTimer(kInfobarSlidingTimerId, kInfobarSlidingTimerInterval, NULL);
+ }
+
+}
+
+int InfobarWindow::CalculateHeight() {
+ RECT dimensions;
+ int current_height = GetClientRect(&dimensions) ? dimensions.bottom : 0;
+
+ if (slide_start_.is_null()) {
+ return target_height_;
+ }
+
+ base::TimeDelta elapsed = base::Time::Now() - slide_start_;
+ int travel = (static_cast<int>(elapsed.InMilliseconds()) /
+ kInfobarSlidingTimerInterval) * kInfobarSlidingStep;
+
+ if (current_height < target_height_) {
+ return std::min(current_height + travel, target_height_);
+ } else if (current_height > target_height_) {
+ return std::max(current_height - travel, target_height_);
+ } else {
+ return current_height;
+ }
+}
+
+LRESULT InfobarWindow::OnTimer(UINT_PTR nIDEvent) {
+ DCHECK(nIDEvent == kInfobarSlidingTimerId);
+
+ host_->UpdateLayout();
+ return S_OK;
+}

Powered by Google App Engine
This is Rietveld 408576698