diff options
3 files changed, 206 insertions, 64 deletions
diff --git a/chrome/browser/ui/panels/panel_overflow_browsertest.cc b/chrome/browser/ui/panels/panel_overflow_browsertest.cc index 71bd4ed..3c011a934 100644 --- a/chrome/browser/ui/panels/panel_overflow_browsertest.cc +++ b/chrome/browser/ui/panels/panel_overflow_browsertest.cc @@ -204,14 +204,14 @@ class PanelOverflowBrowserTest : public BasePanelBrowserTest { // TODO(dimich): remove the guard when overflow indicator is implemented on // other platforms. -#if defined(OS_WIN) -#define MAYBE_CreateMoreOverflowPanels CreateMoreOverflowPanels -#define MAYBE_OverflowIndicatorCount OverflowIndicatorCount -#define MAYBE_DrawOverflowAttention DrawOverflowAttention -#else +#if defined(OS_MACOSX) #define MAYBE_CreateMoreOverflowPanels DISABLED_CreateMoreOverflowPanels #define MAYBE_OverflowIndicatorCount DISABLED_OverflowIndicatorCount #define MAYBE_DrawOverflowAttention DISABLED_DrawOverflowAttention +#else +#define MAYBE_CreateMoreOverflowPanels CreateMoreOverflowPanels +#define MAYBE_OverflowIndicatorCount OverflowIndicatorCount +#define MAYBE_DrawOverflowAttention DrawOverflowAttention #endif IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, CheckPanelProperties) { @@ -1451,7 +1451,7 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_OverflowIndicatorCount) { // docked: P0, P1, P2 // overflow: P3, P4, P5 const int panel_widths[] = { - 250, 250, 210, // docked + 250, 200, 250, // docked 250, 250, 260 // overflow }; std::vector<Panel*> panels = CreateOverflowPanels(3, 3, panel_widths); @@ -1523,15 +1523,16 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_OverflowIndicatorCount) { EXPECT_FALSE(IsPanelVisible(panels[10])); EXPECT_EQ(3, overflow_strip->overflow_indicator()->GetCount()); - // Activating a big overflow panel will cause 2 docked panels to move to the - // oevrflow area and also get the top visible overflow panel bumped to the - // overflow-on-overflow. + // Widen a docked panel to bump a panel to overflow and also get the + // top visible overflow panel bumped to the overflow-to-overflow. // Expect the overflow indicator count gets increased by 1. - // docked: P0, P5 - // overflow: P1, P2, P6, (P7, P8, P9, P10) - panels[5]->Activate(); - WaitForPanelActiveState(panels[5], SHOW_AS_ACTIVE); - WaitForLayoutModeChanged(panels[5], PanelStrip::DOCKED); + // docked: P0, P1 + // overflow: P2, P5, P6, (P7, P8, P9, P10) + gfx::Size larger_size = panels[1]->GetBounds().size(); + larger_size.Enlarge(50, 50); + panel_manager->ResizePanel(panels[1], larger_size); + WaitForBoundsAnimationFinished(panels[1]); + WaitForLayoutModeChanged(panels[2], PanelStrip::IN_OVERFLOW); EXPECT_TRUE(IsPanelVisible(panels[6])); EXPECT_FALSE(IsPanelVisible(panels[7])); EXPECT_FALSE(IsPanelVisible(panels[8])); @@ -1543,6 +1544,13 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_OverflowIndicatorCount) { } IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_DrawOverflowAttention) { + // IceWM may activate another panel when an overflow-on-overflow + // panel is hidden. It happens to pick the panel we want to draw attention + // to, but drawing attention on an active panel is a no-op, so this test + // fails under IceWM. + if (SkipTestIfIceWM()) + return; + PanelManager* panel_manager = PanelManager::GetInstance(); DockedPanelStrip* docked_strip = panel_manager->docked_strip(); OverflowPanelStrip* overflow_strip = panel_manager->overflow_strip(); @@ -1553,7 +1561,7 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_DrawOverflowAttention) { // The panels enclosed in parentheses are hidden. const int panel_widths[] = { 100, 210, 210, 210, // docked - 210, 260, 210, // overflow + 210, 210, 210, // overflow 210, 210, 210, // overflow-on-overflow on shrunk 210, 210 // overflow-on-overflow on expanded }; @@ -1572,19 +1580,18 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_DrawOverflowAttention) { EXPECT_TRUE(panels[5]->IsDrawingAttention()); EXPECT_FALSE(overflow_indicator->IsDrawingAttention()); - // Activating this overflow panel will clear its attention. + // Stop drawing attention for the visible overflow panel. // Expect no impact to the overflow indicator. - // docked: P0, P1, P2, P5 - // overflow: P3, P4, P6, (P7, P8, P9, P10, P11) - panels[5]->Activate(); - WaitForPanelActiveState(panels[5], SHOW_AS_ACTIVE); + // docked: P0, P1, P2, P3 + // overflow: P4, P5, P6, (P7, P8, P9, P10, P11) + panels[5]->FlashFrame(false); EXPECT_FALSE(panels[5]->IsDrawingAttention()); EXPECT_FALSE(overflow_indicator->IsDrawingAttention()); // Draw attention for an overflow-on-overflow panel. // Expect the overflow indicator is showing attention. - // docked: P0, P1, P2, P5 - // overflow: P3, P4, P6, (P7, *P8, P9, P10, P11) + // docked: P0, P1, P2, P3 + // overflow: P4, P5, P6, (P7, *P8, P9, P10, P11) EXPECT_FALSE(panels[8]->IsDrawingAttention()); panels[8]->FlashFrame(true); EXPECT_TRUE(panels[8]->IsDrawingAttention()); @@ -1592,64 +1599,64 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, MAYBE_DrawOverflowAttention) { // Draw attention for another overflow-on-overflow panel. // Expect the overflow indicator is still showing attention. - // docked: P0, P1, P2, P5 - // overflow: P3, P4, P6, (P7, *P8, P9, *P10, P11) + // docked: P0, P1, P2, P3 + // overflow: P4, P5, P6, (P7, *P8, P9, *P10, P11) EXPECT_FALSE(panels[10]->IsDrawingAttention()); panels[10]->FlashFrame(true); EXPECT_TRUE(panels[10]->IsDrawingAttention()); EXPECT_TRUE(overflow_indicator->IsDrawingAttention()); - // Stop drawing attention for an overflow-on-overflow panel by activating it. + // Stop drawing attention for one overflow-on-overflow panel. // Expect the overflow indicator is still showing attention. - // docked: P0, P1, P2, P8 - // overflow: P5, P3, P4, (P6, P7, P9, *P10, P11) - panels[8]->Activate(); - WaitForPanelActiveState(panels[8], SHOW_AS_ACTIVE); + // docked: P0, P1, P2, P3 + // overflow: P4, P5, P6, (P7, P8, P9, *P10, P11) + panels[8]->FlashFrame(false); EXPECT_FALSE(panels[8]->IsDrawingAttention()); EXPECT_TRUE(overflow_indicator->IsDrawingAttention()); - // Stop drawing attention for another overflow-on-overflow panel by activating - // it. Expect the overflow indicator is not showing attention. - // docked: P0, P1, P2, P10 - // overflow: P8, P5, P3, (P4, P6, P7, P9, P11) - panels[10]->Activate(); - WaitForPanelActiveState(panels[10], SHOW_AS_ACTIVE); + // Stop drawing attention for the other overflow-on-overflow panel. + // Expect the overflow indicator is not showing attention. + // docked: P0, P1, P2, P3 + // overflow: P4, P5, P6, (P7, P8, P9, P10, P11) + panels[10]->FlashFrame(false); EXPECT_FALSE(panels[10]->IsDrawingAttention()); EXPECT_FALSE(overflow_indicator->IsDrawingAttention()); // Draw attention for the top overflow panel. // Expect no impact to the overflow indicator. - // docked: P0, P1, P2, P10 - // overflow: P8, P5, *P3, (P4, P6, P7, P9, P11) - EXPECT_TRUE(IsPanelVisible(panels[3])); - EXPECT_FALSE(panels[3]->IsDrawingAttention()); - panels[3]->FlashFrame(true); - EXPECT_TRUE(panels[3]->IsDrawingAttention()); + // docked: P0, P1, P2, P3 + // overflow: P4, P5, *P6, (P7, P8, P9, P10, P11) + EXPECT_TRUE(IsPanelVisible(panels[6])); + EXPECT_FALSE(panels[6]->IsDrawingAttention()); + panels[6]->FlashFrame(true); + EXPECT_TRUE(panels[6]->IsDrawingAttention()); EXPECT_FALSE(overflow_indicator->IsDrawingAttention()); - // Activating a big overflow panel will cause 2 docked panels to move to the - // overflow area and also get the top visible overflow panel bumped to the - // overflow-on-overflow. + // Widen a panel in the dock to bump a panel to the overflow area + // and also get the top visible overflow panel bumped to overflow-on-overflow. // Expect the overflow indicator is showing attention. - // docked: P0, P1, P5 - // overflow: P2, P10, P8, (*P3, P4, P6, P7, P9, P11) - panels[5]->Activate(); - WaitForPanelActiveState(panels[5], SHOW_AS_ACTIVE); - WaitForLayoutModeChanged(panels[5], PanelStrip::DOCKED); + // docked: P0, P1, P2, + // overflow: P3, P4, P5, (*P6, P7, P8, P9, P10, P11) + gfx::Size larger_size = panels[0]->GetBounds().size(); + larger_size.Enlarge(150, 50); + panel_manager->ResizePanel(panels[0], larger_size); + WaitForLayoutModeChanged(panels[3], PanelStrip::IN_OVERFLOW); EXPECT_EQ(3, docked_strip->num_panels()); EXPECT_EQ(9, overflow_strip->num_panels()); - EXPECT_FALSE(IsPanelVisible(panels[3])); - EXPECT_TRUE(panels[3]->IsDrawingAttention()); + WaitForBoundsAnimationFinished(panels[6]); + EXPECT_FALSE(IsPanelVisible(panels[6])); + EXPECT_TRUE(panels[6]->IsDrawingAttention()); EXPECT_TRUE(overflow_indicator->IsDrawingAttention()); - // Close an overflow panel that would move the first oveflow-on-overflow panel - // to become visible. Expect the overflow indicator is not showing attention. - // docked: P0, P1, P5 - // overflow: P2, P10, P3, (P4, P6, P7, P9, P11) - CloseWindowAndWait(panels[8]->browser()); + // Close an overflow panel that would cause the first oveflow-on-overflow + // panel to become visible. Expect the overflow indicator is no longer + // showing attention. + // docked: P0, P1, P2, + // overflow: P4, P5, *P6, (P7, P8, P9, P10, P11) + CloseWindowAndWait(panels[3]->browser()); EXPECT_EQ(3, docked_strip->num_panels()); EXPECT_EQ(8, overflow_strip->num_panels()); - EXPECT_TRUE(panels[3]->IsDrawingAttention()); + EXPECT_TRUE(panels[6]->IsDrawingAttention()); EXPECT_FALSE(overflow_indicator->IsDrawingAttention()); panel_manager->CloseAll(); diff --git a/chrome/browser/ui/panels/panel_overflow_indicator_gtk.cc b/chrome/browser/ui/panels/panel_overflow_indicator_gtk.cc index 42e451b..196fec5 100644 --- a/chrome/browser/ui/panels/panel_overflow_indicator_gtk.cc +++ b/chrome/browser/ui/panels/panel_overflow_indicator_gtk.cc @@ -1,43 +1,166 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/panels/panel_overflow_indicator_gtk.h" +#include <string> + +#include "base/logging.h" +#include "base/string_number_conversions.h" +#include "chrome/browser/ui/gtk/rounded_window.h" +#include "ui/base/gtk/gtk_hig_constants.h" + +namespace { + +// The height in pixels of the widget to show the plus count. +const int kWidgetHeight = 15; + +// Rounded corner size. +const int kRoundedCornerSize = 4; + +// Metrics for the indicator text. +const int kTextFontSize = 10 * PANGO_SCALE; +const GdkColor kTextColor = ui::kGdkWhite; + +// Gradient colors used to draw the background in normal mode. +const GdkColor kNormalBackgroundColorStart = + GDK_COLOR_RGB(0x77, 0x77, 0x77); +const GdkColor kNormalBackgroundColorEnd = + GDK_COLOR_RGB(0x55, 0x55, 0x55); + +// Gradient colors used to draw the background in attention mode. +const GdkColor kAttentionBackgroundColorStart = + GDK_COLOR_RGB(0xFF, 0xAB, 0x57); +const GdkColor kAttentionBackgroundColorEnd = + GDK_COLOR_RGB(0xF5, 0x93, 0x38); + +} // namespace + PanelOverflowIndicator* PanelOverflowIndicator::Create() { return new PanelOverflowIndicatorGtk(); } -PanelOverflowIndicatorGtk::PanelOverflowIndicatorGtk() { +PanelOverflowIndicatorGtk::PanelOverflowIndicatorGtk() + : count_(0), + is_drawing_attention_(false) { + window_ = gtk_window_new(GTK_WINDOW_POPUP); + + title_ = gtk_label_new(NULL); + PangoAttrList* attributes = pango_attr_list_new(); + pango_attr_list_insert(attributes, + pango_attr_weight_new(PANGO_WEIGHT_BOLD)); + pango_attr_list_insert(attributes, + pango_attr_foreground_new(kTextColor.red, + kTextColor.green, + kTextColor.blue)); + pango_attr_list_insert(attributes, + pango_attr_size_new_absolute(kTextFontSize)); + gtk_label_set_attributes(GTK_LABEL(title_), attributes); + pango_attr_list_unref(attributes); + gtk_container_add(GTK_CONTAINER(window_), title_); + gtk_widget_show(title_); + + gtk_util::ActAsRoundedWindow(window_, GdkColor(), kRoundedCornerSize, + gtk_util::ROUNDED_TOP_RIGHT, + gtk_util::BORDER_NONE); + + g_signal_connect(window_, "expose-event", + G_CALLBACK(OnExposeThunk), this); } PanelOverflowIndicatorGtk::~PanelOverflowIndicatorGtk() { + gtk_widget_destroy(window_); } int PanelOverflowIndicatorGtk::GetHeight() const { - return 0; + return kWidgetHeight; } gfx::Rect PanelOverflowIndicatorGtk::GetBounds() const { - return gfx::Rect(); + return bounds_; } void PanelOverflowIndicatorGtk::SetBounds(const gfx::Rect& bounds) { + if (bounds_ == bounds) + return; + bounds_ = bounds; + gtk_window_move(GTK_WINDOW(window_), bounds.x(), bounds.y()); + gtk_window_resize(GTK_WINDOW(window_), bounds.width(), bounds.height()); } int PanelOverflowIndicatorGtk::GetCount() const { - return 0; + return count_; } void PanelOverflowIndicatorGtk::SetCount(int count) { + if (count_ == count) + return; + count_ = count; + + if (count_ > 0) { + std::string title_text = "+" + base::IntToString(count_); + gtk_label_set_text(GTK_LABEL(title_), title_text.c_str()); + + gtk_widget_show(window_); + } else { + gtk_widget_hide(window_); + } } void PanelOverflowIndicatorGtk::DrawAttention() { + if (is_drawing_attention_) + return; + is_drawing_attention_ = true; + gtk_widget_queue_draw(window_); } void PanelOverflowIndicatorGtk::StopDrawingAttention() { + if (!is_drawing_attention_) + return; + is_drawing_attention_ = false; + gtk_widget_queue_draw(window_); } bool PanelOverflowIndicatorGtk::IsDrawingAttention() const { - return false; + return is_drawing_attention_; +} + +gboolean PanelOverflowIndicatorGtk::OnExpose(GtkWidget* widget, + GdkEventExpose* event) { + cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget)); + gdk_cairo_rectangle(cr, &event->area); + cairo_clip(cr); + + // Draw background color. + GtkAllocation allocation; + gtk_widget_get_allocation(widget, &allocation); + cairo_pattern_t* pattern = cairo_pattern_create_linear( + allocation.x, allocation.y, + allocation.x + allocation.width, allocation.y); + + const GdkColor* color_start; + const GdkColor* color_end; + if (is_drawing_attention_) { + color_start = &kAttentionBackgroundColorStart; + color_end = &kAttentionBackgroundColorEnd; + } else { + color_start = &kNormalBackgroundColorStart; + color_end = &kNormalBackgroundColorEnd; + } + + cairo_pattern_add_color_stop_rgb(pattern, 0.0, + color_start->red / 65535.0, + color_start->green / 65535.0, + color_start->blue / 65535.0); + cairo_pattern_add_color_stop_rgb(pattern, 1.0, + color_end->red / 65535.0, + color_end->green / 65535.0, + color_end->blue / 65535.0); + + cairo_set_source(cr, pattern); + cairo_paint(cr); + cairo_destroy(cr); + + return FALSE; } diff --git a/chrome/browser/ui/panels/panel_overflow_indicator_gtk.h b/chrome/browser/ui/panels/panel_overflow_indicator_gtk.h index 9f75c53..76a1b92 100644 --- a/chrome/browser/ui/panels/panel_overflow_indicator_gtk.h +++ b/chrome/browser/ui/panels/panel_overflow_indicator_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,8 +8,11 @@ #include "chrome/browser/ui/panels/panel_overflow_indicator.h" +#include <gtk/gtk.h> + #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "ui/base/gtk/gtk_signal.h" class PanelOverflowIndicatorGtk : public PanelOverflowIndicator { public: @@ -27,6 +30,15 @@ class PanelOverflowIndicatorGtk : public PanelOverflowIndicator { virtual bool IsDrawingAttention() const OVERRIDE; private: + CHROMEGTK_CALLBACK_1(PanelOverflowIndicatorGtk, gboolean, OnExpose, + GdkEventExpose*); + + int count_; + bool is_drawing_attention_; + GtkWidget* window_; + GtkWidget* title_; + gfx::Rect bounds_; + DISALLOW_COPY_AND_ASSIGN(PanelOverflowIndicatorGtk); }; |