Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / remoting / host / disconnect_window_mac.mm
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 <Cocoa/Cocoa.h>
6
7 #import "remoting/host/disconnect_window_mac.h"
8
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/i18n/rtl.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "remoting/base/string_resources.h"
16 #include "remoting/host/client_session_control.h"
17 #include "remoting/host/host_window.h"
18 #include "ui/base/l10n/l10n_util_mac.h"
19
20 @interface DisconnectWindowController()
21 - (BOOL)isRToL;
22 - (void)Hide;
23 @end
24
25 const int kMaximumConnectedNameWidthInPixels = 600;
26
27 namespace remoting {
28
29 class DisconnectWindowMac : public HostWindow {
30  public:
31   DisconnectWindowMac();
32   ~DisconnectWindowMac() override;
33
34   // HostWindow overrides.
35   void Start(const base::WeakPtr<ClientSessionControl>& client_session_control)
36       override;
37
38  private:
39   DisconnectWindowController* window_controller_;
40
41   DISALLOW_COPY_AND_ASSIGN(DisconnectWindowMac);
42 };
43
44 DisconnectWindowMac::DisconnectWindowMac()
45     : window_controller_(nil) {
46 }
47
48 DisconnectWindowMac::~DisconnectWindowMac() {
49   DCHECK(CalledOnValidThread());
50
51   // DisconnectWindowController is responsible for releasing itself in its
52   // windowWillClose: method.
53   [window_controller_ Hide];
54   window_controller_ = nil;
55 }
56
57 void DisconnectWindowMac::Start(
58     const base::WeakPtr<ClientSessionControl>& client_session_control) {
59   DCHECK(CalledOnValidThread());
60   DCHECK(client_session_control);
61   DCHECK(window_controller_ == nil);
62
63   // Create the window.
64   base::Closure disconnect_callback =
65       base::Bind(&ClientSessionControl::DisconnectSession,
66                  client_session_control);
67   std::string client_jid = client_session_control->client_jid();
68   std::string username = client_jid.substr(0, client_jid.find('/'));
69   window_controller_ =
70       [[DisconnectWindowController alloc] initWithCallback:disconnect_callback
71                                                   username:username];
72   [window_controller_ showWindow:nil];
73 }
74
75 // static
76 scoped_ptr<HostWindow> HostWindow::CreateDisconnectWindow() {
77   return make_scoped_ptr(new DisconnectWindowMac());
78 }
79
80 }  // namespace remoting
81
82 @implementation DisconnectWindowController
83 - (id)initWithCallback:(const base::Closure&)disconnect_callback
84               username:(const std::string&)username {
85   self = [super initWithWindowNibName:@"disconnect_window"];
86   if (self) {
87     disconnect_callback_ = disconnect_callback;
88     username_ = base::UTF8ToUTF16(username);
89   }
90   return self;
91 }
92
93 - (void)dealloc {
94   [super dealloc];
95 }
96
97 - (IBAction)stopSharing:(id)sender {
98   if (!disconnect_callback_.is_null()) {
99     disconnect_callback_.Run();
100   }
101 }
102
103 - (BOOL)isRToL {
104   return base::i18n::IsRTL();
105 }
106
107 - (void)Hide {
108   disconnect_callback_.Reset();
109   [self close];
110 }
111
112 - (void)windowDidLoad {
113   [connectedToField_ setStringValue:l10n_util::GetNSStringF(IDS_MESSAGE_SHARED,
114                                                             username_)];
115   [disconnectButton_ setTitle:l10n_util::GetNSString(IDS_STOP_SHARING_BUTTON)];
116
117   // Resize the window dynamically based on the content.
118   CGFloat oldConnectedWidth = NSWidth([connectedToField_ bounds]);
119   [connectedToField_ sizeToFit];
120   NSRect connectedToFrame = [connectedToField_ frame];
121   CGFloat newConnectedWidth = NSWidth(connectedToFrame);
122
123   // Set a max width for the connected to text field.
124   if (newConnectedWidth > kMaximumConnectedNameWidthInPixels) {
125     newConnectedWidth = kMaximumConnectedNameWidthInPixels;
126     connectedToFrame.size.width = newConnectedWidth;
127     [connectedToField_ setFrame:connectedToFrame];
128   }
129
130   CGFloat oldDisconnectWidth = NSWidth([disconnectButton_ bounds]);
131   [disconnectButton_ sizeToFit];
132   NSRect disconnectFrame = [disconnectButton_ frame];
133   CGFloat newDisconnectWidth = NSWidth(disconnectFrame);
134
135   // Move the disconnect button appropriately.
136   disconnectFrame.origin.x += newConnectedWidth - oldConnectedWidth;
137   [disconnectButton_ setFrame:disconnectFrame];
138
139   // Then resize the window appropriately
140   NSWindow *window = [self window];
141   NSRect windowFrame = [window frame];
142   windowFrame.size.width += (newConnectedWidth - oldConnectedWidth +
143                              newDisconnectWidth - oldDisconnectWidth);
144   [window setFrame:windowFrame display:NO];
145
146   if ([self isRToL]) {
147     // Handle right to left case
148     CGFloat buttonInset = NSWidth(windowFrame) - NSMaxX(disconnectFrame);
149     CGFloat buttonTextSpacing
150         = NSMinX(disconnectFrame) - NSMaxX(connectedToFrame);
151     disconnectFrame.origin.x = buttonInset;
152     connectedToFrame.origin.x = NSMaxX(disconnectFrame) + buttonTextSpacing;
153     [connectedToField_ setFrame:connectedToFrame];
154     [disconnectButton_ setFrame:disconnectFrame];
155   }
156
157   // Center the window at the bottom of the screen, above the dock (if present).
158   NSRect desktopRect = [[NSScreen mainScreen] visibleFrame];
159   NSRect windowRect = [[self window] frame];
160   CGFloat x = (NSWidth(desktopRect) - NSWidth(windowRect)) / 2;
161   CGFloat y = NSMinY(desktopRect);
162   [[self window] setFrameOrigin:NSMakePoint(x, y)];
163 }
164
165 - (void)windowWillClose:(NSNotification*)notification {
166   [self stopSharing:self];
167   [self autorelease];
168 }
169
170 @end
171
172
173 @interface DisconnectWindow()
174 - (BOOL)isRToL;
175 @end
176
177 @implementation DisconnectWindow
178
179 - (id)initWithContentRect:(NSRect)contentRect
180                 styleMask:(NSUInteger)aStyle
181                   backing:(NSBackingStoreType)bufferingType
182                   defer:(BOOL)flag {
183   // Pass NSBorderlessWindowMask for the styleMask to remove the title bar.
184   self = [super initWithContentRect:contentRect
185                           styleMask:NSBorderlessWindowMask
186                             backing:bufferingType
187                               defer:flag];
188
189   if (self) {
190     // Set window to be clear and non-opaque so we can see through it.
191     [self setBackgroundColor:[NSColor clearColor]];
192     [self setOpaque:NO];
193     [self setMovableByWindowBackground:YES];
194
195     // Pull the window up to Status Level so that it always displays.
196     [self setLevel:NSStatusWindowLevel];
197   }
198   return self;
199 }
200
201 - (BOOL)isRToL {
202   DCHECK([[self windowController] respondsToSelector:@selector(isRToL)]);
203   return [[self windowController] isRToL];
204 }
205
206 @end
207
208
209 @interface DisconnectView()
210 - (BOOL)isRToL;
211 @end
212
213 @implementation DisconnectView
214
215 - (BOOL)isRToL {
216   DCHECK([[self window] isKindOfClass:[DisconnectWindow class]]);
217   return [static_cast<DisconnectWindow*>([self window]) isRToL];
218 }
219
220 - (void)drawRect:(NSRect)rect {
221   // All magic numbers taken from screen shots provided by UX.
222   NSRect bounds = NSInsetRect([self bounds], 1, 1);
223
224   NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:bounds
225                                                        xRadius:5
226                                                        yRadius:5];
227   NSColor *gray = [NSColor colorWithCalibratedWhite:0.91 alpha:1.0];
228   [gray setFill];
229   [path fill];
230   [path setLineWidth:4];
231   NSColor *green = [NSColor colorWithCalibratedRed:0.13
232                                              green:0.69
233                                               blue:0.11
234                                              alpha:1.0];
235   [green setStroke];
236   [path stroke];
237
238
239   // Draw drag handle on proper side
240   const CGFloat kHeight = 21.0;
241   const CGFloat kBaseInset = 12.0;
242   const CGFloat kDragHandleWidth = 5.0;
243
244   NSColor *dark = [NSColor colorWithCalibratedWhite:0.70 alpha:1.0];
245   NSColor *light = [NSColor colorWithCalibratedWhite:0.97 alpha:1.0];
246
247   // Turn off aliasing so it's nice and crisp.
248   NSGraphicsContext *context = [NSGraphicsContext currentContext];
249   BOOL alias = [context shouldAntialias];
250   [context setShouldAntialias:NO];
251
252   // Handle bidirectional locales properly.
253   CGFloat inset = [self isRToL] ? NSMaxX(bounds) - kBaseInset - kDragHandleWidth
254                                 : kBaseInset;
255
256   NSPoint top = NSMakePoint(inset, NSMidY(bounds) - kHeight / 2.0);
257   NSPoint bottom = NSMakePoint(inset, top.y + kHeight);
258
259   path = [NSBezierPath bezierPath];
260   [path moveToPoint:top];
261   [path lineToPoint:bottom];
262   [dark setStroke];
263   [path stroke];
264
265   top.x += 1;
266   bottom.x += 1;
267   path = [NSBezierPath bezierPath];
268   [path moveToPoint:top];
269   [path lineToPoint:bottom];
270   [light setStroke];
271   [path stroke];
272
273   top.x += 2;
274   bottom.x += 2;
275   path = [NSBezierPath bezierPath];
276   [path moveToPoint:top];
277   [path lineToPoint:bottom];
278   [dark setStroke];
279   [path stroke];
280
281   top.x += 1;
282   bottom.x += 1;
283   path = [NSBezierPath bezierPath];
284   [path moveToPoint:top];
285   [path lineToPoint:bottom];
286   [light setStroke];
287   [path stroke];
288
289   [context setShouldAntialias:alias];
290 }
291
292 @end