omnibox_result_view.h revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_RESULT_VIEW_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_RESULT_VIEW_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/gtest_prod_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_match.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_delegate.h"
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/gfx/font_list.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/image_view.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class LocationBarView;
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OmniboxPopupContentsView;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Canvas;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RenderText;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OmniboxResultView : public views::View,
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          private gfx::AnimationDelegate {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep these ordered from least dominant (normal) to most dominant
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (selected).
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ResultViewState {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NORMAL = 0,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HOVERED,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SELECTED,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NUM_STATES
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ColorKind {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BACKGROUND = 0,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TEXT,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIMMED_TEXT,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URL,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DIVIDER,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NUM_KINDS
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  OmniboxResultView(OmniboxPopupContentsView* model,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int model_index,
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    LocationBarView* location_bar_view,
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                    const gfx::FontList& font_list);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OmniboxResultView();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor GetColor(ResultViewState state, ColorKind kind) const;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the match used to paint the contents of this result view. We copy
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the match so that we can continue to paint the last result even after the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // model has changed.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetMatch(const AutocompleteMatch& match);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ShowKeyword(bool show_keyword);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Invalidate();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::View:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual gfx::Size GetPreferredSize() OVERRIDE;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResultViewState GetState() const;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Returns the height of the text portion of the result view. In the base
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // class, this is the height of one line of text.
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual int GetTextHeight() const;
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Returns the display width required for the match contents.
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int GetMatchContentsWidth() const;
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Paints the given |match| using the RenderText instances |contents| and
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |description| at offset |x| in the bounds of this view.
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void PaintMatch(const AutocompleteMatch& match,
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          gfx::RenderText* contents,
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          gfx::RenderText* description,
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          gfx::Canvas* canvas,
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          int x) const;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Draws given |render_text| on |canvas| at given location (|x|, |y|).
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |contents| indicates whether the |render_text| is for the match contents
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // (rather than the separator or the description).  Additional properties from
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |match| are used to render Infinite suggestions correctly.  If |max_width|
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // is a non-negative number, the text will be elided to fit within
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |max_width|.  Returns the x position to the right of the string.
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int DrawRenderText(const AutocompleteMatch& match,
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     gfx::RenderText* render_text,
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     bool contents,
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                     gfx::Canvas* canvas,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     int x,
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     int y,
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     int max_width) const;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Creates a RenderText with given |text| and rendering defaults.
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<gfx::RenderText> CreateRenderText(
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const base::string16& text) const;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Creates a RenderText with default rendering for the given |text|. The
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |classifications| and |force_dim| are used to style the text.
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<gfx::RenderText> CreateClassifiedRenderText(
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      const base::string16& text,
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const ACMatchClassifications& classifications,
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      bool force_dim) const;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect& text_bounds() const { return text_bounds_; }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_edge_item_padding(int value) { edge_item_padding_ = value; }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_item_padding(int value) { item_padding_ = value; }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_minimum_text_vertical_padding(int value) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    minimum_text_vertical_padding_ = value;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Common initialization code of the colors returned by GetColors().
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void CommonInitColors(const ui::NativeTheme* theme,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SkColor colors[][NUM_KINDS]);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetIcon() const;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkia* GetKeywordIcon() const;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Whether to render only the keyword match.  Returns true if |match_| has an
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // associated keyword match that has been animated so close to the start that
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // the keyword match will hide even the icon of the regular match.
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool ShowOnlyKeywordMatch() const;
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Resets all RenderTexts for contents and description of the |match_| and its
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // associated keyword match.
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void ResetRenderTexts() const;
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Initializes |contents_rendertext_| if it is NULL.
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void InitContentsRenderTextIfNecessary() const;
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::View:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Layout() OVERRIDE;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // gfx::AnimationDelegate:
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Returns the offset at which the contents of the |match| should be displayed
14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // within the text bounds. The directionality of UI and match contents is used
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // to determine the offset relative to the correct edge.
15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int GetDisplayOffset(const AutocompleteMatch& match,
15223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       bool is_ui_rtl,
15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       bool is_match_contents_rtl) const;
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int default_icon_size_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default values cached here, may be overridden using the setters above.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int edge_item_padding_;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int item_padding_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int minimum_text_vertical_padding_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This row's model and model index.
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  OmniboxPopupContentsView* model_;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t model_index_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LocationBarView* location_bar_view_;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const gfx::FontList font_list_;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int font_height_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A context used for mirroring regions.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class MirroringContext;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MirroringContext> mirroring_context_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutocompleteMatch match_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect text_bounds_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect icon_bounds_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect keyword_text_bounds_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<views::ImageView> keyword_icon_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_ptr<gfx::SlideAnimation> animation_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // We preserve these RenderTexts so that we won't recreate them on every call
18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // to GetMatchContentsWidth() or OnPaint().
18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable scoped_ptr<gfx::RenderText> contents_rendertext_;
18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable scoped_ptr<gfx::RenderText> description_rendertext_;
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable scoped_ptr<gfx::RenderText> separator_rendertext_;
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable scoped_ptr<gfx::RenderText> keyword_contents_rendertext_;
19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable scoped_ptr<gfx::RenderText> keyword_description_rendertext_;
19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  mutable int separator_width_;
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OmniboxResultView);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_RESULT_VIEW_H_
199