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_UI_PANELS_PANEL_H_ 6 #define CHROME_BROWSER_UI_PANELS_PANEL_H_ 7 8 #include <string> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/strings/string16.h" 14 #include "chrome/browser/command_updater.h" 15 #include "chrome/browser/command_updater_delegate.h" 16 #include "chrome/browser/sessions/session_id.h" 17 #include "chrome/browser/ui/panels/panel_constants.h" 18 #include "content/public/browser/notification_observer.h" 19 #include "content/public/browser/notification_registrar.h" 20 #include "ui/base/base_window.h" 21 #include "ui/gfx/image/image.h" 22 #include "ui/gfx/rect.h" 23 24 class GURL; 25 class NativePanel; 26 class PanelCollection; 27 class PanelHost; 28 class PanelManager; 29 class Profile; 30 class StackedPanelCollection; 31 32 namespace content { 33 class WebContents; 34 struct NativeWebKeyboardEvent; 35 } 36 37 namespace extensions { 38 class Extension; 39 class WindowController; 40 } 41 42 // A platform independent implementation of ui::BaseWindow for Panels. 43 // This class gets the first crack at all the ui::BaseWindow calls for Panels 44 // and does one or more of the following: 45 // - Do nothing. The function is not relevant to Panels. 46 // - Do Panel specific platform independent processing and then invoke the 47 // function on the platform specific member. For example, restrict panel 48 // size to certain limits. 49 // - Invoke an appropriate PanelManager function to do stuff that might affect 50 // other Panels. For example deleting a panel would rearrange other panels. 51 class Panel : public ui::BaseWindow, 52 public CommandUpdaterDelegate, 53 public content::NotificationObserver { 54 public: 55 enum ExpansionState { 56 // The panel is fully expanded with both title-bar and the client-area. 57 EXPANDED, 58 // The panel is shown with the title-bar only. 59 TITLE_ONLY, 60 // The panel is shown with 3-pixel line. 61 MINIMIZED 62 }; 63 64 // Controls how the attention should be drawn. 65 enum AttentionMode { 66 // Uses the panel attention. The panel's titlebar would be painted 67 // differently to attract the user's attention. This is the default mode. 68 USE_PANEL_ATTENTION = 0x01, 69 // Uses the system attention. On Windows or Linux (depending on Window 70 // Manager), the app icon on taskbar will be flashed. On MacOS, the dock 71 // icon will jump once. 72 USE_SYSTEM_ATTENTION = 0x02 73 }; 74 75 virtual ~Panel(); 76 77 // Returns the PanelManager associated with this panel. 78 PanelManager* manager() const; 79 80 const std::string& app_name() const { return app_name_; } 81 const gfx::Image& app_icon() const { return app_icon_; } 82 const SessionID& session_id() const { return session_id_; } 83 extensions::WindowController* extension_window_controller() const { 84 return extension_window_controller_.get(); 85 } 86 const std::string extension_id() const; 87 88 CommandUpdater* command_updater(); 89 Profile* profile() const; 90 91 const extensions::Extension* GetExtension() const; 92 93 // Returns web contents of the panel, if any. There may be none if web 94 // contents have not been added to the panel yet. 95 content::WebContents* GetWebContents() const; 96 97 void SetExpansionState(ExpansionState new_expansion_state); 98 99 bool IsDrawingAttention() const; 100 101 // This function will only get called by PanelManager when full screen mode 102 // changes i.e it gets called when an app goes into full screen mode or when 103 // an app exits full screen mode. Panel should respond by making sure 104 // a) it does not go on top when some app enters full screen mode. 105 // b) it remains on top when an app exits full screen mode. 106 void FullScreenModeChanged(bool is_full_screen); 107 108 int TitleOnlyHeight() const; 109 110 // Returns true if the panel can show minimize or restore button in its 111 // titlebar, depending on its state. 112 bool CanShowMinimizeButton() const; 113 bool CanShowRestoreButton() const; 114 115 // ui::BaseWindow overrides. 116 virtual bool IsActive() const OVERRIDE; 117 virtual bool IsMaximized() const OVERRIDE; 118 virtual bool IsMinimized() const OVERRIDE; 119 virtual bool IsFullscreen() const OVERRIDE; 120 virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; 121 virtual gfx::Rect GetRestoredBounds() const OVERRIDE; 122 virtual ui::WindowShowState GetRestoredState() const OVERRIDE; 123 virtual gfx::Rect GetBounds() const OVERRIDE; 124 virtual void Show() OVERRIDE; 125 virtual void Hide() OVERRIDE; 126 virtual void ShowInactive() OVERRIDE; 127 virtual void Close() OVERRIDE; 128 virtual void Activate() OVERRIDE; 129 virtual void Deactivate() OVERRIDE; 130 virtual void Maximize() OVERRIDE; 131 virtual void Minimize() OVERRIDE; 132 virtual void Restore() OVERRIDE; 133 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; 134 virtual void FlashFrame(bool flash) OVERRIDE; 135 virtual bool IsAlwaysOnTop() const OVERRIDE; 136 virtual void SetAlwaysOnTop(bool on_top) OVERRIDE; 137 138 // Overridden from CommandUpdaterDelegate: 139 virtual void ExecuteCommandWithDisposition( 140 int id, 141 WindowOpenDisposition disposition) OVERRIDE; 142 143 // content::NotificationObserver overrides. 144 virtual void Observe(int type, 145 const content::NotificationSource& source, 146 const content::NotificationDetails& details) OVERRIDE; 147 148 // Construct a native panel implementation. 149 static NativePanel* CreateNativePanel(Panel* panel, 150 const gfx::Rect& bounds, 151 bool always_on_top); 152 153 NativePanel* native_panel() const { return native_panel_; } 154 155 // Invoked when the native panel has detected a mouse click on the 156 // panel's titlebar, minimize or restore buttons. Behavior of the 157 // click may be modified as indicated by |modifier|. 158 void OnTitlebarClicked(panel::ClickModifier modifier); 159 void OnMinimizeButtonClicked(panel::ClickModifier modifier); 160 void OnRestoreButtonClicked(panel::ClickModifier modifier); 161 162 // Used on platforms where the panel cannot determine its window size 163 // until the window has been created. (e.g. GTK) 164 void OnWindowSizeAvailable(); 165 166 // Asynchronous completion of panel close request. 167 void OnNativePanelClosed(); 168 169 // May be NULL if: 170 // * panel is newly created and has not been positioned yet. 171 // * panel is being closed asynchronously. 172 // Please use it with caution. 173 PanelCollection* collection() const { return collection_; } 174 175 // Sets the current panel collection that contains this panel. 176 void set_collection(PanelCollection* new_collection) { 177 collection_ = new_collection; 178 } 179 180 StackedPanelCollection* stack() const; 181 182 ExpansionState expansion_state() const { return expansion_state_; } 183 const gfx::Size& min_size() const { return min_size_; } 184 const gfx::Size& max_size() const { return max_size_; } 185 bool auto_resizable() const { return auto_resizable_; } 186 187 bool in_preview_mode() const { return in_preview_mode_; } 188 189 panel::Resizability CanResizeByMouse() const; 190 191 AttentionMode attention_mode() const { return attention_mode_; } 192 void set_attention_mode(AttentionMode attention_mode) { 193 attention_mode_ = attention_mode; 194 } 195 196 // The full size is the size of the panel when it is detached or expanded 197 // in the docked collection and squeezing mode is not on. 198 gfx::Size full_size() const { return full_size_; } 199 void set_full_size(const gfx::Size& size) { full_size_ = size; } 200 201 // Panel must be initialized to be "fully created" and ready for use. 202 // Only called by PanelManager. 203 bool initialized() const { return initialized_; } 204 void Initialize(const GURL& url, const gfx::Rect& bounds, bool always_on_top); 205 206 // This is different from BaseWindow::SetBounds(): 207 // * SetPanelBounds() is only called by PanelManager to manage its position. 208 // * SetBounds() is called by the API to try to change the bounds, which may 209 // only change the size for Panel. 210 void SetPanelBounds(const gfx::Rect& bounds); 211 212 // Updates the panel bounds instantly without any animation. 213 void SetPanelBoundsInstantly(const gfx::Rect& bounds); 214 215 // Ensures that the panel's size does not exceed the work area by updating 216 // maximum and full size of the panel. This is called each time when display 217 // settings are changed. Note that bounds are not updated here and the call 218 // of setting bounds or refreshing layout should be called after this. 219 void LimitSizeToWorkArea(const gfx::Rect& work_area); 220 221 // Sets whether the panel will auto resize according to its content. 222 void SetAutoResizable(bool resizable); 223 224 // Configures the web contents for auto resize, including configurations 225 // on the renderer and detecting renderer changes. 226 void EnableWebContentsAutoResize(content::WebContents* web_contents); 227 228 // Invoked when the preferred window size of the given panel might need to 229 // get changed due to the contents being auto-resized. 230 void OnContentsAutoResized(const gfx::Size& new_content_size); 231 232 // Resizes the panel and sets the origin. Invoked when the panel is resized 233 // via the mouse. 234 void OnWindowResizedByMouse(const gfx::Rect& new_bounds); 235 236 // Sets minimum and maximum size for the panel. 237 void SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size); 238 239 // Updates the maximum size of the panel so that it's never smaller than the 240 // panel's desired size. Note that even if the user resizes the panel smaller 241 // later, the increased maximum size will still be in effect. Since it's not 242 // possible currently to switch the panel back to autosizing from 243 // user-resizable, it should not be a problem. 244 void IncreaseMaxSize(const gfx::Size& desired_panel_size); 245 246 // Handles keyboard events coming back from the renderer. 247 void HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event); 248 249 // Sets whether the panel is shown in preview mode. When the panel is 250 // being dragged, it is in preview mode. 251 void SetPreviewMode(bool in_preview_mode); 252 253 // Sets whether the minimize or restore button, if any, are visible. 254 void UpdateMinimizeRestoreButtonVisibility(); 255 256 // Changes the preferred size to acceptable based on min_size() and max_size() 257 gfx::Size ClampSize(const gfx::Size& size) const; 258 259 // Called when the panel's active state changes. 260 // |active| is true if panel became active. 261 void OnActiveStateChanged(bool active); 262 263 // Called when the panel starts/ends the user resizing. 264 void OnPanelStartUserResizing(); 265 void OnPanelEndUserResizing(); 266 267 // Gives beforeunload handlers the chance to cancel the close. 268 bool ShouldCloseWindow(); 269 270 // Invoked when the window containing us is closing. Performs the necessary 271 // cleanup. 272 void OnWindowClosing(); 273 274 // Executes a command if it's enabled. 275 // Returns true if the command is executed. 276 bool ExecuteCommandIfEnabled(int id); 277 278 // Gets the title of the window from the web contents. 279 base::string16 GetWindowTitle() const; 280 281 // Gets the Favicon of the web contents. 282 gfx::Image GetCurrentPageIcon() const; 283 284 // Updates the title bar to display the current title and icon. 285 void UpdateTitleBar(); 286 287 // Updates UI to reflect change in loading state. 288 void LoadingStateChanged(bool is_loading); 289 290 // Updates UI to reflect that the web cotents receives the focus. 291 void WebContentsFocused(content::WebContents* contents); 292 293 // Moves the panel by delta instantly. 294 void MoveByInstantly(const gfx::Vector2d& delta_origin); 295 296 // Applies |corner_style| to the panel window. 297 void SetWindowCornerStyle(panel::CornerStyle corner_style); 298 299 // Performs the system minimize for the panel, i.e. becoming iconic. 300 void MinimizeBySystem(); 301 302 bool IsMinimizedBySystem() const; 303 304 // Returns true if the panel is shown in the active desktop. The user could 305 // create or use multiple desktops or workspaces. 306 bool IsShownOnActiveDesktop() const; 307 308 // Turns on/off the shadow effect around the window shape. 309 void ShowShadow(bool show); 310 311 protected: 312 // Panel can only be created using PanelManager::CreatePanel() or subclass. 313 // |app_name| is the default title for Panels when the page content does not 314 // provide a title. For extensions, this is usually the application name 315 // generated from the extension id. 316 Panel(Profile* profile, const std::string& app_name, 317 const gfx::Size& min_size, const gfx::Size& max_size); 318 319 private: 320 friend class PanelManager; 321 friend class PanelBrowserTest; 322 323 enum MaxSizePolicy { 324 // Default maximum size is proportional to the work area. 325 DEFAULT_MAX_SIZE, 326 // Custom maximum size is used when the panel is resized by the user. 327 CUSTOM_MAX_SIZE 328 }; 329 330 void OnImageLoaded(const gfx::Image& image); 331 332 // Initialize state for all supported commands. 333 void InitCommandState(); 334 335 // Configures the renderer for auto resize (if auto resize is enabled). 336 void ConfigureAutoResize(content::WebContents* web_contents); 337 338 // Load the app's image, firing a load state change when loaded. 339 void UpdateAppIcon(); 340 341 // Prepares a title string for display (removes embedded newlines, etc). 342 static void FormatTitleForDisplay(base::string16* title); 343 344 // The application name that is also the name of the window when the 345 // page content does not provide a title. 346 // This name should be set when the panel is created. 347 const std::string app_name_; 348 349 Profile* profile_; 350 351 // Current collection of panels to which this panel belongs. This determines 352 // the panel's screen layout. 353 PanelCollection* collection_; // Owned by PanelManager. 354 355 bool initialized_; 356 357 // Stores the full size of the panel so we can restore it after it's 358 // been minimized or squeezed due to lack of space in the collection. 359 gfx::Size full_size_; 360 361 // This is the minimum size that the panel can shrink to. 362 gfx::Size min_size_; 363 364 // This is the size beyond which the panel is not going to grow to accomodate 365 // the growing content and WebKit would add the scrollbars in such case. 366 gfx::Size max_size_; 367 368 MaxSizePolicy max_size_policy_; 369 370 // True if this panel auto resizes based on content. 371 bool auto_resizable_; 372 373 // True if this panel is in preview mode. When in preview mode, panel bounds 374 // should not be affected by layout refresh. This is currently used by drag 375 // controller to add a panel to the collection without causing its bounds to 376 // change. 377 bool in_preview_mode_; 378 379 // Platform specifc implementation for panels. It'd be one of 380 // PanelGtk/PanelView/PanelCocoa. 381 NativePanel* native_panel_; // Weak, owns us. 382 383 AttentionMode attention_mode_; 384 385 ExpansionState expansion_state_; 386 387 // The CommandUpdater manages the window commands. 388 CommandUpdater command_updater_; 389 390 content::NotificationRegistrar registrar_; 391 const SessionID session_id_; 392 scoped_ptr<extensions::WindowController> extension_window_controller_; 393 scoped_ptr<PanelHost> panel_host_; 394 395 // Icon showed in the task bar. 396 gfx::Image app_icon_; 397 398 base::WeakPtrFactory<Panel> image_loader_ptr_factory_; 399 400 DISALLOW_COPY_AND_ASSIGN(Panel); 401 }; 402 403 #endif // CHROME_BROWSER_UI_PANELS_PANEL_H_ 404