Initial commit of GrowlITTSW. Currently, all settings are hardcoded.
authorJoseph Spiros <joseph.spiros@ithinksw.com>
Sun, 1 Mar 2009 08:10:43 +0000 (03:10 -0500)
committerJoseph Spiros <joseph.spiros@ithinksw.com>
Sun, 1 Mar 2009 08:10:43 +0000 (03:10 -0500)
22 files changed:
.gitignore [new file with mode: 0644]
English.lproj/GrowlITTSWPrefs.nib/classes.nib [new file with mode: 0644]
English.lproj/GrowlITTSWPrefs.nib/info.nib [new file with mode: 0644]
English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib [new file with mode: 0644]
English.lproj/InfoPlist.strings [new file with mode: 0644]
GrowlApplicationNotification.h [new file with mode: 0644]
GrowlDefines.h [new file with mode: 0644]
GrowlDefinesInternal.h [new file with mode: 0644]
GrowlDisplayPlugin.h [new file with mode: 0644]
GrowlITTSW.xcodeproj/TemplateIcon.icns [new file with mode: 0644]
GrowlITTSW.xcodeproj/project.pbxproj [new file with mode: 0644]
GrowlITTSWController.h [new file with mode: 0644]
GrowlITTSWController.m [new file with mode: 0644]
GrowlITTSWDisplay.h [new file with mode: 0644]
GrowlITTSWDisplay.m [new file with mode: 0644]
GrowlITTSWPrefs.h [new file with mode: 0644]
GrowlITTSWPrefs.m [new file with mode: 0644]
GrowlITTSWWindow.h [new file with mode: 0644]
GrowlITTSWWindow.m [new file with mode: 0644]
GrowlITTSW_Prefix.pch [new file with mode: 0644]
GrowlPlugin.h [new file with mode: 0644]
Info.plist [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..ab810ff
--- /dev/null
@@ -0,0 +1,3 @@
+*.pbxuser
+*.mode1v3
+.DS_Store
diff --git a/English.lproj/GrowlITTSWPrefs.nib/classes.nib b/English.lproj/GrowlITTSWPrefs.nib/classes.nib
new file mode 100644 (file)
index 0000000..1f69d3a
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>IBClasses</key>
+       <array>
+               <dict>
+                       <key>CLASS</key>
+                       <string>NSView</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>SUPERCLASS</key>
+                       <string>NSResponder</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>FirstResponder</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>SUPERCLASS</key>
+                       <string>NSObject</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>NSObject</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>NSPreferencePane</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>OUTLETS</key>
+                       <dict>
+                               <key>_firstKeyView</key>
+                               <string>NSView</string>
+                               <key>_initialKeyView</key>
+                               <string>NSView</string>
+                               <key>_lastKeyView</key>
+                               <string>NSView</string>
+                               <key>_window</key>
+                               <string>NSWindow</string>
+                       </dict>
+                       <key>SUPERCLASS</key>
+                       <string>NSObject</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>NSWindow</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>SUPERCLASS</key>
+                       <string>NSResponder</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>GrowlITTSWPrefs</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>OUTLETS</key>
+                       <dict>
+                               <key>slider_opacity</key>
+                               <string>NSSlider</string>
+                       </dict>
+                       <key>SUPERCLASS</key>
+                       <string>NSPreferencePane</string>
+               </dict>
+       </array>
+       <key>IBVersion</key>
+       <string>1</string>
+</dict>
+</plist>
diff --git a/English.lproj/GrowlITTSWPrefs.nib/info.nib b/English.lproj/GrowlITTSWPrefs.nib/info.nib
new file mode 100644 (file)
index 0000000..5155f4a
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>IBFramework Version</key>
+       <string>672</string>
+       <key>IBLastKnownRelativeProjectPath</key>
+       <string>../../../../Growl.xcodeproj</string>
+       <key>IBOldestOS</key>
+       <integer>3</integer>
+       <key>IBOpenObjects</key>
+       <array>
+               <integer>6</integer>
+       </array>
+       <key>IBSystem Version</key>
+       <string>9G55</string>
+       <key>targetFramework</key>
+       <string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib b/English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib
new file mode 100644 (file)
index 0000000..8994fc5
Binary files /dev/null and b/English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib differ
diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings
new file mode 100644 (file)
index 0000000..5e45963
Binary files /dev/null and b/English.lproj/InfoPlist.strings differ
diff --git a/GrowlApplicationNotification.h b/GrowlApplicationNotification.h
new file mode 100644 (file)
index 0000000..2c99ef5
--- /dev/null
@@ -0,0 +1,72 @@
+//
+//     GrowlApplicationNotification.h
+//     Growl
+//
+//     Created by Mac-arena the Bored Zo on 2005-07-31.
+//     Copyright 2005-2006 The Growl Project. All rights reserved.
+//
+
+@interface GrowlApplicationNotification: NSObject
+{
+       NSString *name, *applicationName;
+       NSString *title, *description;
+       NSAttributedString *attributedTitle, *attributedDescription;
+
+       NSDictionary *dictionary, *auxiliaryDictionary;
+
+       unsigned GANReserved: 30;
+}
+
++ (GrowlApplicationNotification *) notificationWithDictionary:(NSDictionary *)dict;
+
+- (GrowlApplicationNotification *) initWithDictionary:(NSDictionary *)dict;
+
+//you can pass nil for description.
+- (GrowlApplicationNotification *) initWithName:(NSString *)newName
+                                applicationName:(NSString *)newAppName
+                                          title:(NSString *)newTitle
+                                    description:(NSString *)newDesc;
+
+//you can pass nil for description.
+- (GrowlApplicationNotification *) initWithName:(NSString *)newName
+                                applicationName:(NSString *)newAppName
+                                          title:(NSString *)newTitle
+                                    description:(NSString *)newDesc;
+
+#pragma mark -
+
+/*as of 0.8, this returns:
+ *     *       GROWL_NOTIFICATION_NAME
+ *     *       GROWL_APP_NAME
+ *     *       GROWL_NOTIFICATION_TITLE
+ *     *       GROWL_NOTIFICATION_DESCRIPTION
+ *you can pass this set to -dictionaryRepresentationWithKeys:.
+ */
++ (NSSet *) standardKeys;
+
+//same as dictionaryRepresentationWithKeys:nil.
+- (NSDictionary *) dictionaryRepresentation;
+
+/*with nil, returns all of the standard keys plus the auxiliary dictionary.
+ *with non-nil, returns only the keys (from internal storage plus the auxiliary
+ *     dictionary) that are in the set.
+ *in other words, returns the intersection of the standard dictionary keys, the
+ *     auxiliary dictionary, and the provided keys.
+ */
+- (NSDictionary *) dictionaryRepresentationWithKeys:(NSSet *)keys;
+
+#pragma mark -
+
+- (NSString *) name;
+- (NSString *) applicationName;
+
+- (NSString *) title;
+- (NSAttributedString *) attributedTitle;
+
+- (NSString *) notificationDescription;
+- (NSAttributedString *) attributedDescription;
+
+- (NSDictionary *) auxiliaryDictionary;
+- (void) setAuxiliaryDictionary:(NSDictionary *)newAuxDict;
+
+@end
diff --git a/GrowlDefines.h b/GrowlDefines.h
new file mode 100644 (file)
index 0000000..2b971cf
--- /dev/null
@@ -0,0 +1,348 @@
+//
+//  GrowlDefines.h
+//
+
+#ifndef _GROWLDEFINES_H
+#define _GROWLDEFINES_H
+
+#ifdef __OBJC__
+#define XSTR(x) (@x)
+#define STRING_TYPE NSString *
+#else
+#define XSTR CFSTR
+#define STRING_TYPE CFStringRef
+#endif
+
+/*!    @header GrowlDefines.h
+ *     @abstract   Defines all the notification keys.
+ *     @discussion Defines all the keys used for registration with Growl and for
+ *      Growl notifications.
+ *
+ *      Most applications should use the functions or methods of Growl.framework
+ *      instead of posting notifications such as those described here.
+ *     @updated 2004-01-25
+ */
+
+// UserInfo Keys for Registration
+#pragma mark UserInfo Keys for Registration
+
+/*!    @group Registration userInfo keys */
+/*     @abstract       Keys for the userInfo dictionary of a GROWL_APP_REGISTRATION distributed notification.
+ *     @discussion The values of these keys describe the application and the
+ *      notifications it may post.
+ *
+ *      Your application must register with Growl before it can post Growl
+ *      notifications (and have them not be ignored). However, as of Growl 0.6,
+ *      posting GROWL_APP_REGISTRATION notifications directly is no longer the
+ *      preferred way to register your application. Your application should instead
+ *      use Growl.framework's delegate system.
+ *      See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for
+ *      more information.
+ */
+
+/*!    @defined GROWL_APP_NAME
+ *     @abstract The name of your application.
+ *     @discussion The name of your application. This should remain stable between
+ *      different versions and incarnations of your application.
+ *      For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and
+ *      "SurfWriter Lite" are not.
+ */
+#define GROWL_APP_NAME                                 XSTR("ApplicationName")
+/*!    @defined GROWL_APP_ID
+ *     @abstract The bundle identifier of your application.
+ *     @discussion The bundle identifier of your application. This key should
+ *   be unique for your application while there may be several applications
+ *   with the same GROWL_APP_NAME.
+ *   This key is optional.
+ */
+#define GROWL_APP_ID                                   XSTR("ApplicationId")
+/*!    @defined GROWL_APP_ICON
+ *     @abstract The image data for your application's icon.
+ *     @discussion Image data representing your application's icon. This may be
+ *      superimposed on a notification icon as a badge, used as the notification
+ *      icon when a notification-specific icon is not supplied, or ignored
+ *      altogether, depending on the display. Must be in a format supported by
+ *      NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_APP_ICON                                 XSTR("ApplicationIcon")
+/*!    @defined GROWL_NOTIFICATIONS_DEFAULT
+ *     @abstract The array of notifications to turn on by default.
+ *     @discussion These are the names of the notifications that should be enabled
+ *      by default when your application registers for the first time. If your
+ *      application reregisters, Growl will look here for any new notification
+ *      names found in GROWL_NOTIFICATIONS_ALL, but ignore any others.
+ */
+#define GROWL_NOTIFICATIONS_DEFAULT            XSTR("DefaultNotifications")
+/*!    @defined GROWL_NOTIFICATIONS_ALL
+ *     @abstract The array of all notifications your application can send.
+ *     @discussion These are the names of all of the notifications that your
+ *      application may post. See GROWL_NOTIFICATION_NAME for a discussion of good
+ *      notification names.
+ */
+#define GROWL_NOTIFICATIONS_ALL                        XSTR("AllNotifications")
+/*! @defined GROWL_NOTIFICATIONS_HUMAN_READABLE_DESCRIPTIONS
+ *  @abstract A dictionary of human-readable names for your notifications.
+ *  @discussion By default, the Growl UI will display notifications by the names given in GROWL_NOTIFICATIONS_ALL
+ *  which correspond to the GROWL_NOTIFICATION_NAME. This dictionary specifies the human-readable name to display.
+ *  The keys of the dictionary are GROWL_NOTIFICATION_NAME strings; the objects are the human-readable versions.
+ *  For any GROWL_NOTIFICATION_NAME not specific in this dictionary, the GROWL_NOTIFICATION_NAME will be displayed.
+ *
+ *  This key is optional.
+ */
+#define GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES               XSTR("HumanReadableNames")
+/*! @defined GROWL_NOTIFICATIONS_DESCRIPTIONS
+*  @abstract A dictionary of descriptions of _when_ each notification occurs
+*  @discussion This is an NSDictionary whose keys are GROWL_NOTIFICATION_NAME strings and whose objects are
+*  descriptions of _when_ each notification occurs, such as "You received a new mail message" or
+*  "A file finished downloading".
+*
+*  This key is optional.
+*/
+#define GROWL_NOTIFICATIONS_DESCRIPTIONS               XSTR("NotificationDescriptions")
+
+/*!    @defined        GROWL_TICKET_VERSION
+ *     @abstract       The version of your registration ticket.
+ *     @discussion     Include this key in a ticket plist file that you put in your
+ *      application bundle for auto-discovery. The current ticket version is 1.
+ */
+#define GROWL_TICKET_VERSION                   XSTR("TicketVersion")
+// UserInfo Keys for Notifications
+#pragma mark UserInfo Keys for Notifications
+
+/*!    @group Notification userInfo keys */
+/*     @abstract       Keys for the userInfo dictionary of a GROWL_NOTIFICATION distributed notification.
+ *     @discussion The values of these keys describe the content of a Growl
+ *      notification.
+ *
+ *      Not all of these keys are supported by all displays. Only the name, title,
+ *      and description of a notification are universal. Most of the built-in
+ *      displays do support all of these keys, and most other visual displays
+ *      probably will also. But, as of 0.6, the Log, MailMe, and Speech displays
+ *      support only textual data.
+ */
+
+/*!    @defined GROWL_NOTIFICATION_NAME
+ *     @abstract The name of the notification.
+ *     @discussion The name of the notification. Note that if you do not define
+ *  GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES when registering your ticket originally this name
+ *  will the one displayed within the Growl preference pane and should be human-readable.
+ */
+#define GROWL_NOTIFICATION_NAME                        XSTR("NotificationName")
+/*!    @defined GROWL_NOTIFICATION_TITLE
+ *     @abstract The title to display in the notification.
+ *     @discussion The title of the notification. Should be very brief.
+ *      The title usually says what happened, e.g. "Download complete".
+ */
+#define GROWL_NOTIFICATION_TITLE               XSTR("NotificationTitle")
+/*!    @defined GROWL_NOTIFICATION_DESCRIPTION
+ *     @abstract The description to display in the notification.
+ *     @discussion The description should be longer and more verbose than the title.
+ *      The description usually tells the subject of the action,
+ *      e.g. "Growl-0.6.dmg downloaded in 5.02 minutes".
+ */
+#define GROWL_NOTIFICATION_DESCRIPTION         XSTR("NotificationDescription")
+/*!    @defined GROWL_NOTIFICATION_ICON
+ *     @discussion Image data for the notification icon. Must be in a format
+ *      supported by NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_ICON                        XSTR("NotificationIcon")
+/*!    @defined GROWL_NOTIFICATION_APP_ICON
+ *     @discussion Image data for the application icon, in case GROWL_APP_ICON does
+ *      not apply for some reason. Must be in a format supported by NSImage, such
+ *      as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_APP_ICON            XSTR("NotificationAppIcon")
+/*!    @defined GROWL_NOTIFICATION_PRIORITY
+ *     @discussion The priority of the notification as an integer number from
+ *      -2 to +2 (+2 being highest).
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_PRIORITY            XSTR("NotificationPriority")
+/*!    @defined GROWL_NOTIFICATION_STICKY
+ *     @discussion A Boolean number controlling whether the notification is sticky.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_STICKY              XSTR("NotificationSticky")
+/*!    @defined GROWL_NOTIFICATION_CLICK_CONTEXT
+ *     @abstract Identifies which notification was clicked.
+ *     @discussion An identifier for the notification for clicking purposes.
+ *
+ *      This will be passed back to the application when the notification is
+ *      clicked. It must be plist-encodable (a data, dictionary, array, number, or
+ *      string object), and it should be unique for each notification you post.
+ *      A good click context would be a UUID string returned by NSProcessInfo or
+ *      CFUUID.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_CLICK_CONTEXT                       XSTR("NotificationClickContext")
+
+/*!    @defined GROWL_DISPLAY_PLUGIN
+ *     @discussion The name of a display plugin which should be used for this notification.
+ *    Optional. If this key is not set or the specified display plugin does not
+ *    exist, the display plugin stored in the application ticket is used. This key
+ *    allows applications to use different default display plugins for their
+ *    notifications. The user can still override those settings in the preference
+ *    pane.
+ */
+#define GROWL_DISPLAY_PLUGIN                           XSTR("NotificationDisplayPlugin")
+
+/*!    @defined GROWL_NOTIFICATION_IDENTIFIER
+ *     @abstract An identifier for the notification for coalescing purposes.
+ *   Notifications with the same identifier fall into the same class; only
+ *   the last notification of a class is displayed on the screen. If a
+ *   notification of the same class is currently being displayed, it is
+ *   replaced by this notification.
+ *
+ *      Optional. Not supported by all display plugins.
+ */
+#define GROWL_NOTIFICATION_IDENTIFIER  XSTR("GrowlNotificationIdentifier")
+
+/*!    @defined GROWL_APP_PID
+ *     @abstract The process identifier of the process which sends this
+ *   notification. If this field is set, the application will only receive
+ *   clicked and timed out notifications which originate from this process.
+ *
+ *      Optional.
+ */
+#define GROWL_APP_PID                                  XSTR("ApplicationPID")
+
+/*!    @defined GROWL_NOTIFICATION_PROGRESS
+*      @abstract If this key is set, it should contain a double value wrapped
+*     in a NSNumber which describes some sort of progress (from 0.0 to 100.0).
+*     If this is key is not set, no progress bar is shown.
+*
+*       Optional. Not supported by all display plugins.
+*/
+#define GROWL_NOTIFICATION_PROGRESS            XSTR("NotificationProgress")
+
+// Notifications
+#pragma mark Notifications
+
+/*!    @group Notification names */
+/*     @abstract       Names of distributed notifications used by Growl.
+ *     @discussion     These are notifications used by applications (directly or
+ *      indirectly) to interact with Growl, and by Growl for interaction between
+ *      its components.
+ *
+ *      Most of these should no longer be used in Growl 0.6 and later, in favor of
+ *      Growl.framework's GrowlApplicationBridge APIs.
+ */
+
+/*!    @defined GROWL_APP_REGISTRATION
+ *     @abstract The distributed notification for registering your application.
+ *     @discussion This is the name of the distributed notification that can be
+ *      used to register applications with Growl.
+ *
+ *      The userInfo dictionary for this notification can contain these keys:
+ *      <ul>
+ *             <li>GROWL_APP_NAME</li>
+ *             <li>GROWL_APP_ICON</li>
+ *             <li>GROWL_NOTIFICATIONS_ALL</li>
+ *             <li>GROWL_NOTIFICATIONS_DEFAULT</li>
+ *      </ul>
+ *
+ *      No longer recommended as of Growl 0.6. An alternate method of registering
+ *      is to use Growl.framework's delegate system.
+ *      See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for
+ *      more information.
+ */
+#define GROWL_APP_REGISTRATION                 XSTR("GrowlApplicationRegistrationNotification")
+/*!    @defined GROWL_APP_REGISTRATION_CONF
+ *     @abstract The distributed notification for confirming registration.
+ *     @discussion The name of the distributed notification sent to confirm the
+ *      registration. Used by the Growl preference pane. Your application probably
+ *      does not need to use this notification.
+ */
+#define GROWL_APP_REGISTRATION_CONF            XSTR("GrowlApplicationRegistrationConfirmationNotification")
+/*!    @defined GROWL_NOTIFICATION
+ *     @abstract The distributed notification for Growl notifications.
+ *     @discussion This is what it all comes down to. This is the name of the
+ *      distributed notification that your application posts to actually send a
+ *      Growl notification.
+ *
+ *      The userInfo dictionary for this notification can contain these keys:
+ *      <ul>
+ *             <li>GROWL_NOTIFICATION_NAME (required)</li>
+ *             <li>GROWL_NOTIFICATION_TITLE (required)</li>
+ *             <li>GROWL_NOTIFICATION_DESCRIPTION (required)</li>
+ *             <li>GROWL_NOTIFICATION_ICON</li>
+ *             <li>GROWL_NOTIFICATION_APP_ICON</li>
+ *             <li>GROWL_NOTIFICATION_PRIORITY</li>
+ *             <li>GROWL_NOTIFICATION_STICKY</li>
+ *             <li>GROWL_NOTIFICATION_CLICK_CONTEXT</li>
+ *             <li>GROWL_APP_NAME (required)</li>
+ *      </ul>
+ *
+ *      No longer recommended as of Growl 0.6. Three alternate methods of posting
+ *      notifications are +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:],
+ *      Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext, and
+ *      Growl_PostNotification.
+ */
+#define GROWL_NOTIFICATION                             XSTR("GrowlNotification")
+/*!    @defined GROWL_SHUTDOWN
+*      @abstract The distributed notification name that tells Growl to shutdown.
+*      @discussion The Growl preference pane posts this notification when the
+*       "Stop Growl" button is clicked.
+*/
+#define GROWL_SHUTDOWN                                 XSTR("GrowlShutdown")
+/*!    @defined GROWL_PING
+ *     @abstract A distributed notification to check whether Growl is running.
+ *     @discussion This is used by the Growl preference pane. If it receives a
+ *      GROWL_PONG, the preference pane takes this to mean that Growl is running.
+ */
+#define GROWL_PING                                             XSTR("Honey, Mind Taking Out The Trash")
+/*!    @defined GROWL_PONG
+ *     @abstract The distributed notification sent in reply to GROWL_PING.
+ *     @discussion GrowlHelperApp posts this in reply to GROWL_PING.
+ */
+#define GROWL_PONG                                             XSTR("What Do You Want From Me, Woman")
+/*!    @defined GROWL_IS_READY
+ *     @abstract The distributed notification sent when Growl starts up.
+ *     @discussion GrowlHelperApp posts this when it has begin listening on all of
+ *      its sources for new notifications. GrowlApplicationBridge (in
+ *      Growl.framework), upon receiving this notification, reregisters using the
+ *      registration dictionary supplied by its delegate.
+ */
+#define GROWL_IS_READY                                 XSTR("Lend Me Some Sugar; I Am Your Neighbor!")
+/*!    @defined GROWL_NOTIFICATION_CLICKED
+ *     @abstract The distributed notification sent when a supported notification is clicked.
+ *     @discussion When a Growl notification with a click context is clicked on by
+ *      the user, Growl posts this distributed notification.
+ *      The GrowlApplicationBridge responds to this notification by calling a
+ *      callback in its delegate.
+ */
+#define GROWL_NOTIFICATION_CLICKED             XSTR("GrowlClicked!")
+#define GROWL_NOTIFICATION_TIMED_OUT   XSTR("GrowlTimedOut!")
+
+/*!    @group Other symbols */
+/* Symbols which don't fit into any of the other categories. */
+
+/*!    @defined GROWL_KEY_CLICKED_CONTEXT
+ *     @abstract Used internally as the key for the clickedContext passed over DNC.
+ *     @discussion This key is used in GROWL_NOTIFICATION_CLICKED, and contains the
+ *      click context that was supplied in the original notification.
+ */
+#define GROWL_KEY_CLICKED_CONTEXT              XSTR("ClickedContext")
+/*!    @defined GROWL_REG_DICT_EXTENSION
+ *     @abstract The filename extension for registration dictionaries.
+ *     @discussion The GrowlApplicationBridge in Growl.framework registers with
+ *      Growl by creating a file with the extension of .(GROWL_REG_DICT_EXTENSION)
+ *      and opening it in the GrowlHelperApp. This happens whether or not Growl is
+ *      running; if it was stopped, it quits immediately without listening for
+ *      notifications.
+ */
+#define GROWL_REG_DICT_EXTENSION               XSTR("growlRegDict")
+
+
+#define GROWL_POSITION_PREFERENCE_KEY                  @"GrowlSelectedPosition"
+
+#endif //ndef _GROWLDEFINES_H
diff --git a/GrowlDefinesInternal.h b/GrowlDefinesInternal.h
new file mode 100644 (file)
index 0000000..14067e3
--- /dev/null
@@ -0,0 +1,430 @@
+//
+//  GrowlDefinesInternal.h
+//  Growl
+//
+//  Created by Karl Adam on Mon May 17 2004.
+//  Copyright (c) 2004 the Growl Project. All rights reserved.
+//
+
+#ifndef _GROWL_GROWLDEFINESINTERNAL_H
+#define _GROWL_GROWLDEFINESINTERNAL_H
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef __OBJC__
+#define XSTR(x) (@x)
+#else /* !__OBJC__ */
+#define XSTR CFSTR
+#endif /* __OBJC__ */
+
+/*!    @header GrowlDefinesInternal.h
+ *     @abstract       Defines internal Growl macros and types.
+ *  @ignore ATTRIBUTE_PACKED
+ *     @discussion     These constants are used both by GrowlHelperApp and by plug-ins.
+ *
+ *      Notification keys (used in GrowlHelperApp, in GrowlApplicationBridge, and
+ *      by applications that don't use GrowlApplicationBridge) are defined in
+ *      GrowlDefines.h.
+ */
+
+/*!    @defined        GROWL_TCP_PORT
+ *     @abstract       The TCP listen port for Growl notification servers.
+ */
+#define GROWL_TCP_PORT 23052
+
+/*!    @defined        GROWL_UDP_PORT
+ *     @abstract       The UDP listen port for Growl notification servers.
+ */
+#define GROWL_UDP_PORT 9887
+
+/*!    @defined        GROWL_PROTOCOL_VERSION
+ *     @abstract       The current version of the Growl network-notifications protocol (without encryption).
+ */
+#define GROWL_PROTOCOL_VERSION 1
+
+/*!    @defined        GROWL_PROTOCOL_VERSION_AES128
+*      @abstract       The current version of the Growl network-notifications protocol (with AES-128 encryption).
+*/
+#define GROWL_PROTOCOL_VERSION_AES128  2
+
+/*!    @defined        GROWL_TYPE_REGISTRATION
+ *     @abstract       The packet type of registration packets with MD5 authentication.
+ */
+#define GROWL_TYPE_REGISTRATION                        0
+/*!    @defined        GROWL_TYPE_NOTIFICATION
+ *     @abstract       The packet type of notification packets with MD5 authentication.
+ */
+#define GROWL_TYPE_NOTIFICATION                        1
+/*!    @defined        GROWL_TYPE_REGISTRATION_SHA256
+ *     @abstract       The packet type of registration packets with SHA-256 authentication.
+ */
+#define GROWL_TYPE_REGISTRATION_SHA256 2
+/*!    @defined        GROWL_TYPE_NOTIFICATION_SHA256
+ *     @abstract       The packet type of notification packets with SHA-256 authentication.
+ */
+#define GROWL_TYPE_NOTIFICATION_SHA256 3
+/*!    @defined        GROWL_TYPE_REGISTRATION_NOAUTH
+*      @abstract       The packet type of registration packets without authentication.
+*/
+#define GROWL_TYPE_REGISTRATION_NOAUTH 4
+/*!    @defined        GROWL_TYPE_NOTIFICATION_NOAUTH
+*      @abstract       The packet type of notification packets without authentication.
+*/
+#define GROWL_TYPE_NOTIFICATION_NOAUTH 5
+
+#define ATTRIBUTE_PACKED __attribute((packed))
+
+/*!    @struct GrowlNetworkPacket
+ *     @abstract       This struct is a header common to all incoming Growl network
+ *      packets which identifies the type and version of the packet.
+ */
+struct GrowlNetworkPacket {
+       unsigned char version;
+       unsigned char type;
+} ATTRIBUTE_PACKED;
+
+/*!
+ * @struct GrowlNetworkRegistration
+ * @abstract The format of a registration packet.
+ * @discussion A Growl client that wants to register with a Growl server sends
+ * a packet in this format.
+ * @field common The Growl packet header.
+ * @field appNameLen The name of the application that is registering.
+ * @field numAllNotifications The number of notifications in the list.
+ * @field numDefaultNotifications The number of notifications in the list that are enabled by default.
+ * @field data Variable-sized data.
+ */
+struct GrowlNetworkRegistration {
+       struct GrowlNetworkPacket common;
+       /*      This name is used both internally and in the Growl
+        *       preferences.
+        *
+        *       The application name should remain stable between different versions
+        *       and incarnations of your application.
+        *       For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0"
+        *       and "SurfWriter Lite" are not.
+        *
+        *       In addition to being unsigned, the application name length is in
+        *       network byte order.
+        */
+       unsigned short appNameLen;
+       /*      These names are used both internally and in the Growl
+        *       preferences. For this reason, they should be human-readable.
+        */
+       unsigned char numAllNotifications;
+
+       unsigned char numDefaultNotifications;
+       /*      The variable-sized data of a registration is:
+        *       - The application name, in UTF-8 encoding, for appNameLen bytes.
+        *       - The list of all notification names.
+        *       - The list of default notifications, as 8-bit unsigned indices into the list of all notifications.
+        *       - The MD5/SHA256 checksum of all the data preceding the checksum.
+        *
+        *       Each notification name is encoded as:
+        *       - Length: two bytes, unsigned, network byte order.
+        *       - Name: As many bytes of UTF-8-encoded text as the length says.
+        *       And there are numAllNotifications of these.
+        */
+       unsigned char data[];
+} ATTRIBUTE_PACKED;
+
+/*!
+ * @struct GrowlNetworkNotification
+ * @abstract The format of a notification packet.
+ * @discussion A Growl client that wants to post a notification to a Growl
+ * server sends a packet in this format.
+ * @field common The Growl packet header.
+ * @field flags The priority number and the sticky bit.
+ * @field nameLen The length of the notification name.
+ * @field titleLen The length of the notification title.
+ * @field descriptionLen The length of the notification description.
+ * @field appNameLen The length of the application name.
+ * @field data Variable-sized data.
+ */
+struct GrowlNetworkNotification {
+       struct GrowlNetworkPacket common;
+       /*!
+        * @struct GrowlNetworkNotificationFlags
+        * @abstract Various flags.
+        * @discussion This 16-bit packed structure contains the priority as a
+        *  signed 3-bit integer from -2 to +2, and the sticky flag as a single bit.
+        *  The high 12 bits of the structure are reserved for future use.
+        * @field reserved reserved for future use.
+        * @field priority the priority as a signed 3-bit integer from -2 to +2.
+        * @field sticky the sticky flag.
+        */
+       struct GrowlNetworkNotificationFlags {
+#ifdef __BIG_ENDIAN__
+               unsigned reserved: 12;
+               signed   priority: 3;
+               unsigned sticky:   1;
+#else
+               unsigned sticky:   1;
+               signed   priority: 3;
+               unsigned reserved: 12;
+#endif
+       } ATTRIBUTE_PACKED flags; //size = 16 (12 + 3 + 1)
+
+       /*      In addition to being unsigned, the notification name length
+        *       is in network byte order.
+        */
+       unsigned short nameLen;
+       /*      @discussion     In addition to being unsigned, the title length is in
+        *       network byte order.
+        */
+       unsigned short titleLen;
+       /*      In addition to being unsigned, the description length is in
+        *       network byte order.
+        */
+       unsigned short descriptionLen;
+       /*      In addition to being unsigned, the application name length
+        *       is in network byte order.
+        */
+       unsigned short appNameLen;
+       /*      The variable-sized data of a notification is:
+        *       - Notification name, in UTF-8 encoding, for nameLen bytes.
+        *       - Title, in UTF-8 encoding, for titleLen bytes.
+        *       - Description, in UTF-8 encoding, for descriptionLen bytes.
+        *       - Application name, in UTF-8 encoding, for appNameLen bytes.
+        *       - The MD5/SHA256 checksum of all the data preceding the checksum.
+        */
+       unsigned char data[];
+} ATTRIBUTE_PACKED;
+
+/*!    @defined        GrowlEnabledKey
+ *     @abstract       Preference key controlling whether Growl is enabled.
+ *     @discussion     If this is false, then when GrowlHelperApp is launched to open
+ *      a Growl registration dictionary file, GrowlHelperApp will quit when it has
+ *      finished processing the file instead of listening for notifications.
+ */
+#define GrowlEnabledKey                                        XSTR("GrowlEnabled")
+
+/*!    @defined        GROWL_SCREENSHOT_MODE
+ *     @abstract       Preference and notification key controlling whether to save a screenshot of the notification.
+ *     @discussion     This is for GHA's private usage. If your application puts this
+ *      key into a notification dictionary, GHA will clobber it. This key is only
+ *      allowed in the notification dictionaries GHA passes to displays.
+ *
+ *      If this key contains an object whose boolValue is not NO, the display is
+ *      asked to save a screenshot of the notification to
+ *      ~/Library/Application\ Support/Growl/Screenshots.
+ */
+#define GROWL_SCREENSHOT_MODE                  XSTR("ScreenshotMode")
+
+/*!    @defined        GROWL_APP_LOCATION
+ *     @abstract       The location of this application.
+ *     @discussion     Contains either the POSIX path to the application, or a file-data dictionary (as used by the Dock).
+ *      contains the file's alias record and its pathname.
+ */
+#define GROWL_APP_LOCATION                             XSTR("AppLocation")
+
+/*!    @defined        GROWL_REMOTE_ADDRESS
+ *     @abstract       The address of the host who sent this notification/registration.
+ *     @discussion     Contains an NSData with the address of the remote host who
+ *    sent this notification/registration.
+ */
+#define GROWL_REMOTE_ADDRESS                   XSTR("RemoteAddress")
+
+/*!
+ *     @defined    GROWL_PREFPANE_BUNDLE_IDENTIFIER
+ *     @discussion The bundle identifier for the Growl preference pane.
+ */
+#define GROWL_PREFPANE_BUNDLE_IDENTIFIER               XSTR("com.growl.prefpanel")
+/*!
+ *     @defined    GROWL_HELPERAPP_BUNDLE_IDENTIFIER
+ *     @discussion The bundle identifier for the Growl background application (GrowlHelperApp).
+ */
+#define GROWL_HELPERAPP_BUNDLE_IDENTIFIER      XSTR("com.Growl.GrowlHelperApp")
+
+/*!
+ *     @defined    GROWL_PREFPANE_NAME
+ *     @discussion The file name of the Growl preference pane.
+ */
+#define GROWL_PREFPANE_NAME                                            XSTR("Growl.prefPane")
+#define PREFERENCE_PANES_SUBFOLDER_OF_LIBRARY  XSTR("PreferencePanes")
+#define PREFERENCE_PANE_EXTENSION                              XSTR("prefPane")
+
+//plug-in bundle filename extensions
+#define GROWL_PLUGIN_EXTENSION                  XSTR("growlPlugin")
+#define GROWL_PATHWAY_EXTENSION                 XSTR("growlPathway")
+#define GROWL_VIEW_EXTENSION                                   XSTR("growlView")
+#define GROWL_STYLE_EXTENSION                                  XSTR("growlStyle")
+
+/* --- These following macros are intended for plug-ins --- */
+
+/*!    @function    SYNCHRONIZE_GROWL_PREFS
+ *     @abstract    Synchronizes Growl prefs so they're up-to-date.
+ *     @discussion  This macro is intended for use by GrowlHelperApp and by
+ *      plug-ins (when the prefpane is selected).
+ */
+#define SYNCHRONIZE_GROWL_PREFS() CFPreferencesAppSynchronize(CFSTR("com.Growl.GrowlHelperApp"))
+
+/*!    @function    UPDATE_GROWL_PREFS
+ *     @abstract    Tells GrowlHelperApp to update its prefs.
+ *     @discussion  This macro is intended for use by plug-ins.
+ *      It sends a notification to tell GrowlHelperApp to update its preferences.
+ */
+#define UPDATE_GROWL_PREFS() do { \
+       SYNCHRONIZE_GROWL_PREFS(); \
+       CFStringRef _key = CFSTR("pid"); \
+       int pid = getpid(); \
+       CFNumberRef _value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); \
+       CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&_key, (const void **)&_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); \
+       CFRelease(_value); \
+       CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), \
+                                                                                CFSTR("GrowlPreferencesChanged"), \
+                                                                                CFSTR("GrowlUserDefaults"), \
+                                                                                userInfo, false); \
+       CFRelease(userInfo); \
+       } while(0)
+
+/*!    @function    READ_GROWL_PREF_VALUE
+ *     @abstract    Reads the given pref value from the plug-in's preferences.
+ *     @discussion  This macro is intended for use by plug-ins. It reads the value for the
+ *      given key from the plug-in's preferences (which are stored in a dictionary inside of
+ *      GrowlHelperApp's prefs).
+ *     @param  key     The preference key to read the value of.
+ *     @param  domain  The bundle ID of the plug-in.
+ *     @param  type    The type of the result expected.
+ *     @param  result  A pointer to an id. Set to the value if exists, left unchanged if not.
+ *
+ *      If the value is set, you are responsible for releasing it.
+ */
+#define READ_GROWL_PREF_VALUE(key, domain, type, result) do {\
+       CFDictionaryRef prefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
+                                                                                                                                               CFSTR("com.Growl.GrowlHelperApp")); \
+       if (prefs) {\
+               if (CFDictionaryContainsKey(prefs, key)) {\
+                       *result = (type)CFDictionaryGetValue(prefs, key); \
+                       CFRetain(*result); \
+               } \
+               CFRelease(prefs); } \
+       } while(0)
+
+/*!    @function    WRITE_GROWL_PREF_VALUE
+ *     @abstract    Writes the given pref value to the plug-in's preferences.
+ *     @discussion  This macro is intended for use by plug-ins. It writes the given
+ *      value to the plug-in's preferences.
+ *     @param  key     The preference key to write the value of.
+ *     @param  value   The value to write to the preferences. It should be either a
+ *      CoreFoundation type or toll-free bridged with one.
+ *     @param  domain  The bundle ID of the plug-in.
+ */
+#define WRITE_GROWL_PREF_VALUE(key, value, domain) do {\
+       CFDictionaryRef staticPrefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
+                                                                                                                                                        CFSTR("com.Growl.GrowlHelperApp")); \
+       CFMutableDictionaryRef prefs; \
+       if (staticPrefs == NULL) {\
+               prefs = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); \
+       } else {\
+               prefs = CFDictionaryCreateMutableCopy(NULL, 0, staticPrefs); \
+               CFRelease(staticPrefs); \
+       }\
+       CFDictionarySetValue(prefs, key, value); \
+       CFPreferencesSetAppValue((CFStringRef)domain, prefs, CFSTR("com.Growl.GrowlHelperApp")); \
+       CFRelease(prefs); } while(0)
+
+/*!    @function    READ_GROWL_PREF_BOOL
+ *     @abstract    Reads the given Boolean from the plug-in's preferences.
+ *     @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
+ *      use with Booleans.
+ *     @param  key     The preference key to read the Boolean from.
+ *     @param  domain  The bundle ID of the plug-in.
+ *     @param  result  A pointer to a Boolean type. Left unchanged if the value doesn't exist.
+ */
+#define READ_GROWL_PREF_BOOL(key, domain, result) do {\
+       CFBooleanRef boolValue = NULL; \
+       READ_GROWL_PREF_VALUE(key, domain, CFBooleanRef, &boolValue); \
+       if (boolValue) {\
+               *result = CFBooleanGetValue(boolValue); \
+               CFRelease(boolValue); \
+       } } while(0)
+
+/*!    @function    WRITE_GROWL_PREF_BOOL
+ *     @abstract    Writes the given Boolean to the plug-in's preferences.
+ *     @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
+ *      use with Booleans.
+ *     @param  key     The preference key to write the Boolean for.
+ *     @param  value   The Boolean value to write to the preferences.
+ *     @param  domain  The bundle ID of the plug-in.
+ */
+#define WRITE_GROWL_PREF_BOOL(key, value, domain) do {\
+       WRITE_GROWL_PREF_VALUE(key, value ? kCFBooleanTrue : kCFBooleanFalse, domain); } while(0)
+
+/*!    @function    READ_GROWL_PREF_INT
+ *     @abstract    Reads the given integer from the plug-in's preferences.
+ *     @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
+ *      use with integers.
+ *     @param  key     The preference key to read the integer from.
+ *     @param  domain  The bundle ID of the plug-in.
+ *     @param  result  A pointer to an integer. Leaves unchanged if the value doesn't exist.
+ */
+#define READ_GROWL_PREF_INT(key, domain, result) do {\
+       CFNumberRef intValue = NULL; \
+       READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &intValue); \
+       if (intValue) {\
+               CFNumberGetValue(intValue, kCFNumberIntType, result); \
+               CFRelease(intValue); \
+       } } while(0)
+
+/*!    @function    WRITE_GROWL_PREF_INT
+ *     @abstract    Writes the given integer to the plug-in's preferences.
+ *     @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
+ *      use with integers.
+ *     @param  key     The preference key to write the integer for.
+ *     @param  value   The integer value to write to the preferences.
+ *     @param  domain  The bundle ID of the plug-in.
+ */
+#define WRITE_GROWL_PREF_INT(key, value, domain) do {\
+       CFNumberRef intValue = CFNumberCreate(NULL, kCFNumberIntType, &value); \
+       WRITE_GROWL_PREF_VALUE(key, intValue, domain); \
+       CFRelease(intValue); } while(0)
+
+/*!    @function    READ_GROWL_PREF_FLOAT
+ *     @abstract    Reads the given float from the plug-in's preferences.
+ *     @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
+ *      use with floats.
+ *     @param  key     The preference key to read the float from.
+ *     @param  domain  The bundle ID of the plug-in.
+ *     @param  result  A pointer to a float. Leaves unchanged if the value doesn't exist.
+ */
+#define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
+       CFNumberRef floatValue = NULL; \
+       READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
+       if (floatValue) {\
+               CFNumberGetValue(floatValue, kCFNumberFloatType, result); \
+               CFRelease(floatValue); \
+       } } while(0)
+
+/*!    @function    WRITE_GROWL_PREF_FLOAT
+ *     @abstract    Writes the given float to the plug-in's preferences.
+ *     @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
+ *      use with floats.
+ *     @param  key     The preference key to write the float for.
+ *     @param  value   The float value to write to the preferences.
+ *     @param  domain  The bundle ID of the plug-in.
+ */
+#define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
+       CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberFloatType, &value); \
+       WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
+       CFRelease(floatValue); } while(0)
+
+
+/*!    @defined        GROWL_CLOSE_ALL_NOTIFICATIONS
+ *     @abstract       Notification to close all Growl notifications
+ *     @discussion     Should be posted to the default notification center when a close widget is option+clicked.
+ *    All notifications should close in response. 
+ */
+#define GROWL_CLOSE_ALL_NOTIFICATIONS XSTR("GrowlCloseAllNotifications")
+
+#pragma mark Small utilities
+
+/*!
+ * @defined FLOAT_EQ(x,y)
+ * @abstract Compares two floats.
+ */
+#define FLOAT_EQ(x,y) (((y - FLT_EPSILON) < x) && (x < (y + FLT_EPSILON)))
+
+#endif //ndef _GROWL_GROWLDEFINESINTERNAL_H
diff --git a/GrowlDisplayPlugin.h b/GrowlDisplayPlugin.h
new file mode 100644 (file)
index 0000000..1cb30c3
--- /dev/null
@@ -0,0 +1,75 @@
+//
+//     GrowlDisplayPlugin.h
+//     Growl
+//
+//     Created by Mac-arena the Bored Zo on 2005-06-01.
+//     Copyright 2005-2006 The Growl Project. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "GrowlPlugin.h"
+
+@class GrowlApplicationNotification, GrowlNotificationDisplayBridge;
+@class GrowlDisplayWindowController;
+
+//Info.plist keys for plug-in bundles.
+extern NSString *GrowlDisplayPluginInfoKeyUsesQueue;
+extern NSString *GrowlDisplayPluginInfoKeyWindowNibName;
+
+/*!
+ * @class GrowlDisplayPlugin
+ * @abstract Base class for all display plugins.
+ */
+@interface GrowlDisplayPlugin : GrowlPlugin {
+       Class          windowControllerClass;
+       
+       //for all displays
+       NSMutableDictionary *coalescableBridges;
+       
+       //for non-queueing displays
+       NSMutableArray *activeBridges; //GrowlNotificationDisplayBridges currently being displayed
+
+       //for queueing displays
+       GrowlNotificationDisplayBridge *bridge;
+       NSMutableArray *queue;           //GrowlNotificationDisplayBridges yet to be displayed
+}
+
+/*!    @method displayNotification:
+ *     @abstract       Display a notification to the user.
+ *     @param  notification    The notification to display.
+ *  @discussion Unless you have a specific reason to override this method you should not do so.
+ *  All the magic should happen in <code>configureBridge:</code>
+ */
+- (void) displayNotification:(GrowlApplicationNotification *)notification;
+
+/*!    @method configureBridge:
+ *     @abstract       Configures the chosen bridge before a notificaion is displayed.
+ *     @param  bridge  The bridge to configure.
+ *  @discussion This is the place where the magic happens.  Override this method and do any
+ *  specific configuration here.  This is the last port-of-call before a notification is displayed.
+ *  The default implementation does nothing so it is important that you override and provide an
+ *  implementation.
+ */
+- (void) configureBridge:(GrowlNotificationDisplayBridge *)theBridge;
+
+/*!    @method windowNibName
+ *     @abstract       Returns the name of the display's sole nib file (resulting in
+ *      the creation of a window controller for the window in that file).
+ *     @discussion     When subclassing <code>GrowlDisplayPlugin</code>, override this
+ *      method and return the name of the nib (without the ".nib" extension) that
+ *      contains the display window. This method is called by
+ *      <code>displayNotification:</code> to create a
+ *      <code>GrowlNotificationDisplayBridge</code>, which is the File's Owner for
+ *      the nib.
+ *
+ *      The default implementation returns the value of
+ *      <code>GrowlDisplayWindowNibName</code> in the Info.plist of the bundle for
+ *      the display plug-in.
+ *     @result The name of the window nib.
+ */
+- (NSString *) windowNibName;
+
+/* */
+- (void) displayWindowControllerDidTakeDownWindow:(GrowlDisplayWindowController *)wc;
+
+@end
diff --git a/GrowlITTSW.xcodeproj/TemplateIcon.icns b/GrowlITTSW.xcodeproj/TemplateIcon.icns
new file mode 100644 (file)
index 0000000..62cb701
Binary files /dev/null and b/GrowlITTSW.xcodeproj/TemplateIcon.icns differ
diff --git a/GrowlITTSW.xcodeproj/project.pbxproj b/GrowlITTSW.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..479620c
--- /dev/null
@@ -0,0 +1,468 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 45;
+       objects = {
+
+/* Begin PBXBuildFile section */
+               8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
+               8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+               FA4A47250F5A3C2A00F37A2B /* GrowlITTSWDisplay.m in Sources */ = {isa = PBXBuildFile; fileRef = FA4A471E0F5A3C2A00F37A2B /* GrowlITTSWDisplay.m */; };
+               FA4A47270F5A3C2A00F37A2B /* GrowlITTSWController.m in Sources */ = {isa = PBXBuildFile; fileRef = FA4A47220F5A3C2A00F37A2B /* GrowlITTSWController.m */; };
+               FA4A47280F5A3C2A00F37A2B /* GrowlITTSWWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = FA4A47240F5A3C2A00F37A2B /* GrowlITTSWWindow.m */; };
+               FA4A47400F5A3C7100F37A2B /* ITKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA4A473D0F5A3C6900F37A2B /* ITKit.framework */; };
+               FA4A47410F5A3C7300F37A2B /* ITFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA4A47340F5A3C5900F37A2B /* ITFoundation.framework */; };
+               FA4A47510F5A3CFC00F37A2B /* GrowlITTSWPrefs.nib in Resources */ = {isa = PBXBuildFile; fileRef = FA4A474F0F5A3CFC00F37A2B /* GrowlITTSWPrefs.nib */; };
+               FA5074430F5A56DA008DEAD9 /* ITFoundation.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = FA4A47340F5A3C5900F37A2B /* ITFoundation.framework */; };
+               FA5074440F5A56DD008DEAD9 /* ITKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = FA4A473D0F5A3C6900F37A2B /* ITKit.framework */; };
+               FA50774D0F5A7A2D008DEAD9 /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA50774C0F5A7A2D008DEAD9 /* PreferencePanes.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+               FA4A47330F5A3C5900F37A2B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FA4A472F0F5A3C5900F37A2B /* ITFoundation.xcodeproj */;
+                       proxyType = 2;
+                       remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
+                       remoteInfo = ITFoundation;
+               };
+               FA4A473C0F5A3C6900F37A2B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */;
+                       proxyType = 2;
+                       remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
+                       remoteInfo = ITKit;
+               };
+               FA4A473E0F5A3C6900F37A2B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */;
+                       proxyType = 2;
+                       remoteGlobalIDString = 7C992F87054F5389000B93EA;
+                       remoteInfo = ITKitShowcase;
+               };
+               FA4A47490F5A3CD300F37A2B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FA4A472F0F5A3C5900F37A2B /* ITFoundation.xcodeproj */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+                       remoteInfo = ITFoundation;
+               };
+               FA4A474B0F5A3CD500F37A2B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+                       remoteInfo = ITKit;
+               };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+               FA50745D0F5A570F008DEAD9 /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = "";
+                       dstSubfolderSpec = 10;
+                       files = (
+                               FA5074430F5A56DA008DEAD9 /* ITFoundation.framework in CopyFiles */,
+                               FA5074440F5A56DD008DEAD9 /* ITKit.framework in CopyFiles */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+               089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+               089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+               089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+               1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+               32DBCF630370AF2F00C91783 /* GrowlITTSW_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlITTSW_Prefix.pch; sourceTree = "<group>"; };
+               8D5B49B6048680CD000E48DA /* GrowlITTSW.growlView */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GrowlITTSW.growlView; sourceTree = BUILT_PRODUCTS_DIR; };
+               8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+               D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+               FA4A471D0F5A3C2A00F37A2B /* GrowlITTSWDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlITTSWDisplay.h; sourceTree = "<group>"; };
+               FA4A471E0F5A3C2A00F37A2B /* GrowlITTSWDisplay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GrowlITTSWDisplay.m; sourceTree = "<group>"; };
+               FA4A471F0F5A3C2A00F37A2B /* GrowlITTSWPrefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlITTSWPrefs.h; sourceTree = "<group>"; };
+               FA4A47200F5A3C2A00F37A2B /* GrowlITTSWPrefs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GrowlITTSWPrefs.m; sourceTree = "<group>"; };
+               FA4A47210F5A3C2A00F37A2B /* GrowlITTSWController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlITTSWController.h; sourceTree = "<group>"; };
+               FA4A47220F5A3C2A00F37A2B /* GrowlITTSWController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GrowlITTSWController.m; sourceTree = "<group>"; };
+               FA4A47230F5A3C2A00F37A2B /* GrowlITTSWWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlITTSWWindow.h; sourceTree = "<group>"; };
+               FA4A47240F5A3C2A00F37A2B /* GrowlITTSWWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GrowlITTSWWindow.m; sourceTree = "<group>"; };
+               FA4A472B0F5A3C3100F37A2B /* GrowlPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlPlugin.h; sourceTree = "<group>"; };
+               FA4A472C0F5A3C3100F37A2B /* GrowlDisplayPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlDisplayPlugin.h; sourceTree = "<group>"; };
+               FA4A472F0F5A3C5900F37A2B /* ITFoundation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ITFoundation.xcodeproj; path = ../ITFoundation/ITFoundation.xcodeproj; sourceTree = SOURCE_ROOT; };
+               FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ITKit.xcodeproj; path = ../ITKit/ITKit.xcodeproj; sourceTree = SOURCE_ROOT; };
+               FA4A47500F5A3CFC00F37A2B /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/GrowlITTSWPrefs.nib; sourceTree = "<group>"; };
+               FA50739B0F5A4D74008DEAD9 /* GrowlDefinesInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlDefinesInternal.h; sourceTree = "<group>"; };
+               FA5073AA0F5A4D9A008DEAD9 /* GrowlApplicationNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlApplicationNotification.h; sourceTree = "<group>"; };
+               FA5074060F5A5562008DEAD9 /* GrowlDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowlDefines.h; sourceTree = "<group>"; };
+               FA50774C0F5A7A2D008DEAD9 /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               8D5B49B3048680CD000E48DA /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */,
+                               FA4A47400F5A3C7100F37A2B /* ITKit.framework in Frameworks */,
+                               FA4A47410F5A3C7300F37A2B /* ITFoundation.framework in Frameworks */,
+                               FA50774D0F5A7A2D008DEAD9 /* PreferencePanes.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               089C166AFE841209C02AAC07 /* GrowlITTSW */ = {
+                       isa = PBXGroup;
+                       children = (
+                               08FB77AFFE84173DC02AAC07 /* Classes */,
+                               32C88E010371C26100C91783 /* Other Sources */,
+                               089C167CFE841241C02AAC07 /* Resources */,
+                               089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
+                               19C28FB8FE9D52D311CA2CBB /* Products */,
+                       );
+                       name = GrowlITTSW;
+                       sourceTree = "<group>";
+               };
+               089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA4A472F0F5A3C5900F37A2B /* ITFoundation.xcodeproj */,
+                               FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */,
+                               1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */,
+                               1058C7AEFEA557BF11CA2CBB /* Other Frameworks */,
+                       );
+                       name = "Frameworks and Libraries";
+                       sourceTree = "<group>";
+               };
+               089C167CFE841241C02AAC07 /* Resources */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA4A474F0F5A3CFC00F37A2B /* GrowlITTSWPrefs.nib */,
+                               8D5B49B7048680CD000E48DA /* Info.plist */,
+                               089C167DFE841241C02AAC07 /* InfoPlist.strings */,
+                       );
+                       name = Resources;
+                       sourceTree = "<group>";
+               };
+               08FB77AFFE84173DC02AAC07 /* Classes */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA4A471D0F5A3C2A00F37A2B /* GrowlITTSWDisplay.h */,
+                               FA4A471E0F5A3C2A00F37A2B /* GrowlITTSWDisplay.m */,
+                               FA4A471F0F5A3C2A00F37A2B /* GrowlITTSWPrefs.h */,
+                               FA4A47200F5A3C2A00F37A2B /* GrowlITTSWPrefs.m */,
+                               FA4A47210F5A3C2A00F37A2B /* GrowlITTSWController.h */,
+                               FA4A47220F5A3C2A00F37A2B /* GrowlITTSWController.m */,
+                               FA4A47230F5A3C2A00F37A2B /* GrowlITTSWWindow.h */,
+                               FA4A47240F5A3C2A00F37A2B /* GrowlITTSWWindow.m */,
+                       );
+                       name = Classes;
+                       sourceTree = "<group>";
+               };
+               1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,
+                               FA50774C0F5A7A2D008DEAD9 /* PreferencePanes.framework */,
+                       );
+                       name = "Linked Frameworks";
+                       sourceTree = "<group>";
+               };
+               1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               089C167FFE841241C02AAC07 /* AppKit.framework */,
+                               D2F7E65807B2D6F200F64583 /* CoreData.framework */,
+                               089C1672FE841209C02AAC07 /* Foundation.framework */,
+                       );
+                       name = "Other Frameworks";
+                       sourceTree = "<group>";
+               };
+               19C28FB8FE9D52D311CA2CBB /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               8D5B49B6048680CD000E48DA /* GrowlITTSW.growlView */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               32C88E010371C26100C91783 /* Other Sources */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA5074060F5A5562008DEAD9 /* GrowlDefines.h */,
+                               FA50739B0F5A4D74008DEAD9 /* GrowlDefinesInternal.h */,
+                               FA5073AA0F5A4D9A008DEAD9 /* GrowlApplicationNotification.h */,
+                               FA4A472B0F5A3C3100F37A2B /* GrowlPlugin.h */,
+                               FA4A472C0F5A3C3100F37A2B /* GrowlDisplayPlugin.h */,
+                               32DBCF630370AF2F00C91783 /* GrowlITTSW_Prefix.pch */,
+                       );
+                       name = "Other Sources";
+                       sourceTree = "<group>";
+               };
+               FA4A47300F5A3C5900F37A2B /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA4A47340F5A3C5900F37A2B /* ITFoundation.framework */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               FA4A47380F5A3C6900F37A2B /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               FA4A473D0F5A3C6900F37A2B /* ITKit.framework */,
+                               FA4A473F0F5A3C6900F37A2B /* ITKitShowcase.app */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+               8D5B49AC048680CD000E48DA /* GrowlITTSW */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "GrowlITTSW" */;
+                       buildPhases = (
+                               8D5B49AF048680CD000E48DA /* Resources */,
+                               8D5B49B1048680CD000E48DA /* Sources */,
+                               8D5B49B3048680CD000E48DA /* Frameworks */,
+                               FA50745D0F5A570F008DEAD9 /* CopyFiles */,
+                               FA50761F0F5A692D008DEAD9 /* ShellScript */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               FA4A474A0F5A3CD300F37A2B /* PBXTargetDependency */,
+                               FA4A474C0F5A3CD500F37A2B /* PBXTargetDependency */,
+                       );
+                       name = GrowlITTSW;
+                       productInstallPath = "$(HOME)/Library/Bundles";
+                       productName = GrowlITTSW;
+                       productReference = 8D5B49B6048680CD000E48DA /* GrowlITTSW.growlView */;
+                       productType = "com.apple.product-type.bundle";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               089C1669FE841209C02AAC07 /* Project object */ = {
+                       isa = PBXProject;
+                       buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "GrowlITTSW" */;
+                       compatibilityVersion = "Xcode 3.1";
+                       hasScannedForEncodings = 1;
+                       mainGroup = 089C166AFE841209C02AAC07 /* GrowlITTSW */;
+                       projectDirPath = "";
+                       projectReferences = (
+                               {
+                                       ProductGroup = FA4A47300F5A3C5900F37A2B /* Products */;
+                                       ProjectRef = FA4A472F0F5A3C5900F37A2B /* ITFoundation.xcodeproj */;
+                               },
+                               {
+                                       ProductGroup = FA4A47380F5A3C6900F37A2B /* Products */;
+                                       ProjectRef = FA4A47370F5A3C6900F37A2B /* ITKit.xcodeproj */;
+                               },
+                       );
+                       projectRoot = "";
+                       targets = (
+                               8D5B49AC048680CD000E48DA /* GrowlITTSW */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+               FA4A47340F5A3C5900F37A2B /* ITFoundation.framework */ = {
+                       isa = PBXReferenceProxy;
+                       fileType = wrapper.framework;
+                       path = ITFoundation.framework;
+                       remoteRef = FA4A47330F5A3C5900F37A2B /* PBXContainerItemProxy */;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               FA4A473D0F5A3C6900F37A2B /* ITKit.framework */ = {
+                       isa = PBXReferenceProxy;
+                       fileType = wrapper.framework;
+                       path = ITKit.framework;
+                       remoteRef = FA4A473C0F5A3C6900F37A2B /* PBXContainerItemProxy */;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               FA4A473F0F5A3C6900F37A2B /* ITKitShowcase.app */ = {
+                       isa = PBXReferenceProxy;
+                       fileType = wrapper.application;
+                       path = ITKitShowcase.app;
+                       remoteRef = FA4A473E0F5A3C6900F37A2B /* PBXContainerItemProxy */;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+               8D5B49AF048680CD000E48DA /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
+                               FA4A47510F5A3CFC00F37A2B /* GrowlITTSWPrefs.nib in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               FA50761F0F5A692D008DEAD9 /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "install_name_tool -change \\\n\t\"@executable_path/../Frameworks/ITFoundation.framework/Versions/A/ITFoundation\" \\\n\t\"@loader_path/../Frameworks/ITFoundation.framework/Versions/A/ITFoundation\" \\\n\t\"$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/$EXECUTABLE_NAME\"\n\ninstall_name_tool -change \\\n\t\"@executable_path/../Frameworks/ITKit.framework/Versions/A/ITKit\" \\\n\t\"@loader_path/../Frameworks/ITKit.framework/Versions/A/ITKit\" \\\n\t\"$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/$EXECUTABLE_NAME\"\n\ninstall_name_tool -change \\\n\t\"@executable_path/../Frameworks/ITFoundation.framework/Versions/A/ITFoundation\" \\\n\t\"@loader_path/../../../../Frameworks/ITFoundation.framework/Versions/A/ITFoundation\" \\\n\t\"$TARGET_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH/ITKit.framework/Versions/A/ITKit\"";
+               };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               8D5B49B1048680CD000E48DA /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               FA4A47250F5A3C2A00F37A2B /* GrowlITTSWDisplay.m in Sources */,
+                               FA4A47270F5A3C2A00F37A2B /* GrowlITTSWController.m in Sources */,
+                               FA4A47280F5A3C2A00F37A2B /* GrowlITTSWWindow.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+               FA4A474A0F5A3CD300F37A2B /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       name = ITFoundation;
+                       targetProxy = FA4A47490F5A3CD300F37A2B /* PBXContainerItemProxy */;
+               };
+               FA4A474C0F5A3CD500F37A2B /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       name = ITKit;
+                       targetProxy = FA4A474B0F5A3CD500F37A2B /* PBXContainerItemProxy */;
+               };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+               089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
+                       isa = PBXVariantGroup;
+                       children = (
+                               089C167EFE841241C02AAC07 /* English */,
+                       );
+                       name = InfoPlist.strings;
+                       sourceTree = "<group>";
+               };
+               FA4A474F0F5A3CFC00F37A2B /* GrowlITTSWPrefs.nib */ = {
+                       isa = PBXVariantGroup;
+                       children = (
+                               FA4A47500F5A3CFC00F37A2B /* English */,
+                       );
+                       name = GrowlITTSWPrefs.nib;
+                       sourceTree = "<group>";
+               };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+               1DEB913B08733D840010E9CD /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               COPY_PHASE_STRIP = NO;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
+                               GCC_MODEL_TUNING = G5;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
+                               GCC_PREFIX_HEADER = GrowlITTSW_Prefix.pch;
+                               INFOPLIST_FILE = Info.plist;
+                               INSTALL_PATH = "$(USER_LIBRARY_DIR)/Application Support/Growl/Plugins";
+                               LIBRARY_STYLE = BUNDLE;
+                               OTHER_LDFLAGS = (
+                                       "-undefined",
+                                       dynamic_lookup,
+                               );
+                               PRODUCT_NAME = GrowlITTSW;
+                               REZ_RESOURCE_MAP_READ_ONLY = YES;
+                               WRAPPER_EXTENSION = growlView;
+                       };
+                       name = Debug;
+               };
+               1DEB913C08733D840010E9CD /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_MODEL_TUNING = G5;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
+                               GCC_PREFIX_HEADER = GrowlITTSW_Prefix.pch;
+                               INFOPLIST_FILE = Info.plist;
+                               INSTALL_PATH = "$(USER_LIBRARY_DIR)/Application Support/Growl/Plugins";
+                               LIBRARY_STYLE = BUNDLE;
+                               OTHER_LDFLAGS = (
+                                       "-undefined",
+                                       dynamic_lookup,
+                               );
+                               PRODUCT_NAME = GrowlITTSW;
+                               REZ_RESOURCE_MAP_READ_ONLY = YES;
+                               WRAPPER_EXTENSION = growlView;
+                       };
+                       name = Release;
+               };
+               1DEB913F08733D840010E9CD /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+                               GCC_C_LANGUAGE_STANDARD = c99;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               PREBINDING = NO;
+                               SDKROOT = macosx10.5;
+                       };
+                       name = Debug;
+               };
+               1DEB914008733D840010E9CD /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+                               GCC_C_LANGUAGE_STANDARD = c99;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               PREBINDING = NO;
+                               SDKROOT = macosx10.5;
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "GrowlITTSW" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               1DEB913B08733D840010E9CD /* Debug */,
+                               1DEB913C08733D840010E9CD /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "GrowlITTSW" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               1DEB913F08733D840010E9CD /* Debug */,
+                               1DEB914008733D840010E9CD /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 089C1669FE841209C02AAC07 /* Project object */;
+}
diff --git a/GrowlITTSWController.h b/GrowlITTSWController.h
new file mode 100644 (file)
index 0000000..469d6e5
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  GrowlITTSWController.h
+//  Growl
+//
+//  Created by Joseph Spiros on 2/28/09.
+//  Copyright 2009 iThink Software. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <ITFoundation/ITSharedController.h>
+#import "GrowlITTSWWindow.h"
+
+@interface GrowlITTSWController : ITSharedController {
+       GrowlITTSWWindow *_window;
+}
+
+- (void)showWindowWithText:(NSString *)text image:(NSImage *)image;
+
+@end
diff --git a/GrowlITTSWController.m b/GrowlITTSWController.m
new file mode 100644 (file)
index 0000000..0f1cd0e
--- /dev/null
@@ -0,0 +1,93 @@
+//
+//  GrowlITTSWController.m
+//  Growl
+//
+//  Created by Joseph Spiros on 2/28/09.
+//  Copyright 2009 iThink Software. All rights reserved.
+//
+
+#import "GrowlITTSWController.h"
+#import "GrowlITTSWWindow.h"
+
+#import <ITKit/ITTSWBackgroundView.h>
+#import <ITKit/ITWindowEffect.h>
+
+@implementation NSImage (SmoothAdditions)
+
+- (NSImage *)imageScaledSmoothlyToSize:(NSSize)scaledSize
+{
+    NSImage *newImage;
+    NSImageRep *rep = [self bestRepresentationForDevice:nil];
+    
+    newImage = [[NSImage alloc] initWithSize:scaledSize];
+    [newImage lockFocus];
+    {
+        [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
+        [[NSGraphicsContext currentContext] setShouldAntialias:YES];
+        [rep drawInRect:NSMakeRect(3, 3, scaledSize.width - 6, scaledSize.height - 6)];
+    }
+    [newImage unlockFocus];
+    return [newImage autorelease];
+}
+
+@end
+
+@implementation GrowlITTSWController
+
+- (id)init
+{
+    if ( ( self = [super init] ) ) {
+               NSArray *screens = [NSScreen screens];
+        
+               _window = [[GrowlITTSWWindow sharedWindow] retain];
+               
+               [_window setScreen:[screens objectAtIndex:0]];
+               
+        [_window setExitMode:ITTransientStatusWindowExitAfterDelay];
+        [_window setExitDelay:4.0];
+        
+        [_window setHorizontalPosition:ITWindowPositionRight];
+        [_window setVerticalPosition:ITWindowPositionTop];
+        
+        [_window setSizing:ITTransientStatusWindowMini];
+        
+        [_window setEntryEffect:[[[NSClassFromString(@"ITSlideVerticallyWindowEffect") alloc] initWithWindow:_window] autorelease]];
+        [_window setExitEffect:[[[NSClassFromString(@"ITSlideHorizontallyWindowEffect") alloc] initWithWindow:_window] autorelease]];
+        
+        [[_window entryEffect] setEffectTime:0.8];
+        [[_window exitEffect]  setEffectTime:0.8];
+        
+        [(ITTSWBackgroundView *)[_window contentView]setBackgroundMode:
+                ITTSWBackgroundReadable];
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    [_window release];
+    [super dealloc];
+}
+
+- (void)showWindowWithText:(NSString *)text image:(NSImage *)image
+{
+    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
+       NSSize newSize;
+       NSSize oldSize = [image size];
+       
+       if (oldSize.width > oldSize.height) {
+               newSize = NSMakeSize(110.0f, (oldSize.height * (110.0f / oldSize.width)));
+       } else {
+               newSize = NSMakeSize((oldSize.width * (110.0f / oldSize.height)), 110.0f);
+       }
+       
+       image = [[[[NSImage alloc] initWithData:[image TIFFRepresentation]] autorelease] imageScaledSmoothlyToSize:newSize];
+       
+       [_window setImage:image];
+    [_window buildTextWindowWithString:attributedText];
+    [_window appear:self];
+       [attributedText release];
+}
+
+@end
\ No newline at end of file
diff --git a/GrowlITTSWDisplay.h b/GrowlITTSWDisplay.h
new file mode 100644 (file)
index 0000000..1330358
--- /dev/null
@@ -0,0 +1,11 @@
+#import <Cocoa/Cocoa.h>
+#import "GrowlDisplayPlugin.h"
+
+@class GrowlApplicationNotification;
+
+@interface GrowlITTSWDisplay : GrowlDisplayPlugin {
+}
+
+- (void) displayNotification:(GrowlApplicationNotification *)notification;
+
+@end
diff --git a/GrowlITTSWDisplay.m b/GrowlITTSWDisplay.m
new file mode 100644 (file)
index 0000000..bbd7515
--- /dev/null
@@ -0,0 +1,42 @@
+#import "GrowlITTSWDisplay.h"
+#import "GrowlITTSWController.h"
+#import "GrowlITTSWPrefs.h"
+#import "GrowlDefines.h"
+#import "GrowlDefinesInternal.h"
+#import "GrowlApplicationNotification.h"
+
+@implementation GrowlITTSWDisplay
+
+- (void) dealloc {
+       [preferencePane release];
+       [super dealloc];
+}
+
+/* - (NSPreferencePane *) preferencePane {
+       if (!preferencePane)
+               preferencePane = [[GrowlITTSWPrefs alloc] initWithBundle:[NSBundle bundleWithIdentifier:@"com.ithinksw.growl.ittsw"]];
+       return preferencePane;
+}*/
+
+//we implement requiresPositioning entirely because it was added as a requirement for doing 1.1 plugins, however
+//we don't really care if positioning is required or not, because we are only ever in the menubar.
+- (BOOL)requiresPositioning {
+       return NO;
+}
+
+#pragma mark -
+- (void) displayNotification:(GrowlApplicationNotification *)notification {
+       NSDictionary *dict = [notification dictionaryRepresentation];
+       NSString *title = [dict objectForKey:GROWL_NOTIFICATION_TITLE];
+       NSString *desc = [dict objectForKey:GROWL_NOTIFICATION_DESCRIPTION];
+       NSImage *image = [dict objectForKey:GROWL_NOTIFICATION_ICON];
+       NSString *text;
+       if (desc) {
+               text = [title stringByAppendingFormat:@"\n%@", desc];
+       } else {
+               text = title;
+       }
+       [[GrowlITTSWController sharedController] showWindowWithText:text image:image];
+}
+
+@end
diff --git a/GrowlITTSWPrefs.h b/GrowlITTSWPrefs.h
new file mode 100644 (file)
index 0000000..e2c287d
--- /dev/null
@@ -0,0 +1,6 @@
+#import <PreferencePanes/PreferencePanes.h>
+
+@interface GrowlITTSWPrefs : NSPreferencePane {
+}
+
+@end
diff --git a/GrowlITTSWPrefs.m b/GrowlITTSWPrefs.m
new file mode 100644 (file)
index 0000000..395b2ff
--- /dev/null
@@ -0,0 +1,6 @@
+#import "GrowlITTSWPrefs.h"
+#import "GrowlDefinesInternal.h"
+
+@implementation GrowlITTSWPrefs
+
+@end
diff --git a/GrowlITTSWWindow.h b/GrowlITTSWWindow.h
new file mode 100644 (file)
index 0000000..2dc64c9
--- /dev/null
@@ -0,0 +1,15 @@
+#import <Cocoa/Cocoa.h>
+#import <ITKit/ITKit.h>
+
+#define SMALL_DIVISOR       1.33333
+#define MINI_DIVISOR        1.66667
+
+@interface GrowlITTSWWindow : ITTransientStatusWindow {
+       NSImage *_image;
+       NSTextField *_textField;
+}
+
+- (void)setImage:(NSImage *)newImage;
+- (void)buildTextWindowWithString:(id)text;
+
+@end
diff --git a/GrowlITTSWWindow.m b/GrowlITTSWWindow.m
new file mode 100644 (file)
index 0000000..0616224
--- /dev/null
@@ -0,0 +1,252 @@
+//
+//  GrowlITTSWWindow.m
+//  Growl
+//
+//  Created by Joseph Spiros on 2/28/09.
+//  Copyright 2009 iThink Software. All rights reserved.
+//
+
+#import "GrowlITTSWWindow.h"
+
+#define SW_PAD             24.00
+#define SW_SPACE           24.00
+#define SW_MINW           211.00
+#define SW_BORDER          32.00
+#define SW_METER_PAD        4.00
+#define SW_BUTTON_PAD_R    30.00
+#define SW_BUTTON_PAD_B    24.00
+#define SW_BUTTON_DIV      12.00
+#define SW_BUTTON_EXTRA_W   8.00
+#define SW_SHADOW_SAT       1.25
+
+@interface GrowlITTSWWindow (Private)
+- (NSRect)setupWindowWithDataSize:(NSSize)dataSize;
+@end
+
+@implementation GrowlITTSWWindow
+
+
+/*************************************************************************/
+#pragma mark -
+#pragma mark INITIALIZATION / DEALLOCATION METHODS
+/*************************************************************************/
+
+- (id)initWithContentView:(NSView *)contentView
+                 exitMode:(ITTransientStatusWindowExitMode)exitMode
+           backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
+{
+    if ( ( self = [super initWithContentView:contentView
+                                                                       exitMode:exitMode
+                                                         backgroundType:backgroundType] ) ) {
+               // Set default values.
+        _image  = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
+        _sizing = ITTransientStatusWindowRegular;
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    [_image release];
+    [super dealloc];
+}
+
+
+/*************************************************************************/
+#pragma mark -
+#pragma mark ACCESSOR METHODS
+/*************************************************************************/
+
+- (void)setImage:(NSImage *)newImage
+{
+    [_image autorelease];
+    _image = [newImage copy];
+}
+
+- (void)setSizing:(ITTransientStatusWindowSizing)newSizing
+{
+    _sizing = newSizing;
+}
+
+/*************************************************************************/
+#pragma mark -
+#pragma mark INSTANCE METHODS
+/*************************************************************************/
+
+- (void)appear:(id)sender
+{
+    [super appear:sender];
+}
+
+- (void)vanish:(id)sender
+{
+    [super vanish:sender];
+}
+
+- (NSRect)setupWindowWithDataSize:(NSSize)dataSize
+{
+    float        divisor       = 1.0;
+    NSRect       imageRect;
+    float        imageWidth    = 0.0;
+    float        imageHeight   = 0.0;
+    float        dataWidth     = dataSize.width;
+    float        dataHeight    = dataSize.height;
+    float        contentHeight = 0.0;
+    float        windowWidth   = 0.0;
+    float        windowHeight  = 0.0;
+    NSRect       visibleFrame  = [[self screen] visibleFrame];
+    NSPoint      screenOrigin  = visibleFrame.origin;
+    float        screenWidth   = visibleFrame.size.width;
+    float        screenHeight  = visibleFrame.size.height;
+    float        maxWidth      = ( screenWidth  - (SW_BORDER * 2) );
+    float        maxHeight     = ( screenHeight - (SW_BORDER * 2) );
+    float        excessWidth   = 0.0;
+    float        excessHeight  = 0.0;
+    NSPoint      windowOrigin  = NSZeroPoint;
+    ITImageView *imageView;
+    BOOL         shouldAnimate = ( ! (([self visibilityState] == ITWindowAppearingState) ||
+                                      ([self visibilityState] == ITWindowVanishingState)) );
+       
+    if ( _sizing == ITTransientStatusWindowSmall ) {
+        divisor = SMALL_DIVISOR;
+    } else if ( _sizing == ITTransientStatusWindowMini ) {
+        divisor = MINI_DIVISOR;
+    }
+       
+       //  Get image width and height.
+    imageWidth  = ( [_image size].width  / divisor );
+    imageHeight = ( [_image size].height / divisor );
+    
+       //  Set the content height to the greater of the text and image heights.
+    contentHeight = ( ( imageHeight > dataHeight ) ? imageHeight : dataHeight );
+       
+       //  Setup the Window, and remove all its contentview's subviews.
+    windowWidth  = ( (SW_PAD / divisor) + imageWidth + ((dataWidth > 0) ? (SW_SPACE / divisor) + dataWidth : 0) + (SW_PAD / divisor) );
+    windowHeight = ( (SW_PAD / divisor) + contentHeight + (SW_PAD / divisor) );
+    
+       //  Constrain size to max limits.  Adjust data sizes accordingly.
+    excessWidth  = (windowWidth  - maxWidth );
+    excessHeight = (windowHeight - maxHeight);
+       
+    if ( excessWidth > 0.0 ) {
+        windowWidth = maxWidth;
+        dataWidth -= excessWidth;
+    }
+    
+    if ( excessHeight > 0.0 ) {
+        windowHeight = maxHeight;
+        dataHeight -= excessHeight;
+    }
+    
+    if ( [self horizontalPosition] == ITWindowPositionLeft ) {
+        windowOrigin.x = ( SW_BORDER + screenOrigin.x );
+    } else if ( [self horizontalPosition] == ITWindowPositionCenter ) {
+        windowOrigin.x = ( screenOrigin.x + (screenWidth / 2) - (windowWidth / 2) );
+    } else if ( [self horizontalPosition] == ITWindowPositionRight ) {
+        windowOrigin.x = ( screenOrigin.x + screenWidth - (windowWidth + SW_BORDER) );
+    }
+    
+    if ( [self verticalPosition] == ITWindowPositionTop ) {
+        windowOrigin.y = ( screenOrigin.y + screenHeight - (windowHeight + SW_BORDER) );
+    } else if ( [self verticalPosition] == ITWindowPositionMiddle ) {
+               //      Middle-oriented windows should be slightly proud of the screen's middle.
+        windowOrigin.y = ( (screenOrigin.y + (screenHeight / 2) - (windowHeight / 2)) + (screenHeight / 8) );
+    } else if ( [self verticalPosition] == ITWindowPositionBottom ) {
+        windowOrigin.y = ( SW_BORDER + screenOrigin.y );
+    }
+    
+    [self setFrame:NSMakeRect( windowOrigin.x,
+                                                         windowOrigin.y,
+                                                         windowWidth,
+                                                         windowHeight) display:YES animate:shouldAnimate];
+       
+    [[[self contentView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
+    
+       //  Setup, position, fill, and add the image view to the content view.
+    imageRect = NSMakeRect( (SW_PAD / divisor) + ((dataWidth > 0) ? 4 : 0),
+                                                  ((SW_PAD / divisor) + ((contentHeight - imageHeight) / 2)),
+                                                  imageWidth,
+                                                  imageHeight );
+    imageView = [[[ITImageView alloc] initWithFrame:imageRect] autorelease];
+    [imageView setAutoresizingMask:(NSViewMinYMargin | NSViewMaxYMargin)];
+    [imageView setImage:_image];
+    [imageView setCastsShadow:YES];
+    [[self contentView] addSubview:imageView];
+       
+    return NSMakeRect( ((SW_PAD / divisor) + imageWidth + (SW_SPACE / divisor)),
+                                         ((SW_PAD / divisor) + ((contentHeight - dataHeight) / 2)),
+                                         dataWidth,
+                                         dataHeight);
+}
+
+- (void)buildTextWindowWithString:(id)text
+{
+       float         divisor       = 1.0;
+       float         dataWidth     = 0.0;
+       float         dataHeight    = 0.0;
+       NSRect        dataRect;
+       NSArray      *lines                     = [(([text isKindOfClass:[NSString class]]) ? text : [text mutableString]) componentsSeparatedByString:@"\n"];
+       id                        oneLine       = nil;
+       NSEnumerator *lineEnum          = [lines objectEnumerator];
+       float         baseFontSize  = 18.0;
+       ITTextField  *textField;
+       NSFont       *font;
+       NSDictionary *attr;
+       
+       if ( _sizing == ITTransientStatusWindowSmall ) {
+               divisor = SMALL_DIVISOR;
+       } else if ( _sizing == ITTransientStatusWindowMini ) {
+               divisor = MINI_DIVISOR;
+       }
+       
+       font = [NSFont fontWithName:@"LucidaGrande-Bold" size:(baseFontSize / divisor)];
+       attr = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
+       
+       //      Iterate over each line to get text width and height
+       while ( (oneLine = [lineEnum nextObject]) ) {
+               //          Get the width of one line, adding 8.0 because Apple sucks donkey rectum.
+               float oneLineWidth = ( [oneLine sizeWithAttributes:attr].width + 8.0 );
+               //          Add the height of this line to the total text height
+               dataHeight += [oneLine sizeWithAttributes:attr].height;
+               //          If this line wider than the last one, set it as the text width.
+               dataWidth = ( ( dataWidth > oneLineWidth ) ? dataWidth : oneLineWidth );
+       }
+       
+       //      Add 4.0 to the final dataHeight to accomodate the shadow.
+       dataHeight += 4.0;
+       
+       dataRect = [self setupWindowWithDataSize:NSMakeSize(dataWidth, dataHeight)];
+       
+       //      Create, position, setup, fill, and add the text view to the content view.
+       textField = [[[ITTextField alloc] initWithFrame:dataRect] autorelease];
+       [textField setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
+       [textField setEditable:NO];
+       [textField setSelectable:NO];
+       [textField setBordered:NO];
+       [textField setDrawsBackground:NO];
+       [textField setFont:font];
+       [textField setTextColor:[NSColor whiteColor]];
+       [textField setCastsShadow:YES];
+       [[textField cell] setWraps:NO];
+       
+       if ([text isKindOfClass:[NSString class]]) {
+               [textField setStringValue:text];
+       } else {
+               [textField setAttributedStringValue:text];
+       }
+       
+       [textField setShadowSaturation:SW_SHADOW_SAT];
+       [[self contentView] addSubview:textField];
+       
+       //      Display the window.
+       [[self contentView] setNeedsDisplay:YES];
+       _textField = textField;
+}
+
+- (NSTimeInterval)animationResizeTime:(NSRect)newFrame
+{
+    return (NSTimeInterval)0.25;
+}
+
+@end
diff --git a/GrowlITTSW_Prefix.pch b/GrowlITTSW_Prefix.pch
new file mode 100644 (file)
index 0000000..399baf0
--- /dev/null
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'GrowlITTSW' target in the 'GrowlITTSW' project.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif
diff --git a/GrowlPlugin.h b/GrowlPlugin.h
new file mode 100644 (file)
index 0000000..fd3d30a
--- /dev/null
@@ -0,0 +1,105 @@
+//
+//  GrowlPlugin.h
+//  Growl
+//
+//  Created by Mac-arena the Bored Zo on 2005-06-01.
+//  Copyright 2005-2006 The Growl Project. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@class NSPreferencePane;
+
+/*!    @class  GrowlPlugin
+ *     @abstract       The base plug-in class.
+ *     @discussion     All Growl plug-in instances are a kind of this class, including
+ *      display plug-ins, which are kinds of <code>GrowlDisplayPlugin</code>.
+ */
+@interface GrowlPlugin : NSObject {
+       NSString *pluginName, *pluginAuthor, *pluginVersion, *pluginDesc;
+       NSBundle *pluginBundle;
+       NSString *pluginPathname;
+
+       NSPreferencePane *preferencePane;
+       NSString             *prefDomain;
+}
+
+/*!
+ * @method initWithName:author:version:pathname:
+ * @abstract Designated initializer.
+ * @param name The name of the plugin.
+ * @param author The author of the plugin.
+ * @param version The version of the plugin.
+ * @param pathname The pathname of the plugin.
+ * @result An initialized GrowlPlugin object.
+ */
+- (id) initWithName:(NSString *)name author:(NSString *)author version:(NSString *)version pathname:(NSString *)pathname;
+
+/*!
+ * @method initWithBundle:
+ * @abstract Initializer for plug-ins in bundles. The name, author, version, and pathname will be obtained from the bundle.
+ * @result An initialized GrowlPlugin object.
+ */
+- (id) initWithBundle:(NSBundle *)bundle;
+
+
+/*!
+ * @method name
+ * @abstract Returns the name of the receiver.
+ */
+- (NSString *) name;
+
+/*!
+ * @method author
+ * @abstract Returns the author of the receiver.
+ */
+- (NSString *) author;
+
+/*!
+ * @method pluginDescription
+ * @abstract Returns the description of the receiver.
+ */
+- (NSString *) pluginDescription;
+
+/*!
+ * @method version
+ * @abstract Returns the version of the receiver.
+ */
+- (NSString *) version;
+
+/*!
+ * @method bundle
+ * @abstract Returns the bundle of the receiver.
+ */
+- (NSBundle *) bundle;
+
+/*!
+ * @method pathname
+ * @abstract Returns the pathname of the receiver.
+ */
+- (NSString *) pathname;
+
+/*!
+* @method pathname
+ * @abstract Returns the string used to access the preference domain of the receiver.
+ */
+- (NSString *) prefDomain;
+
+
+/*!    @method preferencePane
+ *     @abstract       Return an <code>NSPreferencePane</code> instance that manages
+ *      the plugin's preferences.
+ *     @discussion     Your plug-in should put the controls for its preferences in
+ *      this preference pane.
+ *
+ *      Currently, the size of the preference pane's view should be 354 pixels by
+ *      289 pixels, but you should set the springs of the view and its subviews
+ *      under the assumption that it can be resized horizontally and vertically to
+ *      any size.
+ *
+ *      The default implementation of this method returns <code>nil</code>.
+ *     @result The preference pane. Can be <code>nil</code>.
+ */
+- (NSPreferencePane *) preferencePane;
+
+@end
diff --git a/Info.plist b/Info.plist
new file mode 100644 (file)
index 0000000..7bc2d5d
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>GrowlITTSW</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.ithinksw.growl-ittsw</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>GrowlITTSW</string>
+       <key>CFBundlePackageType</key>
+       <string>DISP</string>
+       <key>CFBundleSignature</key>
+       <string>GRRR</string>
+       <key>CFBundleVersion</key>
+       <string>1.0</string>
+       <key>CSResourcesFileMapped</key>
+       <string>yes</string>
+       <key>GrowlDisplayUsesQueue</key>
+       <true/>
+       <key>GrowlPluginAuthor</key>
+       <string>iThink Software</string>
+       <key>GrowlPluginDescription</key>
+       <string>ITTSW uses the ITTransientStatusWindow class from ITKit</string>
+       <key>NSPrincipalClass</key>
+       <string>GrowlITTSWDisplay</string>
+</dict>
+</plist>