Home | History | Annotate | Download | only in cocoa
      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 #import "chrome/browser/ui/cocoa/dev_tools_controller.h"
      6 
      7 #include <algorithm>
      8 #include <cmath>
      9 
     10 #include <Cocoa/Cocoa.h>
     11 
     12 #include "base/prefs/pref_service.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #import "chrome/browser/ui/cocoa/view_id_util.h"
     16 #include "chrome/common/pref_names.h"
     17 #include "content/public/browser/web_contents.h"
     18 #include "ui/base/cocoa/base_view.h"
     19 #include "ui/base/cocoa/focus_tracker.h"
     20 #include "ui/gfx/mac/scoped_ns_disable_screen_updates.h"
     21 #include "ui/gfx/size_conversions.h"
     22 
     23 using content::WebContents;
     24 
     25 @interface DevToolsContainerView : BaseView {
     26   DevToolsContentsResizingStrategy strategy_;
     27 
     28   // Weak references. Ownership via -subviews.
     29   NSView* devToolsView_;
     30   NSView* contentsView_;
     31 }
     32 
     33 - (void)setDevToolsView:(NSView*)devToolsView
     34            withStrategy:(const DevToolsContentsResizingStrategy&)strategy;
     35 - (void)adjustSubviews;
     36 - (BOOL)hasDevToolsView;
     37 
     38 @end
     39 
     40 
     41 @implementation DevToolsContainerView
     42 
     43 - (void)setDevToolsView:(NSView*)devToolsView
     44            withStrategy:(const DevToolsContentsResizingStrategy&)strategy {
     45   strategy_.CopyFrom(strategy);
     46   if (devToolsView == devToolsView_) {
     47     if (contentsView_)
     48       [contentsView_ setHidden:strategy.hide_inspected_contents()];
     49     return;
     50   }
     51 
     52   if (devToolsView_) {
     53     DCHECK_EQ(2u, [[self subviews] count]);
     54     [devToolsView_ removeFromSuperview];
     55     [contentsView_ setHidden:NO];
     56     contentsView_ = nil;
     57     devToolsView_ = nil;
     58   }
     59 
     60   if (devToolsView) {
     61     NSArray* subviews = [self subviews];
     62     DCHECK_EQ(1u, [subviews count]);
     63     contentsView_ = [subviews objectAtIndex:0];
     64     devToolsView_ = devToolsView;
     65     // Place DevTools under contents.
     66     [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
     67 
     68     [contentsView_ setHidden:strategy.hide_inspected_contents()];
     69   }
     70 }
     71 
     72 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
     73   [self adjustSubviews];
     74 }
     75 
     76 - (BOOL)hasDevToolsView {
     77   return devToolsView_ != nil;
     78 }
     79 
     80 - (void)adjustSubviews {
     81   if (![[self subviews] count])
     82     return;
     83 
     84   if (!devToolsView_) {
     85     DCHECK_EQ(1u, [[self subviews] count]);
     86     NSView* contents = [[self subviews] objectAtIndex:0];
     87     [contents setFrame:[self bounds]];
     88     return;
     89   }
     90 
     91   DCHECK_EQ(2u, [[self subviews] count]);
     92 
     93   gfx::Rect new_devtools_bounds;
     94   gfx::Rect new_contents_bounds;
     95   ApplyDevToolsContentsResizingStrategy(
     96       strategy_, gfx::Size(NSSizeToCGSize([self bounds].size)),
     97       &new_devtools_bounds, &new_contents_bounds);
     98   [devToolsView_ setFrame:[self flipRectToNSRect:new_devtools_bounds]];
     99   [contentsView_ setFrame:[self flipRectToNSRect:new_contents_bounds]];
    100 }
    101 
    102 @end
    103 
    104 
    105 @implementation DevToolsController
    106 
    107 - (id)init {
    108   if ((self = [super init])) {
    109     devToolsContainerView_.reset(
    110         [[DevToolsContainerView alloc] initWithFrame:NSZeroRect]);
    111     [devToolsContainerView_
    112         setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
    113   }
    114   return self;
    115 }
    116 
    117 - (NSView*)view {
    118   return devToolsContainerView_.get();
    119 }
    120 
    121 - (void)updateDevToolsForWebContents:(WebContents*)contents
    122                          withProfile:(Profile*)profile {
    123   DevToolsContentsResizingStrategy strategy;
    124   WebContents* devTools = DevToolsWindow::GetInTabWebContents(
    125       contents, &strategy);
    126 
    127   // Make sure we do not draw any transient arrangements of views.
    128   gfx::ScopedNSDisableScreenUpdates disabler;
    129 
    130   if (devTools && ![devToolsContainerView_ hasDevToolsView]) {
    131     focusTracker_.reset(
    132         [[FocusTracker alloc] initWithWindow:[devToolsContainerView_ window]]);
    133   }
    134 
    135   if (!devTools && [devToolsContainerView_ hasDevToolsView]) {
    136     [focusTracker_ restoreFocusInWindow:[devToolsContainerView_ window]];
    137     focusTracker_.reset();
    138   }
    139 
    140   NSView* devToolsView = nil;
    141   if (devTools) {
    142     devToolsView = devTools->GetNativeView();
    143     // |devToolsView| is a WebContentsViewCocoa object, whose ViewID was
    144     // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
    145     // VIEW_ID_DEV_TOOLS_DOCKED here.
    146     view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED);
    147 
    148     devTools->SetAllowOtherViews(true);
    149     contents->SetAllowOtherViews(true);
    150   } else {
    151     contents->SetAllowOtherViews(false);
    152   }
    153 
    154   [devToolsContainerView_ setDevToolsView:devToolsView withStrategy:strategy];
    155   [devToolsContainerView_ adjustSubviews];
    156 }
    157 
    158 @end
    159