1 package ch
.cyberduck
.ui
.cocoa
;
4 * Copyright (c) 2005 David Kocher. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to:
18 * dkocher@cyberduck.ch
21 import ch
.cyberduck
.binding
.application
.NSAlert
;
22 import ch
.cyberduck
.binding
.application
.NSButton
;
23 import ch
.cyberduck
.binding
.application
.NSCell
;
24 import ch
.cyberduck
.binding
.application
.NSPrintInfo
;
25 import ch
.cyberduck
.binding
.application
.NSPrintOperation
;
26 import ch
.cyberduck
.binding
.application
.NSPrintPanel
;
27 import ch
.cyberduck
.binding
.application
.NSTextField
;
28 import ch
.cyberduck
.binding
.application
.NSTextView
;
29 import ch
.cyberduck
.binding
.application
.NSView
;
30 import ch
.cyberduck
.binding
.application
.NSWindow
;
31 import ch
.cyberduck
.binding
.application
.SheetCallback
;
32 import ch
.cyberduck
.binding
.foundation
.NSAttributedString
;
33 import ch
.cyberduck
.binding
.foundation
.NSDictionary
;
34 import ch
.cyberduck
.binding
.foundation
.NSNotification
;
35 import ch
.cyberduck
.core
.Host
;
36 import ch
.cyberduck
.core
.LocaleFactory
;
37 import ch
.cyberduck
.core
.exception
.BackgroundException
;
38 import ch
.cyberduck
.core
.local
.BrowserLauncherFactory
;
39 import ch
.cyberduck
.core
.preferences
.PreferencesFactory
;
40 import ch
.cyberduck
.ui
.cocoa
.threading
.PanelAlertCallback
;
42 import org
.apache
.commons
.lang3
.StringUtils
;
43 import org
.apache
.log4j
.Logger
;
44 import org
.rococoa
.Foundation
;
45 import org
.rococoa
.ID
;
46 import org
.rococoa
.cocoa
.foundation
.NSPoint
;
48 import java
.util
.Collections
;
49 import java
.util
.HashSet
;
55 public abstract class WindowController
extends BundleController
implements NSWindow
.Delegate
{
56 private static Logger log
= Logger
.getLogger(WindowController
.class);
58 protected static final String DEFAULT
= LocaleFactory
.localizedString("Default");
60 public WindowController() {
65 public void invalidate() {
68 window
.setDelegate(null);
74 * The window this controller is owner of
77 protected NSWindow window
;
79 private Set
<WindowListener
> listeners
80 = Collections
.synchronizedSet(new HashSet
<WindowListener
>());
83 * @param listener Callback on window close
85 public void addListener(final WindowListener listener
) {
86 listeners
.add(listener
);
90 * @param listener Callback on window close
92 public void removeListener(final WindowListener listener
) {
93 listeners
.remove(listener
);
96 public void setWindow(final NSWindow window
) {
98 window
.setReleasedWhenClosed(!this.isSingleton());
99 window
.setDelegate(this.id());
102 public NSWindow
window() {
107 * A singleton window is not released when closed and the controller is not invalidated
109 * @return Always false
111 * @see ch.cyberduck.binding.application.NSWindow#setReleasedWhenClosed(boolean)
113 public boolean isSingleton() {
118 * @return True if the controller window is on screen.
120 public boolean isVisible() {
121 final NSWindow w
= this.window();
125 return w
.isVisible();
129 public void windowDidBecomeKey(final NSNotification notification
) {
134 public void windowDidResignKey(final NSNotification notification
) {
139 public void windowDidBecomeMain(final NSNotification notification
) {
144 public void windowDidResignMain(final NSNotification notification
) {
148 public void windowWillEnterFullScreen(final NSNotification notification
) {
152 public void windowWillExitFullScreen(final NSNotification notification
) {
156 public void windowDidFailToEnterFullScreen(final NSWindow window
) {
157 log
.error("Error entering full screen");
161 * @see ch.cyberduck.binding.application.NSWindow.Delegate
164 public boolean windowShouldClose(final NSWindow sender
) {
169 * Override this method if the controller should not be invalidated after its window closes
172 public void windowWillClose(final NSNotification notification
) {
173 if(log
.isDebugEnabled()) {
174 log
.debug(String
.format("Window will close %s", notification
));
176 for(WindowListener listener
: listeners
.toArray(new WindowListener
[listeners
.size()])) {
177 listener
.windowWillClose();
179 if(!this.isSingleton()) {
180 //If the window is closed it is assumed the controller object is no longer used
186 * Position this controller's window relative to other open windows
188 protected NSPoint
cascade(final NSPoint point
) {
189 return window
.cascadeTopLeftFromPoint(point
);
193 * @param toggle Checkbox
194 * @param select Selected
196 protected void setState(final NSButton toggle
, final boolean select
) {
198 toggle
.performClick(null);
200 toggle
.setState(select ? NSCell
.NSOnState
: NSCell
.NSOffState
);
204 * @return True if this window has a sheet attached
206 public boolean hasSheet() {
210 return window
.attachedSheet() != null;
214 public boolean alert(final Host host
, final BackgroundException failure
,
215 final StringBuilder transcript
) {
216 return new PanelAlertCallback(this).alert(host
, failure
, transcript
);
221 * @return Return code from the dialog if called from background thread.
224 protected int alert(final NSAlert alert
) {
225 return this.alert(alert
, (String
) null);
230 * @param help Help URL
231 * @return Button selection
233 protected int alert(final NSAlert alert
, final String help
) {
234 final int[] response
= new int[1];
235 this.alert(alert
, new SheetCallback() {
237 public void callback(final int returncode
) {
238 response
[0] = returncode
;
245 * Display alert as sheet to the window of this controller
248 * @param callback Dismissed notification
250 protected void alert(final NSAlert alert
, final SheetCallback callback
) {
251 this.alert(alert
, callback
, null);
256 * @param callback Dismissed notification
257 * @param help Help URL
259 protected void alert(final NSAlert alert
, final SheetCallback callback
, final String help
) {
260 final SheetController c
= new AlertController(this, alert
) {
262 public void callback(final int returncode
) {
263 callback
.callback(returncode
);
267 protected void help() {
268 if(StringUtils
.isBlank(help
)) {
272 BrowserLauncherFactory
.get().open(help
);
280 * Attach a sheet to this window
282 * @param sheet The sheet to be attached to this window
283 * @see SheetController#beginSheet()
285 protected void alert(final NSWindow sheet
) {
286 this.alert(sheet
, new SheetCallback() {
288 public void callback(final int returncode
) {
295 * Attach a sheet to this window
297 * @param sheet The sheet to be attached to this window
298 * @param callback The callback to call after the sheet is dismissed
299 * @see SheetController#beginSheet()
301 protected void alert(final NSWindow sheet
, final SheetCallback callback
) {
302 final SheetController c
= new SheetController(this) {
304 public void callback(final int returncode
) {
305 callback
.callback(returncode
);
309 public NSWindow
window() {
316 protected void updateField(final NSTextView f
, final String value
) {
317 f
.setString(StringUtils
.isNotBlank(value
) ? value
: StringUtils
.EMPTY
);
320 protected void updateField(final NSTextField f
, final String value
) {
321 f
.setStringValue(StringUtils
.isNotBlank(value
) ? value
: StringUtils
.EMPTY
);
324 protected void updateField(final NSTextField f
, final String value
, final NSDictionary attributes
) {
325 f
.setAttributedStringValue(NSAttributedString
.attributedStringWithAttributes(StringUtils
.isNotBlank(value
) ? value
: StringUtils
.EMPTY
, attributes
));
330 public void helpButtonClicked(final NSButton sender
) {
331 BrowserLauncherFactory
.get().open(PreferencesFactory
.get().getProperty("website.help"));
334 protected void print(NSView view
) {
335 NSPrintInfo print
= NSPrintInfo
.sharedPrintInfo();
336 print
.setOrientation(NSPrintInfo
.NSPrintingOrientation
.NSLandscapeOrientation
);
337 NSPrintOperation op
= NSPrintOperation
.printOperationWithView_printInfo(view
, print
);
338 op
.setShowsPrintPanel(true);
339 final NSPrintPanel panel
= op
.printPanel();
340 panel
.setOptions(panel
.options() | NSPrintPanel
.NSPrintPanelShowsOrientation
341 | NSPrintPanel
.NSPrintPanelShowsPaperSize
| NSPrintPanel
.NSPrintPanelShowsScaling
);
342 op
.runOperationModalForWindow_delegate_didRunSelector_contextInfo(this.window(), this.id(),
343 Foundation
.selector("printOperationDidRun:success:contextInfo:"), null);
346 public void printOperationDidRun_success_contextInfo(NSPrintOperation op
, boolean success
, ID contextInfo
) {
348 log
.warn(String
.format("Printing failed for context %s", contextInfo
));