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 137 // Overridden from CommandUpdaterDelegate: 138 virtual void ExecuteCommandWithDisposition( 139 int id, 140 WindowOpenDisposition disposition) OVERRIDE; 141 142 // content::NotificationObserver overrides. 143 virtual void Observe(int type, 144 const content::NotificationSource& source, 145 const content::NotificationDetails& details) OVERRIDE; 146 147 // Construct a native panel implementation. 148 static NativePanel* CreateNativePanel(Panel* panel, 149 const gfx::Rect& bounds, 150 bool always_on_top); 151 152 NativePanel* native_panel() const { return native_panel_; } 153 154 // Invoked when the native panel has detected a mouse click on the 155 // panel's titlebar, minimize or restore buttons. Behavior of the 156 // click may be modified as indicated by |modifier|. 157 void OnTitlebarClicked(panel::ClickModifier modifier); 158 void OnMinimizeButtonClicked(panel::ClickModifier modifier); 159 void OnRestoreButtonClicked(panel::ClickModifier modifier); 160 161 // Used on platforms where the panel cannot determine its window size 162 // until the window has been created. (e.g. GTK) 163 void OnWindowSizeAvailable(); 164 165 // Asynchronous completion of panel close request. 166 void OnNativePanelClosed(); 167 168 // May be NULL if: 169 // * panel is newly created and has not been positioned yet. 170 // * panel is being closed asynchronously. 171 // Please use it with caution. 172 PanelCollection* collection() const { return collection_; } 173 174 // Sets the current panel collection that contains this panel. 175 void set_collection(PanelCollection* new_collection) { 176 collection_ = new_collection; 177 } 178 179 StackedPanelCollection* stack() const; 180 181 ExpansionState expansion_state() const { return expansion_state_; } 182 const gfx::Size& min_size() const { return min_size_; } 183 const gfx::Size& max_size() const { return max_size_; } 184 bool auto_resizable() const { return auto_resizable_; } 185 186 bool in_preview_mode() const { return in_preview_mode_; } 187 188 panel::Resizability CanResizeByMouse() const; 189 190 AttentionMode attention_mode() const { return attention_mode_; } 191 void set_attention_mode(AttentionMode attention_mode) { 192 attention_mode_ = attention_mode; 193 } 194 195 // The full size is the size of the panel when it is detached or expanded 196 // in the docked collection and squeezing mode is not on. 197 gfx::Size full_size() const { return full_size_; } 198 void set_full_size(const gfx::Size& size) { full_size_ = size; } 199 200 // Panel must be initialized to be "fully created" and ready for use. 201 // Only called by PanelManager. 202 bool initialized() const { return initialized_; } 203 void Initialize(const GURL& url, const gfx::Rect& bounds, bool always_on_top); 204 205 // This is different from BaseWindow::SetBounds(): 206 // * SetPanelBounds() is only called by PanelManager to manage its position. 207 // * SetBounds() is called by the API to try to change the bounds, which may 208 // only change the size for Panel. 209 void SetPanelBounds(const gfx::Rect& bounds); 210 211 // Updates the panel bounds instantly without any animation. 212 void SetPanelBoundsInstantly(const gfx::Rect& bounds); 213 214 // Ensures that the panel's size does not exceed the work area by updating 215 // maximum and full size of the panel. This is called each time when display 216 // settings are changed. Note that bounds are not updated here and the call 217 // of setting bounds or refreshing layout should be called after this. 218 void LimitSizeToWorkArea(const gfx::Rect& work_area); 219 220 // Sets whether the panel will auto resize according to its content. 221 void SetAutoResizable(bool resizable); 222 223 // Configures the web contents for auto resize, including configurations 224 // on the renderer and detecting renderer changes. 225 void EnableWebContentsAutoResize(content::WebContents* web_contents); 226 227 // Invoked when the preferred window size of the given panel might need to 228 // get changed due to the contents being auto-resized. 229 void OnContentsAutoResized(const gfx::Size& new_content_size); 230 231 // Resizes the panel and sets the origin. Invoked when the panel is resized 232 // via the mouse. 233 void OnWindowResizedByMouse(const gfx::Rect& new_bounds); 234 235 // Sets minimum and maximum size for the panel. 236 void SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size); 237 238 // Updates the maximum size of the panel so that it's never smaller than the 239 // panel's desired size. Note that even if the user resizes the panel smaller 240 // later, the increased maximum size will still be in effect. Since it's not 241 // possible currently to switch the panel back to autosizing from 242 // user-resizable, it should not be a problem. 243 void IncreaseMaxSize(const gfx::Size& desired_panel_size); 244 245 // Handles keyboard events coming back from the renderer. 246 void HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event); 247 248 // Whether the panel window is always on top. 249 void SetAlwaysOnTop(bool on_top); 250 251 // Sets whether the panel is shown in preview mode. When the panel is 252 // being dragged, it is in preview mode. 253 void SetPreviewMode(bool in_preview_mode); 254 255 // Sets up the panel for being resizable by the user - for example, 256 // enables the resize mouse cursors when mouse is hovering over the edges. 257 void EnableResizeByMouse(bool enable); 258 259 // Sets whether the minimize or restore button, if any, are visible. 260 void UpdateMinimizeRestoreButtonVisibility(); 261 262 // Changes the preferred size to acceptable based on min_size() and max_size() 263 gfx::Size ClampSize(const gfx::Size& size) const; 264 265 // Called when the panel's active state changes. 266 // |active| is true if panel became active. 267 void OnActiveStateChanged(bool active); 268 269 // Called when the panel starts/ends the user resizing. 270 void OnPanelStartUserResizing(); 271 void OnPanelEndUserResizing(); 272 273 // Gives beforeunload handlers the chance to cancel the close. 274 bool ShouldCloseWindow(); 275 276 // Invoked when the window containing us is closing. Performs the necessary 277 // cleanup. 278 void OnWindowClosing(); 279 280 // Executes a command if it's enabled. 281 // Returns true if the command is executed. 282 bool ExecuteCommandIfEnabled(int id); 283 284 // Gets the title of the window from the web contents. 285 string16 GetWindowTitle() const; 286 287 // Gets the Favicon of the web contents. 288 gfx::Image GetCurrentPageIcon() const; 289 290 // Updates the title bar to display the current title and icon. 291 void UpdateTitleBar(); 292 293 // Updates UI to reflect change in loading state. 294 void LoadingStateChanged(bool is_loading); 295 296 // Updates UI to reflect that the web cotents receives the focus. 297 void WebContentsFocused(content::WebContents* contents); 298 299 // Moves the panel by delta instantly. 300 void MoveByInstantly(const gfx::Vector2d& delta_origin); 301 302 // Applies |corner_style| to the panel window. 303 void SetWindowCornerStyle(panel::CornerStyle corner_style); 304 305 // Performs the system minimize for the panel, i.e. becoming iconic. 306 void MinimizeBySystem(); 307 308 bool IsMinimizedBySystem() const; 309 310 // Returns true if the panel is shown in the active desktop. The user could 311 // create or use multiple desktops or workspaces. 312 bool IsShownOnActiveDesktop() const; 313 314 // Turns on/off the shadow effect around the window shape. 315 void ShowShadow(bool show); 316 317 protected: 318 // Panel can only be created using PanelManager::CreatePanel() or subclass. 319 // |app_name| is the default title for Panels when the page content does not 320 // provide a title. For extensions, this is usually the application name 321 // generated from the extension id. 322 Panel(Profile* profile, const std::string& app_name, 323 const gfx::Size& min_size, const gfx::Size& max_size); 324 325 private: 326 friend class PanelManager; 327 friend class PanelBrowserTest; 328 329 enum MaxSizePolicy { 330 // Default maximum size is proportional to the work area. 331 DEFAULT_MAX_SIZE, 332 // Custom maximum size is used when the panel is resized by the user. 333 CUSTOM_MAX_SIZE 334 }; 335 336 void OnImageLoaded(const gfx::Image& image); 337 338 // Initialize state for all supported commands. 339 void InitCommandState(); 340 341 // Configures the renderer for auto resize (if auto resize is enabled). 342 void ConfigureAutoResize(content::WebContents* web_contents); 343 344 // Load the app's image, firing a load state change when loaded. 345 void UpdateAppIcon(); 346 347 // Prepares a title string for display (removes embedded newlines, etc). 348 static void FormatTitleForDisplay(string16* title); 349 350 // The application name that is also the name of the window when the 351 // page content does not provide a title. 352 // This name should be set when the panel is created. 353 const std::string app_name_; 354 355 Profile* profile_; 356 357 // Current collection of panels to which this panel belongs. This determines 358 // the panel's screen layout. 359 PanelCollection* collection_; // Owned by PanelManager. 360 361 bool initialized_; 362 363 // Stores the full size of the panel so we can restore it after it's 364 // been minimized or squeezed due to lack of space in the collection. 365 gfx::Size full_size_; 366 367 // This is the minimum size that the panel can shrink to. 368 gfx::Size min_size_; 369 370 // This is the size beyond which the panel is not going to grow to accomodate 371 // the growing content and WebKit would add the scrollbars in such case. 372 gfx::Size max_size_; 373 374 MaxSizePolicy max_size_policy_; 375 376 // True if this panel auto resizes based on content. 377 bool auto_resizable_; 378 379 // True if this panel is in preview mode. When in preview mode, panel bounds 380 // should not be affected by layout refresh. This is currently used by drag 381 // controller to add a panel to the collection without causing its bounds to 382 // change. 383 bool in_preview_mode_; 384 385 // Platform specifc implementation for panels. It'd be one of 386 // PanelGtk/PanelView/PanelCocoa. 387 NativePanel* native_panel_; // Weak, owns us. 388 389 AttentionMode attention_mode_; 390 391 ExpansionState expansion_state_; 392 393 // The CommandUpdater manages the window commands. 394 CommandUpdater command_updater_; 395 396 content::NotificationRegistrar registrar_; 397 const SessionID session_id_; 398 scoped_ptr<extensions::WindowController> extension_window_controller_; 399 scoped_ptr<PanelHost> panel_host_; 400 401 // Icon showed in the task bar. 402 gfx::Image app_icon_; 403 404 base::WeakPtrFactory<Panel> image_loader_ptr_factory_; 405 406 DISALLOW_COPY_AND_ASSIGN(Panel); 407 }; 408 409 #endif // CHROME_BROWSER_UI_PANELS_PANEL_H_ 410