diff options
Diffstat (limited to 'chrome/browser/gtk/tabs/tab_renderer_gtk.h')
-rw-r--r-- | chrome/browser/gtk/tabs/tab_renderer_gtk.h | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h new file mode 100644 index 0000000..1ba697d --- /dev/null +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -0,0 +1,457 @@ +// Copyright (c) 2006-2008 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. + +#ifndef CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_ +#define CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_ + +#include <gtk/gtk.h> +#include <map> + +#include "app/animation.h" +#include "app/gtk_signal.h" +#include "app/slide_animation.h" +#include "base/basictypes.h" +#include "base/string16.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/owned_widget_gtk.h" +#include "gfx/canvas.h" +#include "gfx/font.h" +#include "gfx/rect.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace gfx { +class Size; +} // namespace gfx + +class CustomDrawButton; +class GtkThemeProvider; +class TabContents; +class ThemeProvider; +class ThrobAnimation; + +class TabRendererGtk : public AnimationDelegate, + public NotificationObserver { + public: + // Possible animation states. + enum AnimationState { + ANIMATION_NONE, + ANIMATION_WAITING, + ANIMATION_LOADING + }; + + class LoadingAnimation : public NotificationObserver { + public: + struct Data { + explicit Data(ThemeProvider* theme_provider); + Data(int loading, int waiting, int waiting_to_loading); + + SkBitmap* waiting_animation_frames; + SkBitmap* loading_animation_frames; + int loading_animation_frame_count; + int waiting_animation_frame_count; + int waiting_to_loading_frame_count_ratio; + }; + + explicit LoadingAnimation(ThemeProvider* theme_provider); + + // Used in unit tests to inject specific data. + explicit LoadingAnimation(const LoadingAnimation::Data& data); + + // Advance the loading animation to the next frame, or hide the animation if + // the tab isn't loading. Returns |true| if the icon area needs to be + // repainted. + bool ValidateLoadingAnimation(AnimationState animation_state); + + AnimationState animation_state() const { return animation_state_; } + int animation_frame() const { return animation_frame_; } + + const SkBitmap* waiting_animation_frames() const { + return data_->waiting_animation_frames; + } + const SkBitmap* loading_animation_frames() const { + return data_->loading_animation_frames; + } + + // Provide NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + scoped_ptr<Data> data_; + + // Used to listen for theme change notifications. + NotificationRegistrar registrar_; + + // Gives us our throbber images. + ThemeProvider* theme_provider_; + + // Current state of the animation. + AnimationState animation_state_; + + // The current index into the Animation image strip. + int animation_frame_; + + DISALLOW_COPY_AND_ASSIGN(LoadingAnimation); + }; + + explicit TabRendererGtk(ThemeProvider* theme_provider); + virtual ~TabRendererGtk(); + + // TabContents. If only the loading state was updated, the loading_only flag + // should be specified. If other things change, set this flag to false to + // update everything. + virtual void UpdateData(TabContents* contents, + bool phantom, + bool app, + bool loading_only); + + // Sets the blocked state of the tab. + void SetBlocked(bool pinned); + bool is_blocked() const; + + // Sets the mini-state of the tab. + void set_mini(bool mini) { data_.mini = mini; } + bool mini() const { return data_.mini; } + + // Sets the phantom state of the tab. + void set_phantom(bool phantom) { data_.phantom = phantom; } + bool phantom() const { return data_.phantom; } + + // Sets the app state of the tab. + void set_app(bool app) { data_.app = app; } + bool app() const { return data_.app; } + + // Are we in the process of animating a mini tab state change on this tab? + void set_animating_mini_change(bool value) { + data_.animating_mini_change = value; + } + + // Updates the display to reflect the contents of this TabRenderer's model. + void UpdateFromModel(); + + // Returns true if the Tab is selected, false otherwise. + virtual bool IsSelected() const; + + // Returns true if the Tab is visible, false otherwise. + virtual bool IsVisible() const; + + // Sets the visibility of the Tab. + virtual void SetVisible(bool visible) const; + + // Paints the tab into |canvas|. + virtual void Paint(gfx::Canvas* canvas); + + // Paints the tab into a SkBitmap. + virtual SkBitmap PaintBitmap(); + + // Paints the tab, and keeps the result server-side. The returned surface must + // be freed with cairo_surface_destroy(). + virtual cairo_surface_t* PaintToSurface(); + + // There is no PaintNow available, so the fastest we can do is schedule a + // paint with the windowing system. + virtual void SchedulePaint(); + + // Notifies the Tab that the close button has been clicked. + virtual void CloseButtonClicked(); + + // Sets the bounds of the tab. + virtual void SetBounds(const gfx::Rect& bounds); + + // Provide NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Advance the loading animation to the next frame, or hide the animation if + // the tab isn't loading. Returns |true| if the icon area needs to be + // repainted. + bool ValidateLoadingAnimation(AnimationState animation_state); + + // Repaint only the area of the tab that contains the favicon. + void PaintFavIconArea(GdkEventExpose* event); + + // Returns the minimum possible size of a single unselected Tab. + static gfx::Size GetMinimumUnselectedSize(); + // Returns the minimum possible size of a selected Tab. Selected tabs must + // always show a close button and have a larger minimum size than unselected + // tabs. + static gfx::Size GetMinimumSelectedSize(); + // Returns the preferred size of a single Tab, assuming space is + // available. + static gfx::Size GetStandardSize(); + + // Returns the width for mini-tabs. Mini-tabs always have this width. + static int GetMiniWidth(); + + // Loads the images to be used for the tab background. + static void LoadTabImages(); + + // Sets the colors used for painting text on the tabs. + static void SetSelectedTitleColor(SkColor color); + static void SetUnselectedTitleColor(SkColor color); + + static gfx::Font* title_font() { return title_font_; } + + // Returns the bounds of the Tab. + int x() const { return bounds_.x(); } + int y() const { return bounds_.y(); } + int width() const { return bounds_.width(); } + int height() const { return bounds_.height(); } + + gfx::Rect bounds() const { return bounds_; } + + gfx::Rect favicon_bounds() const { return favicon_bounds_; } + + // Returns the non-mirrored (LTR) bounds of this tab. + gfx::Rect GetNonMirroredBounds(GtkWidget* parent) const; + + // Returns the requested bounds of the tab. + gfx::Rect GetRequisition() const; + + GtkWidget* widget() const { return tab_.get(); } + + // Start/stop the mini-tab title animation. + void StartMiniTabTitleAnimation(); + void StopMiniTabTitleAnimation(); + + void set_vertical_offset(int offset) { background_offset_y_ = offset; } + + protected: + const gfx::Rect& title_bounds() const { return title_bounds_; } + const gfx::Rect& close_button_bounds() const { return close_button_bounds_; } + + // Returns the title of the Tab. + std::wstring GetTitle() const; + + // enter-notify-event handler that signals when the mouse enters the tab. + CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnEnterNotifyEvent, + GdkEventCrossing*); + + // leave-notify-event handler that signals when the mouse enters the tab. + CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnLeaveNotifyEvent, + GdkEventCrossing*); + + private: + class FavIconCrashAnimation; + + // The data structure used to hold cached bitmaps. We need to manually free + // the bitmap in CachedBitmap when we remove it from |cached_bitmaps_|. We + // handle this when we replace images in the map and in the destructor. + struct CachedBitmap { + int bg_offset_x; + int bg_offset_y; + SkBitmap* bitmap; + }; + typedef std::map<std::pair<const SkBitmap*, const SkBitmap*>, CachedBitmap> + BitmapCache; + + // Model data. We store this here so that we don't need to ask the underlying + // model, which is tricky since instances of this object can outlive the + // corresponding objects in the underlying model. + struct TabData { + TabData() + : is_default_favicon(false), + loading(false), + crashed(false), + off_the_record(false), + show_icon(true), + mini(false), + blocked(false), + animating_mini_change(false), + phantom(false), + app(false) { + } + + SkBitmap favicon; + bool is_default_favicon; + string16 title; + bool loading; + bool crashed; + bool off_the_record; + bool show_icon; + bool mini; + bool blocked; + bool animating_mini_change; + bool phantom; + bool app; + }; + + // TODO(jhawkins): Move into TabResources class. + struct TabImage { + SkBitmap* image_l; + SkBitmap* image_c; + SkBitmap* image_r; + int l_width; + int r_width; + int y_offset; + }; + + // Overridden from AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation); + virtual void AnimationCanceled(const Animation* animation); + virtual void AnimationEnded(const Animation* animation); + + // Starts/Stops the crash animation. + void StartCrashAnimation(); + void StopCrashAnimation(); + + // Return true if the crash animation is currently running. + bool IsPerformingCrashAnimation() const; + + // Set the temporary offset for the favicon. This is used during animation. + void SetFavIconHidingOffset(int offset); + + void DisplayCrashedFavIcon(); + void ResetCrashedFavIcon(); + + // Generates the bounds for the interior items of the tab. + void Layout(); + + // Returns the local bounds of the tab. This returns the rect + // {0, 0, width(), height()} for now, as we don't yet support borders. + gfx::Rect GetLocalBounds(); + + // Moves the close button widget within the GtkFixed container. + void MoveCloseButtonWidget(); + + // Returns the largest of the favicon, title text, and the close button. + static int GetContentHeight(); + + // A helper method for generating the masked bitmaps used to draw the curved + // edges of tabs. We cache the generated bitmaps because they can take a + // long time to compute. + SkBitmap* GetMaskedBitmap(const SkBitmap* mask, + const SkBitmap* background, + int bg_offset_x, + int bg_offset_y); + BitmapCache cached_bitmaps_; + + // Paints the tab, minus the close button. + void PaintTab(GdkEventExpose* event); + + // Paint various portions of the Tab + void PaintTitle(gfx::Canvas* canvas); + void PaintIcon(gfx::Canvas* canvas); + void PaintTabBackground(gfx::Canvas* canvas); + void PaintInactiveTabBackground(gfx::Canvas* canvas); + void PaintActiveTabBackground(gfx::Canvas* canvas); + void PaintLoadingAnimation(gfx::Canvas* canvas); + + // Returns the number of favicon-size elements that can fit in the tab's + // current size. + int IconCapacity() const; + + // Returns whether the Tab should display a favicon. + bool ShouldShowIcon() const; + + // Returns whether the Tab should display a close button. + bool ShouldShowCloseBox() const; + + CustomDrawButton* MakeCloseButton(); + + // Gets the throb value for the tab. When a tab is not selected the + // active background is drawn at |GetThrobValue()|%. This is used for hover + // and mini-tab title change effects. + double GetThrobValue(); + + // Handles the clicked signal for the close button. + CHROMEGTK_CALLBACK_0(TabRendererGtk, void, OnCloseButtonClicked); + + // Handles middle clicking the close button. + CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnCloseButtonMouseRelease, + GdkEventButton*); + + // expose-event handler that redraws the tab. + CHROMEGTK_CALLBACK_1(TabRendererGtk, gboolean, OnExposeEvent, + GdkEventExpose*); + + // size-allocate handler used to update the current bounds of the tab. + CHROMEGTK_CALLBACK_1(TabRendererGtk, void, OnSizeAllocate, GtkAllocation*); + + // TODO(jhawkins): Move to TabResources. + static void InitResources(); + static bool initialized_; + + // The bounds of various sections of the display. + gfx::Rect favicon_bounds_; + gfx::Rect title_bounds_; + gfx::Rect close_button_bounds_; + + TabData data_; + + static TabImage tab_active_; + static TabImage tab_inactive_; + static TabImage tab_alpha_; + + static gfx::Font* title_font_; + static int title_font_height_; + + static int close_button_width_; + static int close_button_height_; + + static SkColor selected_title_color_; + static SkColor unselected_title_color_; + + // The GtkDrawingArea we draw the tab on. + OwnedWidgetGtk tab_; + + // Whether we're showing the icon. It is cached so that we can detect when it + // changes and layout appropriately. + bool showing_icon_; + + // Whether we are showing the close button. It is cached so that we can + // detect when it changes and layout appropriately. + bool showing_close_button_; + + // The offset used to animate the favicon location. + int fav_icon_hiding_offset_; + + // The animation object used to swap the favicon with the sad tab icon. + scoped_ptr<FavIconCrashAnimation> crash_animation_; + + // Set when the crashed favicon should be displayed. + bool should_display_crashed_favicon_; + + // The bounds of this Tab. + gfx::Rect bounds_; + + // The requested bounds of this tab. These bounds are relative to the + // tabstrip. + gfx::Rect requisition_; + + // Hover animation. + scoped_ptr<SlideAnimation> hover_animation_; + + // Animation used when the title of an inactive mini-tab changes. + scoped_ptr<ThrobAnimation> mini_title_animation_; + + // Contains the loading animation state. + LoadingAnimation loading_animation_; + + // The offset used to paint the tab theme images. + int background_offset_x_; + + // The vertical offset used to paint the tab theme images. Controlled by the + // tabstrip and plumbed here to offset the theme image by the size of the + // alignment in the BrowserTitlebar. + int background_offset_y_; + + GtkThemeProvider* theme_provider_; + + // The close button. + scoped_ptr<CustomDrawButton> close_button_; + + // The current color of the close button. + SkColor close_button_color_; + + // Used to listen for theme change notifications. + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(TabRendererGtk); +}; + +#endif // CHROME_BROWSER_GTK_TABS_TAB_RENDERER_GTK_H_ |