1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_VIEW_H_ 6 #define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_VIEW_H_ 7 8 #include "base/gtest_prod_util.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "chromeos/ime/candidate_window.h" 11 #include "ui/views/view.h" 12 13 namespace gfx { 14 class Font; 15 } 16 17 namespace chromeos { 18 namespace input_method { 19 20 class CandidateView; 21 class CandidateWindow; 22 class HidableArea; 23 class InformationTextArea; 24 25 // CandidateWindowView is the main container of the candidate window UI. 26 class CandidateWindowView : public views::View { 27 public: 28 // The object can be monitored by the observer. 29 class Observer { 30 public: ~Observer()31 virtual ~Observer() {} 32 // The function is called when a candidate is committed. 33 virtual void OnCandidateCommitted(int index) = 0; 34 35 virtual void OnCandidateWindowOpened() = 0; 36 virtual void OnCandidateWindowClosed() = 0; 37 }; 38 39 explicit CandidateWindowView(views::Widget* parent_frame); 40 virtual ~CandidateWindowView(); 41 void Init(); 42 43 // Adds the given observer. The ownership is not transferred. AddObserver(Observer * observer)44 void AddObserver(Observer* observer) { 45 observers_.AddObserver(observer); 46 } 47 48 // Removes the given observer. RemoveObserver(Observer * observer)49 void RemoveObserver(Observer* observer) { 50 observers_.RemoveObserver(observer); 51 } 52 53 // Selects the candidate specified by the index in the current page 54 // (zero-origin). Changes the appearance of the selected candidate, 55 // updates the information in the candidate window as needed. 56 void SelectCandidateAt(int index_in_page); 57 58 // The function is called when a candidate is being dragged. From the 59 // given point, locates the candidate under the mouse cursor, and 60 // selects it. 61 void OnCandidatePressed(const gfx::Point& point); 62 63 // Commits the candidate currently being selected. 64 void CommitCandidate(); 65 66 // Hides the lookup table. 67 void HideLookupTable(); 68 69 // Hides the auxiliary text. 70 void HideAuxiliaryText(); 71 72 // Hides the preedit text. 73 void HidePreeditText(); 74 75 // Hides whole the candidate window. 76 void HideAll(); 77 78 // Shows the lookup table. 79 void ShowLookupTable(); 80 81 // Shows the auxiliary text. 82 void ShowAuxiliaryText(); 83 84 // Shows the preedit text. 85 void ShowPreeditText(); 86 87 // Updates the auxiliary text. 88 void UpdateAuxiliaryText(const std::string& utf8_text); 89 90 // Updates the preedit text. 91 void UpdatePreeditText(const std::string& utf8_text); 92 93 // Returns true if we should update candidate views in the window. For 94 // instance, if we are going to show the same candidates as before, we 95 // don't have to update candidate views. This happens when the user just 96 // moves the cursor in the same page in the candidate window. 97 static bool ShouldUpdateCandidateViews( 98 const CandidateWindow& old_candidate_window, 99 const CandidateWindow& new_candidate_window); 100 101 // Updates candidates of the candidate window from |candidate_window|. 102 // Candidates are arranged per |orientation|. 103 void UpdateCandidates(const CandidateWindow& candidate_window); 104 105 // Resizes and moves the parent frame. The two actions should be 106 // performed consecutively as resizing may require the candidate window 107 // to move. For instance, we may need to move the candidate window from 108 // below the cursor to above the cursor, if the candidate window becomes 109 // too big to be shown near the bottom of the screen. This function 110 // needs to be called when the visible contents of the candidate window 111 // are modified. 112 void ResizeAndMoveParentFrame(); 113 114 // Returns the horizontal offset used for placing the vertical candidate 115 // window so that the first candidate is aligned with the the text being 116 // converted like: 117 // 118 // XXX <- The user is converting XXX 119 // +-----+ 120 // |1 XXX| 121 // |2 YYY| 122 // |3 ZZZ| 123 // 124 // Returns 0 if no candidate is present. 125 int GetHorizontalOffset(); 126 set_cursor_bounds(const gfx::Rect & cursor_bounds)127 void set_cursor_bounds(const gfx::Rect& cursor_bounds) { 128 cursor_bounds_ = cursor_bounds; 129 } 130 set_composition_head_bounds(const gfx::Rect & composition_head_bounds)131 void set_composition_head_bounds( 132 const gfx::Rect& composition_head_bounds) { 133 composition_head_bounds_ = composition_head_bounds; 134 } 135 cursor_bounds()136 const gfx::Rect& cursor_bounds() const { return cursor_bounds_; } composition_head_bounds()137 const gfx::Rect& composition_head_bounds() const { 138 return composition_head_bounds_; 139 } 140 141 protected: 142 // Override View::VisibilityChanged() 143 virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE; 144 145 // Override View::OnBoundsChanged() 146 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 147 148 private: 149 FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, 150 UpdateCandidatesTest_CursorVisibility); 151 FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, ShortcutSettingTest); 152 FRIEND_TEST_ALL_PREFIXES(CandidateWindowViewTest, 153 DoNotChangeRowHeightWithLabelSwitchTest); 154 155 // Initializes the candidate views if needed. 156 void MaybeInitializeCandidateViews(const CandidateWindow& candidate_window); 157 158 // Returns the appropriate area (header or footer) to put auxiliary texts. 159 InformationTextArea* GetAuxiliaryTextArea(); 160 161 // Returns true if the candidate window is open. The suggestion window does 162 // not count as the candidate window. 163 bool IsCandidateWindowOpen() const; 164 165 // Notifies observers if the candidate window's opened/closed state has 166 // changed from the previous call to this function. 167 void NotifyIfCandidateWindowOpenedOrClosed(); 168 169 // The candidate window. 170 CandidateWindow candidate_window_; 171 172 // The index in the current page of the candidate currently being selected. 173 int selected_candidate_index_in_page_; 174 175 // The observers of the object. 176 ObserverList<Observer> observers_; 177 178 // The parent frame. 179 views::Widget* parent_frame_; 180 181 // Views created in the class will be part of tree of |this|, so these 182 // child views will be deleted when |this| is deleted. 183 184 // The preedit area is where the preedit text is shown, if it is needed 185 // in cases such as the focus is on a plugin that doesn't support in-line 186 // preedit drawing. 187 InformationTextArea* preedit_area_; 188 // The header area is where the auxiliary text is shown, if the 189 // orientation is horizontal. If the auxiliary text is not provided, we 190 // show nothing. For instance, we show pinyin text like "zhong'guo". 191 InformationTextArea* header_area_; 192 // The candidate area is where candidates are rendered. 193 HidableArea* candidate_area_; 194 // The candidate views are used for rendering candidates. 195 std::vector<CandidateView*> candidate_views_; 196 // The footer area is where the auxiliary text is shown, if the 197 // orientation is vertical. Usually the auxiliary text is used for 198 // showing candidate number information like 2/19. 199 InformationTextArea* footer_area_; 200 201 // Current columns size in |candidate_area_|. 202 gfx::Size previous_shortcut_column_size_; 203 gfx::Size previous_candidate_column_size_; 204 gfx::Size previous_annotation_column_size_; 205 206 // The last cursor bounds. 207 gfx::Rect cursor_bounds_; 208 209 // The last compostion head bounds. 210 gfx::Rect composition_head_bounds_; 211 212 // True if the candidate window should be shown with aligning with composition 213 // text as opposed to the cursor. 214 bool should_show_at_composition_head_; 215 216 // True if the candidate window should be shonw on the upper side of 217 // composition text. 218 bool should_show_upper_side_; 219 220 // True if the candidate window was open. This is used to determine when to 221 // send OnCandidateWindowOpened and OnCandidateWindowClosed events. 222 bool was_candidate_window_open_; 223 224 // This function judge whether the candidate window should be shown or not, 225 // if should be, shows parent_frame and if not, hides parent_frame. 226 void UpdateParentArea(); 227 228 DISALLOW_COPY_AND_ASSIGN(CandidateWindowView); 229 }; 230 231 } // namespace input_method 232 } // namespace chromeos 233 234 #endif // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_CANDIDATE_WINDOW_VIEW_H_ 235