Fix transcript in transfer window.
[cyberduck.git] / source / ch / cyberduck / ui / cocoa / WindowController.java
blob498af7fcd2f804d0093419efaddad8d2faa4814a
1 package ch.cyberduck.ui.cocoa;
3 /*
4 * Copyright (c) 2005 David Kocher. All rights reserved.
5 * http://cyberduck.ch/
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.NSApplication;
23 import ch.cyberduck.binding.application.NSButton;
24 import ch.cyberduck.binding.application.NSCell;
25 import ch.cyberduck.binding.application.NSPrintInfo;
26 import ch.cyberduck.binding.application.NSPrintOperation;
27 import ch.cyberduck.binding.application.NSPrintPanel;
28 import ch.cyberduck.binding.application.NSTextField;
29 import ch.cyberduck.binding.application.NSTextView;
30 import ch.cyberduck.binding.application.NSView;
31 import ch.cyberduck.binding.application.NSWindow;
32 import ch.cyberduck.binding.application.SheetCallback;
33 import ch.cyberduck.binding.foundation.NSArray;
34 import ch.cyberduck.binding.foundation.NSAttributedString;
35 import ch.cyberduck.binding.foundation.NSDictionary;
36 import ch.cyberduck.binding.foundation.NSNotification;
37 import ch.cyberduck.core.Host;
38 import ch.cyberduck.core.LocaleFactory;
39 import ch.cyberduck.core.exception.BackgroundException;
40 import ch.cyberduck.core.local.BrowserLauncherFactory;
41 import ch.cyberduck.core.preferences.PreferencesFactory;
42 import ch.cyberduck.ui.cocoa.threading.PanelAlertCallback;
44 import org.apache.commons.lang3.StringUtils;
45 import org.apache.log4j.Logger;
46 import org.rococoa.Foundation;
47 import org.rococoa.ID;
48 import org.rococoa.Rococoa;
49 import org.rococoa.cocoa.foundation.NSPoint;
50 import org.rococoa.cocoa.foundation.NSUInteger;
52 import java.util.Collections;
53 import java.util.HashSet;
54 import java.util.Set;
56 /**
57 * @version $Id$
59 public abstract class WindowController extends BundleController implements NSWindow.Delegate {
60 private static Logger log = Logger.getLogger(WindowController.class);
62 protected static final String DEFAULT = LocaleFactory.localizedString("Default");
64 public WindowController() {
65 super();
68 @Override
69 public void invalidate() {
70 listeners.clear();
71 if(window != null) {
72 window.setDelegate(null);
74 super.invalidate();
77 /**
78 * The window this controller is owner of
80 @Outlet
81 protected NSWindow window;
83 private Set<WindowListener> listeners
84 = Collections.synchronizedSet(new HashSet<WindowListener>());
86 /**
87 * @param listener Callback on window close
89 public void addListener(final WindowListener listener) {
90 listeners.add(listener);
93 /**
94 * @param listener Callback on window close
96 public void removeListener(final WindowListener listener) {
97 listeners.remove(listener);
100 public void setWindow(final NSWindow window) {
101 this.window = window;
102 window.setReleasedWhenClosed(!this.isSingleton());
103 window.setDelegate(this.id());
106 public NSWindow window() {
107 return window;
111 * A singleton window is not released when closed and the controller is not invalidated
113 * @return Always false
114 * @see #invalidate()
115 * @see ch.cyberduck.binding.application.NSWindow#setReleasedWhenClosed(boolean)
117 public boolean isSingleton() {
118 return false;
122 * @return True if the controller window is on screen.
124 public boolean isVisible() {
125 final NSWindow w = this.window();
126 if(null == w) {
127 return false;
129 return w.isVisible();
132 @Override
133 public void windowDidBecomeKey(final NSNotification notification) {
137 @Override
138 public void windowDidResignKey(final NSNotification notification) {
142 @Override
143 public void windowDidBecomeMain(final NSNotification notification) {
147 @Override
148 public void windowDidResignMain(final NSNotification notification) {
152 public void windowWillEnterFullScreen(final NSNotification notification) {
156 public void windowWillExitFullScreen(final NSNotification notification) {
160 public void windowDidFailToEnterFullScreen(final NSWindow window) {
161 log.error("Error entering full screen");
165 * @see ch.cyberduck.binding.application.NSWindow.Delegate
167 @Override
168 public boolean windowShouldClose(final NSWindow sender) {
169 return true;
173 * Override this method if the controller should not be invalidated after its window closes
175 @Override
176 public void windowWillClose(final NSNotification notification) {
177 if(log.isDebugEnabled()) {
178 log.debug(String.format("Window will close %s", notification));
180 for(WindowListener listener : listeners.toArray(new WindowListener[listeners.size()])) {
181 listener.windowWillClose();
183 if(!this.isSingleton()) {
184 //If the window is closed it is assumed the controller object is no longer used
185 this.invalidate();
190 * Position this controller's window relative to other open windows
192 protected void cascade() {
193 NSArray windows = NSApplication.sharedApplication().windows();
194 int count = windows.count().intValue();
195 if(count != 0) {
196 NSWindow w = Rococoa.cast(windows.objectAtIndex(new NSUInteger(count - 1)), NSWindow.class);
197 NSPoint origin = w.frame().origin;
198 origin = new NSPoint(origin.x.doubleValue(), origin.y.doubleValue() + w.frame().size.height.doubleValue());
199 window.setFrameTopLeftPoint(window.cascadeTopLeftFromPoint(origin));
204 * @param toggle Checkbox
205 * @param select Selected
207 protected void setState(final NSButton toggle, final boolean select) {
208 if(select) {
209 toggle.performClick(null);
211 toggle.setState(select ? NSCell.NSOnState : NSCell.NSOffState);
215 * @return True if this window has a sheet attached
217 public boolean hasSheet() {
218 if(null == window) {
219 return false;
221 return window.attachedSheet() != null;
224 @Override
225 public boolean alert(final Host host, final BackgroundException failure,
226 final StringBuilder transcript) {
227 return new PanelAlertCallback(this).alert(host, failure, transcript);
231 * @param alert Sheet
232 * @return Return code from the dialog if called from background thread.
234 @Override
235 protected int alert(final NSAlert alert) {
236 return this.alert(alert, (String) null);
240 * @param alert Sheet
241 * @param help Help URL
242 * @return Button selection
244 protected int alert(final NSAlert alert, final String help) {
245 final int[] response = new int[1];
246 this.alert(alert, new SheetCallback() {
247 @Override
248 public void callback(final int returncode) {
249 response[0] = returncode;
251 }, help);
252 return response[0];
256 * Display alert as sheet to the window of this controller
258 * @param alert Sheet
259 * @param callback Dismissed notification
261 protected void alert(final NSAlert alert, final SheetCallback callback) {
262 this.alert(alert, callback, null);
266 * @param alert Sheet
267 * @param callback Dismissed notification
268 * @param help Help URL
270 protected void alert(final NSAlert alert, final SheetCallback callback, final String help) {
271 final SheetController c = new AlertController(this, alert) {
272 @Override
273 public void callback(final int returncode) {
274 callback.callback(returncode);
277 @Override
278 protected void help() {
279 if(StringUtils.isBlank(help)) {
280 super.help();
282 else {
283 BrowserLauncherFactory.get().open(help);
287 c.beginSheet();
291 * Attach a sheet to this window
293 * @param sheet The sheet to be attached to this window
294 * @see SheetController#beginSheet()
296 protected void alert(final NSWindow sheet) {
297 this.alert(sheet, new SheetCallback() {
298 @Override
299 public void callback(final int returncode) {
306 * Attach a sheet to this window
308 * @param sheet The sheet to be attached to this window
309 * @param callback The callback to call after the sheet is dismissed
310 * @see SheetController#beginSheet()
312 protected void alert(final NSWindow sheet, final SheetCallback callback) {
313 final SheetController c = new SheetController(this) {
314 @Override
315 public void callback(final int returncode) {
316 callback.callback(returncode);
319 @Override
320 public NSWindow window() {
321 return sheet;
324 c.beginSheet();
327 protected void updateField(final NSTextView f, final String value) {
328 f.setString(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY);
331 protected void updateField(final NSTextField f, final String value) {
332 f.setStringValue(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY);
335 protected void updateField(final NSTextField f, final String value, final NSDictionary attributes) {
336 f.setAttributedStringValue(NSAttributedString.attributedStringWithAttributes(StringUtils.isNotBlank(value) ? value : StringUtils.EMPTY, attributes));
340 @Action
341 public void helpButtonClicked(final NSButton sender) {
342 BrowserLauncherFactory.get().open(PreferencesFactory.get().getProperty("website.help"));
345 protected void print(NSView view) {
346 NSPrintInfo print = NSPrintInfo.sharedPrintInfo();
347 print.setOrientation(NSPrintInfo.NSPrintingOrientation.NSLandscapeOrientation);
348 NSPrintOperation op = NSPrintOperation.printOperationWithView_printInfo(view, print);
349 op.setShowsPrintPanel(true);
350 final NSPrintPanel panel = op.printPanel();
351 panel.setOptions(panel.options() | NSPrintPanel.NSPrintPanelShowsOrientation
352 | NSPrintPanel.NSPrintPanelShowsPaperSize | NSPrintPanel.NSPrintPanelShowsScaling);
353 op.runOperationModalForWindow_delegate_didRunSelector_contextInfo(this.window(), this.id(),
354 Foundation.selector("printOperationDidRun:success:contextInfo:"), null);
357 public void printOperationDidRun_success_contextInfo(NSPrintOperation op, boolean success, ID contextInfo) {
358 if(!success) {
359 log.warn(String.format("Printing failed for context %s", contextInfo));