// 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. // This view displays a list of historical page visits. It requires a // BaseHistoryModel to provide the information that will be shown. #ifndef CHROME_BROWSER_HISTORY_VIEW_H_ #define CHROME_BROWSER_HISTORY_VIEW_H_ #include #include "chrome/browser/history_model.h" #include "chrome/views/link.h" #include "chrome/views/scroll_view.h" class PageNavigator; class HistoryItemRenderer; class BaseHistoryModel; class SearchableUIContainer; class HistoryView : public views::View, public BaseHistoryModelObserver, public views::LinkController, views::VariableRowHeightScrollHelper::Controller { public: HistoryView(SearchableUIContainer* container, BaseHistoryModel* model, PageNavigator* navigator); virtual ~HistoryView(); // Returns true if this view is currently visible to the user. bool IsVisible(); // Overridden for layout purposes. virtual void DidChangeBounds(const gfx::Rect& previous, const gfx::Rect& current); virtual void Layout(); virtual bool GetFloatingViewIDForPoint(int x, int y, int* id); // Overriden for focus traversal. virtual bool EnumerateFloatingViews( views::View::FloatingViewPosition position, int starting_id, int* id); virtual views::View* ValidateFloatingViewForID(int id); // Render the visible area. virtual void Paint(ChromeCanvas* canvas); // BaseHistoryModelObserver implementation. void ModelChanged(bool result_set_changed); void ModelBeginWork(); void ModelEndWork(); // Returns the entry height, varies with font-height to prevent clipping. int GetEntryHeight(); // Sets whether the delete controls are visible. void SetShowDeleteControls(bool show_delete_controls); // We expose the PageNavigator so history entries can cause navigations // directly. PageNavigator* navigator() const { return navigator_; } // Scrolling. virtual int GetPageScrollIncrement(views::ScrollView* scroll_view, bool is_horizontal, bool is_positive); virtual int GetLineScrollIncrement(views::ScrollView* scroll_view, bool is_horizontal, bool is_positive); virtual views::VariableRowHeightScrollHelper::RowInfo GetRowInfo(int y); private: // For any given break (see comments for BreakOffsets, below), we store the // index of the item following the break, and whether or not the break // corresponds to a day break or session break. struct BreakValue { int index; bool day; }; // The map of our breaks (see comments for BreakOffsets, below). typedef std::map BreakOffsets; // Ensures the renderers are valid. void EnsureRenderer(); // Returns the bottom of the last entry. int GetLastEntryMaxY(); // Returns the max view id. int GetMaxViewID(); // Returns the y coordinate for the view with the specified floating view id, // the index into the model of the specified view and whether the view is // a delete control. int GetYCoordinateForViewID(int view_id, int* model_index, bool* is_delete_control); // Invoked when the user clicks the delete previous visits link. virtual void LinkActivated(views::Link* source, int event_flags); // Prompts the user to make sure they really want to delete, and if so // deletes the day at the specified model index. void DeleteDayAtModelIndex(int index); // Returns the number of delete controls shown before the specified iterator. int CalculateDeleteOffset(const BreakOffsets::const_iterator& it); // Returns the width of the delete control, calculating if necessary. int GetDeleteControlWidth(); // Calculates the bounds for the delete control given the specified y // location. gfx::Rect CalculateDeleteControlBounds(int base_y); // The "searchable view" container for this view. SearchableUIContainer* container_; // The font used for the "n days" ago heading. ChromeFont day_break_font_; // A "stamper"-style renderer for only painting the things that are // in the current view. HistoryItemRenderer* renderer_; // Used to render 'delete' controls. scoped_ptr delete_renderer_; // Class that performs the navigation when the user clicks on a page. PageNavigator* navigator_; // Pointer to the model that provides the contents of this view. scoped_ptr model_; // For laying out the potentially huge list of history entries, we // cache the offsets of session and day breaks. // // Each entry in BreakOffsets is a pair, where the key is the y // coordinate of a day heading and the value is a struct containing // both the index of the first history entry after that day // heading and a boolean value indicating whether the offset // represents a day or session break (these display differently). // // This lets us quickly compute, for a given y value, how to lay out // entries in the vicinity of that y value. // // Here's an example: // 4 days ago <- key: the y coordinate of the top of this block // +---------------- // | history item #7 <- index: 7, the index of this history item // +---------------- // +---------------- // | history item #8 // +---------------- // <- key: the y coordinate of this separator // +---------------- // | history item #9 <- index: 9, the index of this history item // +---------------- // +---------------- // | history item #10 // +---------------- // 5 days ago <- key: the y coordinate of this block // +---------------- // | history item #11 <- index: 11 // +---------------- // Each history item is represented as a floating view. In addition the // the delete controls are represented as floating views. A ramification // of this is that when the delete controls are displayed the view ids do // not necessarily directly correspond to a model index. The following // example shows the view ids and corresponding model index. // // delete <- view_id=10 // +---------------- // | history item #7 <- view_id=11, model_index=10 // +---------------- // +---------------- // | history item #8 <- view_id=12, model_index=11 // +---------------- // delete <- view_id=13 // +---------------- // | history item #9 <- view_id=14, model_index=12 // +---------------- // BreakOffsets break_offsets_; // Retrieve the nearest BreakOffsets less than or equal to the given y. // Another way of looking at this is that it fetches the BreakOffsets // entry that heads the section containing y. BreakOffsets::iterator GetBreakOffsetIteratorForY(int y); int GetBreakOffsetHeight(BreakValue value); views::VariableRowHeightScrollHelper scroll_helper_; // Whether we are showing search results. bool show_results_; // The loading state of the model. bool loading_; // Whether we're showing delete controls. bool show_delete_controls_; // How tall a single line of text is. int line_height_; // Width needed for the delete control. Calculated in GetDeleteControlWidth. int delete_control_width_; DISALLOW_EVIL_CONSTRUCTORS(HistoryView); }; #endif // CHROME_BROWSER_HISTORY_VIEW_H_