From d2224fae1d2c8062999a4d79f5dad7d7a8221b9b Mon Sep 17 00:00:00 2001 From: greay Date: Tue, 1 Jun 2010 23:28:44 -0700 Subject: [PATCH] initial commit of Phil Dow's (unchanged) Sprouted Interface framework --- .gitignore | 6 + ABBarSmall.png | Bin 0 -> 1381 bytes ActualSize.png | Bin 0 -> 948 bytes ActualSizePressed.png | Bin 0 -> 3831 bytes AppleScriptActionBarSmall.png | Bin 0 -> 937 bytes AppleScriptAlert.h | 23 + AppleScriptAlert.m | 66 + Back.tif | Bin 0 -> 1304 bytes BackDisabled.tif | Bin 0 -> 1378 bytes BackPressed.tif | Bin 0 -> 17600 bytes Bigger.png | Bin 0 -> 710 bytes BiggerDisabled.png | Bin 0 -> 660 bytes BiggerPressed.png | Bin 0 -> 3540 bytes CollectionManagerView.h | 25 + CollectionManagerView.m | 80 + ComposeMailBarSmall.png | Bin 0 -> 1195 bytes ConditionController.h | 98 + ConditionController.m | 384 +++ CustomFindPanel.h | 17 + CustomFindPanel.m | 28 + Display.png | Bin 0 -> 1008 bytes DisplayPressed.png | Bin 0 -> 3873 bytes DocumentMakerController.h | 45 + DocumentMakerController.m | 148 ++ DragView.h | 17 + DragView.m | 30 + EmailBarSmall.png | Bin 0 -> 1818 bytes English.lproj/FileInfo.strings | 10 + English.lproj/InfoPlist.strings | Bin 0 -> 210 bytes English.lproj/InsertLink.nib/classes.nib | 17 + English.lproj/InsertLink.nib/info.nib | 14 + English.lproj/InsertLink.nib/keyedobjects.nib | Bin 0 -> 6972 bytes .../IntegrationFileCopy.nib/classes.nib | 12 + .../IntegrationFileCopy.nib/info.nib | 12 + .../IntegrationFileCopy.nib/keyedobjects.nib | Bin 0 -> 4290 bytes English.lproj/Mediabar.strings | 27 + English.lproj/NewMediabarItem.nib/classes.nib | 36 + English.lproj/NewMediabarItem.nib/info.nib | 16 + .../NewMediabarItem.nib/keyedobjects.nib | Bin 0 -> 12702 bytes English.lproj/PDFavoritesBar.strings | 5 + English.lproj/PDFontPreview.strings | 1 + English.lproj/PDTabsView.strings | 4 + .../SproutedAboutBox.nib/classes.nib | 98 + English.lproj/SproutedAboutBox.nib/info.nib | 18 + .../SproutedAboutBox.nib/keyedobjects.nib | Bin 0 -> 7281 bytes English.lproj/Stats.nib/classes.nib | 14 + English.lproj/Stats.nib/info.nib | 18 + English.lproj/Stats.nib/keyedobjects.nib | Bin 0 -> 5727 bytes EtchedPopUpButton.h | 15 + EtchedPopUpButton.m | 43 + EtchedPopUpButtonCell.h | 14 + EtchedPopUpButtonCell.m | 43 + EtchedText.h | 14 + EtchedText.m | 42 + EtchedTextCell.h | 14 + EtchedTextCell.m | 41 + Forward.tif | Bin 0 -> 1324 bytes ForwardDisabled.tif | Bin 0 -> 1364 bytes ForwardPressed.tif | Bin 0 -> 17704 bytes HUDWindow.h | 33 + HUDWindow.m | 296 +++ Home.tif | Bin 0 -> 1592 bytes HomePressed.tif | Bin 0 -> 18092 bytes ImageAndTextCell.h | 50 + ImageAndTextCell.m | 588 +++++ Info.plist | 26 + InfoBarSmall.png | Bin 0 -> 1411 bytes IntegrationCopyFiles.h | 26 + IntegrationCopyFiles.m | 80 + JRLRFooter.h | 15 + JRLRFooter.m | 47 + JournlerGradientView.h | 63 + JournlerGradientView.m | 476 ++++ LabelPicker.h | 50 + LabelPicker.m | 238 ++ LinkController.h | 36 + LinkController.m | 110 + MNLineNumberingRulerView.h | 101 + MNLineNumberingRulerView.m | 1095 +++++++++ MNLineNumberingTextStorage.h | 32 + MNLineNumberingTextStorage.m | 140 ++ MNLineNumberingTextView.h | 52 + MNLineNumberingTextView.m | 128 + MUPhotoCell.h | 23 + MUPhotoCell.m | 137 ++ MUPhotoView.h | 317 +++ MUPhotoView.m | 2168 +++++++++++++++++ MUPhotoView.zip | Bin 0 -> 21145 bytes MediaContentController.h | 107 + MediaContentController.m | 658 +++++ MediaViewer.h | 52 + MediaViewer.m | 305 +++ MediabarItemApplicationPicker.h | 32 + MediabarItemApplicationPicker.m | 132 + NewMediabarItemController.h | 92 + NewMediabarItemController.m | 423 ++++ PDAnnotatedRulerView.h | 17 + PDAnnotatedRulerView.m | 230 ++ PDAnnotatedTextStorage.h | 19 + PDAnnotatedTextStorage.m | 53 + PDAnnotatedTextView.h | 18 + PDAnnotatedTextView.m | 47 + PDAutoCompleteTextField.h | 19 + PDAutoCompleteTextField.m | 67 + PDBlueHighlightTextCell.h | 16 + PDBlueHighlightTextCell.m | 45 + PDBorderedView.h | 34 + PDBorderedView.m | 196 ++ PDButton.h | 18 + PDButton.m | 37 + PDButtonCell.h | 16 + PDButtonCell.m | 131 + PDButtonColorWell.h | 22 + PDButtonColorWell.m | 84 + PDButtonColorWellCell.h | 21 + PDButtonColorWellCell.m | 196 ++ PDButtonTextOnImage.h | 18 + PDButtonTextOnImage.m | 44 + PDButtonTextOnImageCell.h | 16 + PDButtonTextOnImageCell.m | 127 + PDCaseInsensitiveComboBoxCell.h | 17 + PDCaseInsensitiveComboBoxCell.m | 45 + PDCircleButton.h | 18 + PDCircleButton.m | 37 + PDCircleButtonCell.h | 16 + PDCircleButtonCell.m | 129 + PDColorWell.h | 17 + PDColorWell.m | 19 + PDDateDisplayCell.h | 30 + PDDateDisplayCell.m | 266 ++ PDFavorite.h | 57 + PDFavorite.m | 304 +++ PDFavoritesBar.h | 92 + PDFavoritesBar.m | 963 ++++++++ PDFileInfoView.h | 30 + PDFileInfoView.m | 842 +++++++ PDFontDisplay.h | 18 + PDFontDisplay.m | 63 + PDFontPreview.h | 96 + PDFontPreview.m | 262 ++ PDGradientView.h | 48 + PDGradientView.m | 310 +++ PDHorizontallyCenteredText.h | 25 + PDHorizontallyCenteredText.m | 97 + PDInvisibleButton.h | 17 + PDInvisibleButton.m | 45 + PDInvisibleButtonCell.h | 17 + PDInvisibleButtonCell.m | 63 + PDMatrixButton.h | 18 + PDMatrixButton.m | 36 + PDMatrixButtonCell.h | 16 + PDMatrixButtonCell.m | 186 ++ PDMediaBar.h | 95 + PDMediaBar.m | 591 +++++ PDMediabarItem.h | 59 + PDMediabarItem.m | 229 ++ PDOutlineView.h | 24 + PDOutlineView.m | 48 + PDPhotoView.h | 75 + PDPhotoView.m | 786 ++++++ PDPopUpButton.h | 18 + PDPopUpButton.m | 86 + PDPopUpButtonCell.h | 16 + PDPopUpButtonCell.m | 133 + PDPopUpButtonToolbarItem.h | 21 + PDPopUpButtonToolbarItem.m | 77 + PDPopUpButtonToolbarItemCell.h | 22 + PDPopUpButtonToolbarItemCell.m | 63 + PDPredicateBuilder.h | 36 + PDPrintTextView.h | 41 + PDPrintTextView.m | 136 ++ PDRankCell.h | 27 + PDRankCell.m | 120 + PDSelfValidatingToolbarItem.h | 25 + PDSelfValidatingToolbarItem.m | 43 + PDStylesButton.h | 21 + PDStylesButton.m | 43 + PDStylesButtonCell.h | 20 + PDStylesButtonCell.m | 161 ++ PDTableView.h | 25 + PDTableView.m | 49 + PDTabsView.h | 128 + PDTabsView.m | 1316 ++++++++++ PDTokenField.h | 25 + PDTokenField.m | 45 + PDTokenFieldCell.h | 31 + PDTokenFieldCell.m | 67 + PDToolbar.h | 32 + PDToolbar.m | 85 + PDURLTextField.h | 29 + PDURLTextField.m | 163 ++ PDURLTextFieldCell.h | 43 + PDURLTextFieldCell.m | 229 ++ PDURLTextFieldFileDefault.png | Bin 0 -> 630 bytes PDURLTextFieldWebDefault.tiff | Bin 0 -> 1068 bytes PolishedWindow.h | 42 + PolishedWindow.m | 250 ++ PreviewBarSmall.png | Bin 0 -> 1745 bytes QTBarSmall.png | Bin 0 -> 1516 bytes RBSplitSubview.h | 146 ++ RBSplitSubview.m | 927 +++++++ RBSplitView.h | 225 ++ RBSplitView.m | 1734 +++++++++++++ RBSplitViewPrivateDefines.h | 98 + README | 47 + Read Me.rtf | 64 + Reload.tif | Bin 0 -> 1568 bytes ReloadPressed.tif | Bin 0 -> 17964 bytes RevealInFinderBarSmall.png | Bin 0 -> 1410 bytes RoundedView.h | 15 + RoundedView.m | 55 + RoundedViewWhiteText.h | 26 + RoundedViewWhiteText.m | 84 + SafariBarSmall.png | Bin 0 -> 1625 bytes Smaller.png | Bin 0 -> 717 bytes SmallerDisabled.png | Bin 0 -> 696 bytes SmallerPressed.png | Bin 0 -> 3548 bytes Sprouted Interface.xcodeproj/phildow.mode1 | 1369 +++++++++++ Sprouted Interface.xcodeproj/project.pbxproj | 1492 ++++++++++++ Sprouted Interface_Prefix.pch | 7 + SproutedAboutBoxController.h | 24 + SproutedAboutBoxController.m | 89 + SproutedAnchoredDocumentView.h | 18 + SproutedAnchoredDocumentView.m | 27 + SproutedInterface.h | 110 + StatsController.h | 27 + StatsController.m | 69 + Stop.tif | Bin 0 -> 1564 bytes StopPressed.tif | Bin 0 -> 20156 bytes TextEditBarSmall.png | Bin 0 -> 1618 bytes TransparentWindow.h | 24 + TransparentWindow.m | 103 + Version History.rtf | 22 + WordBarSmall.png | Bin 0 -> 1357 bytes da.lproj/FileInfo.strings | 10 + da.lproj/InfoPlist.strings | Bin 0 -> 210 bytes da.lproj/InsertLink.nib/classes.nib | 17 + da.lproj/InsertLink.nib/info.nib | 14 + da.lproj/InsertLink.nib/keyedobjects.nib | Bin 0 -> 7004 bytes da.lproj/IntegrationFileCopy.nib/classes.nib | 12 + da.lproj/IntegrationFileCopy.nib/info.nib | 12 + .../IntegrationFileCopy.nib/keyedobjects.nib | Bin 0 -> 4315 bytes da.lproj/Mediabar.strings | 27 + da.lproj/NewMediabarItem.nib/classes.nib | 134 + da.lproj/NewMediabarItem.nib/info.nib | 16 + da.lproj/NewMediabarItem.nib/keyedobjects.nib | Bin 0 -> 13080 bytes da.lproj/PDFavoritesBar.strings | 5 + da.lproj/PDFontPreview.strings | 1 + da.lproj/PDTabsView.strings | 4 + da.lproj/SproutedAboutBox.nib/classes.nib | 98 + da.lproj/SproutedAboutBox.nib/info.nib | 18 + .../SproutedAboutBox.nib/keyedobjects.nib | Bin 0 -> 7281 bytes da.lproj/Stats.nib/classes.nib | 14 + da.lproj/Stats.nib/info.nib | 14 + da.lproj/Stats.nib/keyedobjects.nib | Bin 0 -> 5712 bytes de.lproj/FileInfo.strings | 10 + de.lproj/InfoPlist.strings | Bin 0 -> 210 bytes de.lproj/InsertLink.nib/classes.nib | 17 + de.lproj/InsertLink.nib/data.dependency | 10 + de.lproj/InsertLink.nib/info.nib | 14 + de.lproj/InsertLink.nib/keyedobjects.nib | Bin 0 -> 6988 bytes de.lproj/IntegrationFileCopy.nib/classes.nib | 12 + .../IntegrationFileCopy.nib/data.dependency | 10 + de.lproj/IntegrationFileCopy.nib/info.nib | 12 + .../IntegrationFileCopy.nib/keyedobjects.nib | Bin 0 -> 4282 bytes de.lproj/Mediabar.strings | 27 + de.lproj/NewMediabarItem.nib/classes.nib | 134 + de.lproj/NewMediabarItem.nib/info.nib | 18 + de.lproj/NewMediabarItem.nib/keyedobjects.nib | Bin 0 -> 13843 bytes de.lproj/PDFavoritesBar.strings | 5 + de.lproj/PDFontPreview.strings | 1 + de.lproj/PDTabsView.strings | 4 + de.lproj/SproutedAboutBox.nib/classes.nib | 98 + de.lproj/SproutedAboutBox.nib/info.nib | 20 + .../SproutedAboutBox.nib/keyedobjects.nib | Bin 0 -> 7373 bytes de.lproj/Stats.nib/classes.nib | 14 + de.lproj/Stats.nib/info.nib | 18 + de.lproj/Stats.nib/keyedobjects.nib | Bin 0 -> 5754 bytes flat_bottom_left.png | Bin 0 -> 326 bytes flat_bottom_middle.png | Bin 0 -> 221 bytes flat_bottom_right.png | Bin 0 -> 327 bytes flat_middle_left.png | Bin 0 -> 187 bytes flat_middle_right.png | Bin 0 -> 188 bytes flat_top_left.png | Bin 0 -> 344 bytes flat_top_middle.png | Bin 0 -> 237 bytes flat_top_right.png | Bin 0 -> 340 bytes hud_titlebar-close.tiff | Bin 0 -> 622 bytes iTunesBarSmall.png | Bin 0 -> 1936 bytes labelall.tif | Bin 0 -> 26576 bytes labelhover.tif | Bin 0 -> 17048 bytes labelselected.tif | Bin 0 -> 17088 bytes more.tif | Bin 0 -> 482 bytes tabcloseback.tif | Bin 0 -> 516 bytes tabclosebackdown.tif | Bin 0 -> 518 bytes tabclosebackroll.tif | Bin 0 -> 518 bytes tabclosefront.tif | Bin 0 -> 17036 bytes tabclosefrontdown.tif | Bin 0 -> 17032 bytes tabclosefrontroll.tif | Bin 0 -> 17044 bytes 298 files changed, 28510 insertions(+) create mode 100644 .gitignore create mode 100644 ABBarSmall.png create mode 100644 ActualSize.png create mode 100644 ActualSizePressed.png create mode 100644 AppleScriptActionBarSmall.png create mode 100644 AppleScriptAlert.h create mode 100644 AppleScriptAlert.m create mode 100644 Back.tif create mode 100644 BackDisabled.tif create mode 100644 BackPressed.tif create mode 100644 Bigger.png create mode 100644 BiggerDisabled.png create mode 100644 BiggerPressed.png create mode 100644 CollectionManagerView.h create mode 100644 CollectionManagerView.m create mode 100644 ComposeMailBarSmall.png create mode 100644 ConditionController.h create mode 100644 ConditionController.m create mode 100644 CustomFindPanel.h create mode 100644 CustomFindPanel.m create mode 100644 Display.png create mode 100644 DisplayPressed.png create mode 100644 DocumentMakerController.h create mode 100644 DocumentMakerController.m create mode 100644 DragView.h create mode 100644 DragView.m create mode 100644 EmailBarSmall.png create mode 100644 English.lproj/FileInfo.strings create mode 100644 English.lproj/InfoPlist.strings create mode 100644 English.lproj/InsertLink.nib/classes.nib create mode 100644 English.lproj/InsertLink.nib/info.nib create mode 100644 English.lproj/InsertLink.nib/keyedobjects.nib create mode 100644 English.lproj/IntegrationFileCopy.nib/classes.nib create mode 100644 English.lproj/IntegrationFileCopy.nib/info.nib create mode 100644 English.lproj/IntegrationFileCopy.nib/keyedobjects.nib create mode 100644 English.lproj/Mediabar.strings create mode 100644 English.lproj/NewMediabarItem.nib/classes.nib create mode 100644 English.lproj/NewMediabarItem.nib/info.nib create mode 100644 English.lproj/NewMediabarItem.nib/keyedobjects.nib create mode 100644 English.lproj/PDFavoritesBar.strings create mode 100644 English.lproj/PDFontPreview.strings create mode 100644 English.lproj/PDTabsView.strings create mode 100644 English.lproj/SproutedAboutBox.nib/classes.nib create mode 100644 English.lproj/SproutedAboutBox.nib/info.nib create mode 100644 English.lproj/SproutedAboutBox.nib/keyedobjects.nib create mode 100644 English.lproj/Stats.nib/classes.nib create mode 100644 English.lproj/Stats.nib/info.nib create mode 100644 English.lproj/Stats.nib/keyedobjects.nib create mode 100644 EtchedPopUpButton.h create mode 100644 EtchedPopUpButton.m create mode 100644 EtchedPopUpButtonCell.h create mode 100644 EtchedPopUpButtonCell.m create mode 100644 EtchedText.h create mode 100644 EtchedText.m create mode 100644 EtchedTextCell.h create mode 100644 EtchedTextCell.m create mode 100644 Forward.tif create mode 100644 ForwardDisabled.tif create mode 100644 ForwardPressed.tif create mode 100644 HUDWindow.h create mode 100644 HUDWindow.m create mode 100644 Home.tif create mode 100644 HomePressed.tif create mode 100644 ImageAndTextCell.h create mode 100644 ImageAndTextCell.m create mode 100644 Info.plist create mode 100644 InfoBarSmall.png create mode 100644 IntegrationCopyFiles.h create mode 100644 IntegrationCopyFiles.m create mode 100644 JRLRFooter.h create mode 100644 JRLRFooter.m create mode 100644 JournlerGradientView.h create mode 100644 JournlerGradientView.m create mode 100644 LabelPicker.h create mode 100644 LabelPicker.m create mode 100644 LinkController.h create mode 100644 LinkController.m create mode 100644 MNLineNumberingRulerView.h create mode 100644 MNLineNumberingRulerView.m create mode 100644 MNLineNumberingTextStorage.h create mode 100644 MNLineNumberingTextStorage.m create mode 100644 MNLineNumberingTextView.h create mode 100644 MNLineNumberingTextView.m create mode 100644 MUPhotoCell.h create mode 100644 MUPhotoCell.m create mode 100644 MUPhotoView.h create mode 100644 MUPhotoView.m create mode 100644 MUPhotoView.zip create mode 100644 MediaContentController.h create mode 100644 MediaContentController.m create mode 100644 MediaViewer.h create mode 100644 MediaViewer.m create mode 100644 MediabarItemApplicationPicker.h create mode 100644 MediabarItemApplicationPicker.m create mode 100644 NewMediabarItemController.h create mode 100644 NewMediabarItemController.m create mode 100644 PDAnnotatedRulerView.h create mode 100644 PDAnnotatedRulerView.m create mode 100644 PDAnnotatedTextStorage.h create mode 100644 PDAnnotatedTextStorage.m create mode 100644 PDAnnotatedTextView.h create mode 100644 PDAnnotatedTextView.m create mode 100644 PDAutoCompleteTextField.h create mode 100644 PDAutoCompleteTextField.m create mode 100644 PDBlueHighlightTextCell.h create mode 100644 PDBlueHighlightTextCell.m create mode 100644 PDBorderedView.h create mode 100644 PDBorderedView.m create mode 100644 PDButton.h create mode 100644 PDButton.m create mode 100644 PDButtonCell.h create mode 100644 PDButtonCell.m create mode 100644 PDButtonColorWell.h create mode 100644 PDButtonColorWell.m create mode 100644 PDButtonColorWellCell.h create mode 100644 PDButtonColorWellCell.m create mode 100644 PDButtonTextOnImage.h create mode 100644 PDButtonTextOnImage.m create mode 100644 PDButtonTextOnImageCell.h create mode 100644 PDButtonTextOnImageCell.m create mode 100644 PDCaseInsensitiveComboBoxCell.h create mode 100644 PDCaseInsensitiveComboBoxCell.m create mode 100644 PDCircleButton.h create mode 100644 PDCircleButton.m create mode 100644 PDCircleButtonCell.h create mode 100644 PDCircleButtonCell.m create mode 100644 PDColorWell.h create mode 100644 PDColorWell.m create mode 100644 PDDateDisplayCell.h create mode 100644 PDDateDisplayCell.m create mode 100644 PDFavorite.h create mode 100644 PDFavorite.m create mode 100644 PDFavoritesBar.h create mode 100644 PDFavoritesBar.m create mode 100644 PDFileInfoView.h create mode 100644 PDFileInfoView.m create mode 100644 PDFontDisplay.h create mode 100644 PDFontDisplay.m create mode 100644 PDFontPreview.h create mode 100644 PDFontPreview.m create mode 100644 PDGradientView.h create mode 100644 PDGradientView.m create mode 100644 PDHorizontallyCenteredText.h create mode 100644 PDHorizontallyCenteredText.m create mode 100644 PDInvisibleButton.h create mode 100644 PDInvisibleButton.m create mode 100644 PDInvisibleButtonCell.h create mode 100644 PDInvisibleButtonCell.m create mode 100644 PDMatrixButton.h create mode 100644 PDMatrixButton.m create mode 100644 PDMatrixButtonCell.h create mode 100644 PDMatrixButtonCell.m create mode 100644 PDMediaBar.h create mode 100644 PDMediaBar.m create mode 100644 PDMediabarItem.h create mode 100644 PDMediabarItem.m create mode 100644 PDOutlineView.h create mode 100644 PDOutlineView.m create mode 100644 PDPhotoView.h create mode 100644 PDPhotoView.m create mode 100644 PDPopUpButton.h create mode 100644 PDPopUpButton.m create mode 100644 PDPopUpButtonCell.h create mode 100644 PDPopUpButtonCell.m create mode 100644 PDPopUpButtonToolbarItem.h create mode 100644 PDPopUpButtonToolbarItem.m create mode 100644 PDPopUpButtonToolbarItemCell.h create mode 100644 PDPopUpButtonToolbarItemCell.m create mode 100644 PDPredicateBuilder.h create mode 100644 PDPrintTextView.h create mode 100644 PDPrintTextView.m create mode 100644 PDRankCell.h create mode 100644 PDRankCell.m create mode 100644 PDSelfValidatingToolbarItem.h create mode 100644 PDSelfValidatingToolbarItem.m create mode 100644 PDStylesButton.h create mode 100644 PDStylesButton.m create mode 100644 PDStylesButtonCell.h create mode 100644 PDStylesButtonCell.m create mode 100644 PDTableView.h create mode 100644 PDTableView.m create mode 100644 PDTabsView.h create mode 100644 PDTabsView.m create mode 100644 PDTokenField.h create mode 100644 PDTokenField.m create mode 100644 PDTokenFieldCell.h create mode 100644 PDTokenFieldCell.m create mode 100644 PDToolbar.h create mode 100644 PDToolbar.m create mode 100644 PDURLTextField.h create mode 100644 PDURLTextField.m create mode 100644 PDURLTextFieldCell.h create mode 100644 PDURLTextFieldCell.m create mode 100644 PDURLTextFieldFileDefault.png create mode 100644 PDURLTextFieldWebDefault.tiff create mode 100644 PolishedWindow.h create mode 100644 PolishedWindow.m create mode 100644 PreviewBarSmall.png create mode 100644 QTBarSmall.png create mode 100644 RBSplitSubview.h create mode 100644 RBSplitSubview.m create mode 100644 RBSplitView.h create mode 100644 RBSplitView.m create mode 100644 RBSplitViewPrivateDefines.h create mode 100644 README create mode 100644 Read Me.rtf create mode 100644 Reload.tif create mode 100644 ReloadPressed.tif create mode 100644 RevealInFinderBarSmall.png create mode 100644 RoundedView.h create mode 100644 RoundedView.m create mode 100644 RoundedViewWhiteText.h create mode 100644 RoundedViewWhiteText.m create mode 100644 SafariBarSmall.png create mode 100644 Smaller.png create mode 100644 SmallerDisabled.png create mode 100644 SmallerPressed.png create mode 100644 Sprouted Interface.xcodeproj/phildow.mode1 create mode 100644 Sprouted Interface.xcodeproj/project.pbxproj create mode 100644 Sprouted Interface_Prefix.pch create mode 100644 SproutedAboutBoxController.h create mode 100644 SproutedAboutBoxController.m create mode 100644 SproutedAnchoredDocumentView.h create mode 100644 SproutedAnchoredDocumentView.m create mode 100644 SproutedInterface.h create mode 100644 StatsController.h create mode 100644 StatsController.m create mode 100644 Stop.tif create mode 100644 StopPressed.tif create mode 100644 TextEditBarSmall.png create mode 100644 TransparentWindow.h create mode 100644 TransparentWindow.m create mode 100644 Version History.rtf create mode 100644 WordBarSmall.png create mode 100644 da.lproj/FileInfo.strings create mode 100644 da.lproj/InfoPlist.strings create mode 100644 da.lproj/InsertLink.nib/classes.nib create mode 100644 da.lproj/InsertLink.nib/info.nib create mode 100644 da.lproj/InsertLink.nib/keyedobjects.nib create mode 100644 da.lproj/IntegrationFileCopy.nib/classes.nib create mode 100644 da.lproj/IntegrationFileCopy.nib/info.nib create mode 100644 da.lproj/IntegrationFileCopy.nib/keyedobjects.nib create mode 100644 da.lproj/Mediabar.strings create mode 100644 da.lproj/NewMediabarItem.nib/classes.nib create mode 100644 da.lproj/NewMediabarItem.nib/info.nib create mode 100644 da.lproj/NewMediabarItem.nib/keyedobjects.nib create mode 100644 da.lproj/PDFavoritesBar.strings create mode 100644 da.lproj/PDFontPreview.strings create mode 100644 da.lproj/PDTabsView.strings create mode 100644 da.lproj/SproutedAboutBox.nib/classes.nib create mode 100644 da.lproj/SproutedAboutBox.nib/info.nib create mode 100644 da.lproj/SproutedAboutBox.nib/keyedobjects.nib create mode 100644 da.lproj/Stats.nib/classes.nib create mode 100644 da.lproj/Stats.nib/info.nib create mode 100644 da.lproj/Stats.nib/keyedobjects.nib create mode 100644 de.lproj/FileInfo.strings create mode 100644 de.lproj/InfoPlist.strings create mode 100644 de.lproj/InsertLink.nib/classes.nib create mode 100644 de.lproj/InsertLink.nib/data.dependency create mode 100644 de.lproj/InsertLink.nib/info.nib create mode 100644 de.lproj/InsertLink.nib/keyedobjects.nib create mode 100644 de.lproj/IntegrationFileCopy.nib/classes.nib create mode 100644 de.lproj/IntegrationFileCopy.nib/data.dependency create mode 100644 de.lproj/IntegrationFileCopy.nib/info.nib create mode 100644 de.lproj/IntegrationFileCopy.nib/keyedobjects.nib create mode 100644 de.lproj/Mediabar.strings create mode 100644 de.lproj/NewMediabarItem.nib/classes.nib create mode 100644 de.lproj/NewMediabarItem.nib/info.nib create mode 100644 de.lproj/NewMediabarItem.nib/keyedobjects.nib create mode 100644 de.lproj/PDFavoritesBar.strings create mode 100644 de.lproj/PDFontPreview.strings create mode 100644 de.lproj/PDTabsView.strings create mode 100644 de.lproj/SproutedAboutBox.nib/classes.nib create mode 100644 de.lproj/SproutedAboutBox.nib/info.nib create mode 100644 de.lproj/SproutedAboutBox.nib/keyedobjects.nib create mode 100644 de.lproj/Stats.nib/classes.nib create mode 100644 de.lproj/Stats.nib/info.nib create mode 100644 de.lproj/Stats.nib/keyedobjects.nib create mode 100644 flat_bottom_left.png create mode 100644 flat_bottom_middle.png create mode 100644 flat_bottom_right.png create mode 100644 flat_middle_left.png create mode 100644 flat_middle_right.png create mode 100644 flat_top_left.png create mode 100644 flat_top_middle.png create mode 100644 flat_top_right.png create mode 100644 hud_titlebar-close.tiff create mode 100644 iTunesBarSmall.png create mode 100644 labelall.tif create mode 100644 labelhover.tif create mode 100644 labelselected.tif create mode 100644 more.tif create mode 100644 tabcloseback.tif create mode 100644 tabclosebackdown.tif create mode 100644 tabclosebackroll.tif create mode 100755 tabclosefront.tif create mode 100755 tabclosefrontdown.tif create mode 100755 tabclosefrontroll.tif diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb549ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +*.pbxuser +*.mode1v3 +SproutedInterface.framework +SproutedUtilities.framework +build \ No newline at end of file diff --git a/ABBarSmall.png b/ABBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..acc681bda82d36a0322f5e0e2439638175060bec GIT binary patch literal 1381 zcmV-r1)BPaP)2LLm?|Q4a=G;zbT>{0}^M_C#Xh$qPph9=zzy7!!<@ zgHcI{2b4&N*n&bygKc5EZMWTa+s^EK&-lF4{TLvgjFUWhci(yE_xwJd-|rP^n&SU_ z#DxnNx_?wvMZLa;#zsSr!bnTf1PUKIVP*&DOBjWQ5JJ&)J-ztTMN256tO$WZp-{em zzgoS=N7J;fO-sOH=ydd2o4;W=>7@A5Km1!i}8^XQm={qlP_@3?!-ru2x;U2 zl8g|F#&{S}=)ourF?}YsR_9Y+-uyOY?iE7ZxBcSH^eqh&$4nYw2@|7e4E;k&Pg>zj*kq>YCK86pzfzs$< zY}aPc{QCyICxKdk(Z3htFTIE5=_&Z`x|A6dvjjym@&sv)AVn*PV7n;vvJ0_ws}JUp__XZ$m2%WkS%jA_;m$R@h9)!_Np> zu_Hypob-{Dmzzaz6nJll{2lU zqWpc3{pLGA@Q@afje@1=^BA3c6Nk@yh_%^Y;n_8I?l1!^!RjAHdC%k6Sh&LdHJ(?q zR4Pi2!1w*`ACBrQO#zi8rz2fqZvfs`y}in+Yi&|B>;GMdhX^``ldQVChzPU& nE_^sd(Khs7A0_7q{t;jR^cAXh7PVJe00000NkvXXu0mjf!E=LT literal 0 HcmV?d00001 diff --git a/ActualSize.png b/ActualSize.png new file mode 100644 index 0000000000000000000000000000000000000000..5d764c4e06b9cbace84cfae75fde6ca89b08ca38 GIT binary patch literal 948 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 literal 0 HcmV?d00001 diff --git a/AppleScriptActionBarSmall.png b/AppleScriptActionBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..8853c207c6646d9f47324f8d626ec8f3118479e0 GIT binary patch literal 937 zcmV;a16KTrP);J%qpqV5u(M_$^qmHZhpEA~8nUp>B-vk+7(; zL_&iIR49~6C~YaUP)f&hE}hBHFvWPAleV{Wf9LT(=T_1*4ZI{t!szJegGeNDzf>xn z@IG6mQZe4k<+4;P7Aw(c^zHikdK8x|od+F2OP-pVdQSi?m&zGCBcDGM8yqFu+1Z(4yzF+nIx#Wv z!sqiTv$M0$FLNN9zev@R=w`Fo3{w;Zjg5^A6~8&1PE1cvKOGqvd3YsQmgRGk}4#u0!0 z`~|7x4ni%hSY2B~>d!7Y3E+sjh8?qz4Gj%YRh1o8s`^_;%+W0VSj6|}H`pi|2C$$$ zuZM(l!A9lJXAj^D`o%dGmmOG&$53*7W(OR#$K%03Btm(SpaiE8MmC#6Y + +@interface AppleScriptAlert : NSWindowController +{ + IBOutlet NSTextView *errorView; + IBOutlet NSTextView *sourceView; + + id source; + id error; +} + +- (id) initWithSource:(id)source error:(id)error; + +@end diff --git a/AppleScriptAlert.m b/AppleScriptAlert.m new file mode 100644 index 0000000..81d3d82 --- /dev/null +++ b/AppleScriptAlert.m @@ -0,0 +1,66 @@ +// +// AppleScriptAlert.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation AppleScriptAlert + +- (id) initWithSource:(id)theSource error:(id)theError +{ + if ( self = [super initWithWindowNibName:@"AppleScriptAlert"] ) + { + source = [theSource retain]; + error = [theError retain]; + + [self retain]; + } + + return self; +} + +- (void) windowDidLoad +{ + if ( [source isKindOfClass:[NSString class]] ) + [sourceView setString:source]; + + else if ( [source isKindOfClass:[NSAttributedString class]] ) + { + [[sourceView textStorage] beginEditing]; + [[sourceView textStorage] setAttributedString:source]; + [[sourceView textStorage] endEditing]; + } + + if ( error == nil ) + [errorView setString:[NSString string]]; + else + [errorView setString:[error description]]; +} + +- (void) dealloc +{ + [source release]; + [error release]; + + [super dealloc]; +} + +- (void) windowWillClose:(NSNotification*)aNotification +{ + [self autorelease]; +} + +#pragma mark - + +- (IBAction) showWindow:(id)sender +{ + [[self window] center]; + [super showWindow:sender]; +} + +@end diff --git a/Back.tif b/Back.tif new file mode 100644 index 0000000000000000000000000000000000000000..19bb116eba8998477e729b934a18fde06f29869a GIT binary patch literal 1304 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 literal 0 HcmV?d00001 diff --git a/BiggerDisabled.png b/BiggerDisabled.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa0ce95d80510d80290cf10bc7ab1c67d3dfad5 GIT binary patch literal 660 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 O0000 + +@interface CollectionManagerView : NSView +{ + BOOL bordered; + int numConditions; +} + +- (int) numConditions; +- (void) setNumConditions:(int)num; + +- (BOOL) bordered; +- (void) setBordered:(BOOL)drawsBorder; + +@end \ No newline at end of file diff --git a/CollectionManagerView.m b/CollectionManagerView.m new file mode 100644 index 0000000..e3f6fb9 --- /dev/null +++ b/CollectionManagerView.m @@ -0,0 +1,80 @@ + +// +// CollectionManagerView.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation CollectionManagerView + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) { + // Add initialization code here + bordered = YES; + } + return self; +} + +#pragma mark - + +- (int) numConditions +{ + return numConditions; +} + +- (void) setNumConditions:(int)num +{ + numConditions = num; +} + +- (BOOL) bordered +{ + return bordered; +} + +- (void) setBordered:(BOOL)drawsBorder +{ + bordered = drawsBorder; +} + +#pragma mark - + +- (BOOL) isFlipped +{ + return YES; +} + +- (void)drawRect:(NSRect)rect +{ + int i; + NSRect bds = [self bounds]; + + for ( i = 0; i < [self numConditions]; i++ ) + { + if ( i % 2 == 0 ) + { + [[NSColor whiteColor] set]; + NSRectFillUsingOperation(NSMakeRect( 0, (kConditionViewHeight*i), bds.size.width, kConditionViewHeight), NSCompositeSourceOver); + } + else + { + [[[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:1] set]; + NSRectFillUsingOperation(NSMakeRect( 0, (kConditionViewHeight*i), bds.size.width, kConditionViewHeight), NSCompositeSourceOver); + } + } + + if ( [self bordered] ) + { + [[NSColor lightGrayColor] set]; + NSFrameRect(bds); + } +} + +@end diff --git a/ComposeMailBarSmall.png b/ComposeMailBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..b1a4fb17e47a58afdb92981f93ff72f5eb5bdb28 GIT binary patch literal 1195 zcmV;c1XTNpP)@SuICrlv3&F<}+o;uQl5!*xK_ZbrPfw2oFBDecazm{7`26ed@ZjVLBvV5&7{YKp zzwC*CNE@T%I3VT`LkC5#F(xG-;7X-J%;Yy6q;*3$%dE^mt1RK8k1f=k62`|yVMYuQ zkSm#%#gh_-)Murt3uUyZq#$|72$-1Eo$1Ks3b2gdu|GP8*xV_M9X*7>p&=2FCzarW zMY-lR&2WS#Vn9L>cyDiS^D;vTAm<#%Lq2x_JM=vM_;Cq|)B!yH#FIiAF4t*)ATS8C z$$%h~(I6d_DMn-@RW_GKoL_{OF5sudJW>yz#2tw)DP4GkF^m7=nmg#_2r%cz!$nDhG4w{Hx&><#1#d3l(Csf~~+ z2C`ln?ME{B?2`}VG-qHAtoAMZ+EwBA>l~de@kR=LIu(2nuXE4~t3%KZe13cJY;i~jB2dB#w+;F1>Av&zWdFbc z3S2l)^Q@t7xLt*7Rz>1B9MCtrw*2QzHuu+iw5|@?4bvO#gN0g2dp~S<5GV(YCmHEk zCeuPp6uAB$&5&*2APlUW@sN{1+n~#8ZFAVbLAz8zo8eyp1^|eeinGpMdUgN+002ov JPDHLkV1n(TIx+wN literal 0 HcmV?d00001 diff --git a/ConditionController.h b/ConditionController.h new file mode 100644 index 0000000..34d4dd0 --- /dev/null +++ b/ConditionController.h @@ -0,0 +1,98 @@ +// +// ConditionController.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define kConditionViewHeight 26 + +#define PDConditionContains 0 +#define PDConditionNotContains 1 +#define PDConditionBeginsWith 2 +#define PDConditionEndsWith 3 +#define PDConditionIs 4 + +#define PDConditionBefore 0 +#define PDConditionAfter 1 +#define PDConditionBetween 2 +#define PDConditionInTheLast 3 +#define PDConditionInTheNext 4 + +#define PDConditionDay 0 +#define PDConditionWeek 1 +#define PDConditionMonth 2 + +@interface ConditionController : NSObject +{ + IBOutlet NSView *conditionView; + IBOutlet NSView *specifiedConditionView; + IBOutlet NSPopUpButton *keyPop; + + IBOutlet NSButton *removeButton; + + int tag; + id target; + + BOOL _allowsEmptyCondition; + BOOL _autogeneratesDynamicDates; + BOOL _sendsLiveUpdate; + +} + +- (id) initWithTarget:(id)anObject; +- (void) setInitialPredicate:(NSPredicate*)aPredicate; +- (void) setInitialCondition:(NSString*)condition; + +- (NSView*) conditionView; +- (NSPredicate*) predicate; +- (NSString*) predicateString; + +- (int) tag; +- (void) setTag:(int)newTag; + +- (id) target; +- (void) setTarget:(id)anObject; + +- (BOOL) sendsLiveUpdate; +- (void) setSendsLiveUpdate:(BOOL)updates; + +- (BOOL) autogeneratesDynamicDates; +- (void) setAutogeneratesDynamicDates:(BOOL)autogenerate; + +- (BOOL) allowsEmptyCondition; +- (void) setAllowsEmptyCondition:(BOOL)allowsEmpty; + +- (BOOL) removeButtonEnabled; +- (void) setRemoveButtonEnabled:(BOOL)enabled; + +- (IBAction) addCondition:(id)sender; +- (IBAction) removeCondition:(id)sender; +- (IBAction) changeCondition:(id)sender; +- (IBAction) changeConditionKey:(id)sender; + +- (id) selectableView; +- (void) appropriateFirstResponder:(NSWindow*)aWindow; +- (void) removeFromSuper; + +- (void) _sendUpdateIfRequested; + +// utility for creating spotlight based conditions - subclasses feel free to use +- (NSString*) _spotlightConditionStringWithAttribute:(NSString*)anAttribute condition:(NSString*)aCondition operation:(int)anOperation; +- (NSString*) _spotlightConditionStringWithAttributes:(NSArray*)theAttributes condition:(NSString*)aCondition operation:(int)anOperation; + +- (BOOL) validatePredicate; +@end + + +#pragma mark - + +@interface NSObject (ConditionControllerDelegate) + +- (void) conditionDidChange:(id)condition; + +@end \ No newline at end of file diff --git a/ConditionController.m b/ConditionController.m new file mode 100644 index 0000000..e8a4f1b --- /dev/null +++ b/ConditionController.m @@ -0,0 +1,384 @@ + +// +// ConditionController.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation ConditionController + +- (id) initWithTarget:(id)anObject { + + if ( self = [super init] ) { + + //[NSBundle loadNibNamed:@"Condition" owner:self]; + + target = anObject; + tag = 0; + + _sendsLiveUpdate = YES; + _allowsEmptyCondition = NO; + _autogeneratesDynamicDates = NO; + } + + return self; +} + +- (void) dealloc { + + [conditionView release]; + conditionView = nil; + + [super dealloc]; + +} + +- (void) awakeFromNib +{ + +} + +#pragma mark - + +- (NSView*) conditionView +{ + return conditionView; +} + +#pragma mark - + +- (int) tag +{ + return tag; +} + +- (void) setTag:(int)newTag +{ + tag = newTag; +} + +- (id) target +{ + return target; +} + +- (void) setTarget:(id)anObject +{ + target = anObject; +} + +- (BOOL) sendsLiveUpdate +{ + return _sendsLiveUpdate; +} + +- (void) setSendsLiveUpdate:(BOOL)updates +{ + _sendsLiveUpdate = updates; +} + +- (BOOL) autogeneratesDynamicDates +{ + return _autogeneratesDynamicDates; +} + +- (void) setAutogeneratesDynamicDates:(BOOL)autogenerate +{ + _autogeneratesDynamicDates = autogenerate; +} + +- (BOOL) allowsEmptyCondition +{ + return _allowsEmptyCondition; +} + +- (void) setAllowsEmptyCondition:(BOOL)allowsEmpty +{ + _allowsEmptyCondition = allowsEmpty; +} + +- (BOOL) removeButtonEnabled +{ + return [removeButton isEnabled]; +} + +- (void) setRemoveButtonEnabled:(BOOL)enabled +{ + [removeButton setEnabled:enabled]; +} + +#pragma mark - + +- (void)controlTextDidChange:(NSNotification *)aNotification +{ + [self _sendUpdateIfRequested]; +} + +- (IBAction) changeCondition:(id)sender +{ + [self _sendUpdateIfRequested]; +} + +- (void) _sendUpdateIfRequested +{ + if ( [self sendsLiveUpdate] && [target respondsToSelector:@selector(conditionDidChange:)] ) + [target conditionDidChange:self]; +} + +#pragma mark - + +- (void) setInitialPredicate:(NSPredicate*)aPredicate +{ + // + // used to reproduce the saved condition + [self setInitialCondition:[aPredicate predicateFormat]]; +} + +- (void) setInitialCondition:(NSString*)condition +{ + + // + // used to reproduce the saved condition + +} + +- (NSPredicate*) predicate +{ + // + // derive a predicate from the specified condition + NSString *predicateString = [self predicateString]; + return ( predicateString != nil ? [NSPredicate predicateWithFormat:predicateString] : nil ); +} + +- (NSString*) predicateString { + + // + // build the predicate string from our current conditions + return nil; +} + +#pragma mark - + +- (IBAction)addCondition:(id)sender +{ + if ( [target respondsToSelector:@selector(addCondition:)] ) + [target performSelector:@selector(addCondition:) withObject:self]; + //[self _sendUpdateIfRequested]; +} + +- (IBAction)removeCondition:(id)sender +{ + if ( [target respondsToSelector:@selector(removeCondition:)] ) + [target performSelector:@selector(removeCondition:) withObject:self]; + //[self _sendUpdateIfRequested]; +} + +- (IBAction)changeConditionKey:(id)sender +{ + // + // remove and add superviews as needed + [self _sendUpdateIfRequested]; +} + +- (id) selectableView +{ + // + // return the a responder that may become first responder + return nil; +} + +- (void) appropriateFirstResponder:(NSWindow*)aWindow +{ + // should depend on the condition +} + +- (void) removeFromSuper +{ + [conditionView removeFromSuperviewWithoutNeedingDisplay]; +} + +#pragma mark - + +- (NSString*) _spotlightConditionStringWithAttribute:(NSString*)anAttribute condition:(NSString*)aCondition operation:(int)anOperation +{ + // handy utility method for creating text based spotlight conditions + + NSString *predicateString = nil; + NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"\"'"]; + + if ( [aCondition length] == 0 ) + { + if ( _allowsEmptyCondition == NO ) + return nil; + else if ( anOperation == PDConditionNotContains ) + predicateString = [NSString stringWithFormat:@"%@ != \"%@\"", anAttribute, @"^"]; + else + predicateString = [NSString stringWithFormat:@"%@ == %@", anAttribute, @"^"]; + } + + else if ( [aCondition rangeOfCharacterFromSet:charSet].location != NSNotFound ) + return nil; + + switch ( anOperation ) + { + + case PDConditionContains: + predicateString = [NSString stringWithFormat:@"%@ like[cd] \"*%@*\"", anAttribute, aCondition]; + break; + + case PDConditionNotContains: + predicateString = [NSString stringWithFormat: @"not %@ like[cd] \"*%@*\"", anAttribute, aCondition]; + break; + + case PDConditionBeginsWith: + predicateString = [NSString stringWithFormat:@"%@ like[cd] \"%@*\"", anAttribute, aCondition]; + break; + + case PDConditionEndsWith: + predicateString = [NSString stringWithFormat:@"%@ like[cd] \"*%@\"", anAttribute, aCondition]; + break; + + case PDConditionIs: + //predicateString = [NSString stringWithFormat:@"%@ ==[cd] \"%@\"", anAttribute, aCondition]; + predicateString = [NSString stringWithFormat:@"%@ like[cd] \"%@\"", anAttribute, aCondition]; + break; + + } + + return predicateString; +} + +- (NSString*) _spotlightConditionStringWithAttributes:(NSArray*)theAttributes condition:(NSString*)aCondition operation:(int)anOperation +{ + NSMutableArray *theStrings = [NSMutableArray array]; + + NSString *predicateString = nil; + NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"\"'"]; + + NSString *anAttribute; + NSEnumerator *enumerator = [theAttributes objectEnumerator]; + + while ( anAttribute = [enumerator nextObject] ) + { + NSString *aPredicateString = nil; + + if ( [aCondition length] == 0 ) + { + if ( _allowsEmptyCondition == NO ) + return nil; + else if ( anOperation == PDConditionNotContains ) + aPredicateString = [NSString stringWithFormat:@"%@ != \"%@\"", anAttribute, @"^"]; + else + aPredicateString = [NSString stringWithFormat:@"%@ == %@", anAttribute, @"^"]; + } + + else if ( [aCondition rangeOfCharacterFromSet:charSet].location != NSNotFound ) + return nil; + + switch ( anOperation ) + { + + case PDConditionContains: + aPredicateString = [NSString stringWithFormat:@"%@ like[cd] \"*%@*\"", anAttribute, aCondition]; + break; + + case PDConditionNotContains: + aPredicateString = [NSString stringWithFormat: @"not %@ like[cd] \"*%@*\"", anAttribute, aCondition]; + break; + + case PDConditionBeginsWith: + aPredicateString = [NSString stringWithFormat:@"%@ like[cd] \"%@*\"", anAttribute, aCondition]; + break; + + case PDConditionEndsWith: + aPredicateString = [NSString stringWithFormat:@"%@ like[cd] \"*%@\"", anAttribute, aCondition]; + break; + + case PDConditionIs: + //aPredicateString = [NSString stringWithFormat:@"%@ ==[cd] \"%@\"", anAttribute, aCondition]; + aPredicateString = [NSString stringWithFormat:@"%@ like[cd] \"%@\"", anAttribute, aCondition]; + break; + + } + + if ( aPredicateString != nil ) + [theStrings addObject:aPredicateString]; + + } + + // put them all together + if ( [aCondition length] == 0 ) + predicateString = [theStrings componentsJoinedByString:@" && "]; + else if ( anOperation == PDConditionNotContains ) + predicateString = [theStrings componentsJoinedByString:@" && "]; + else + predicateString = [theStrings componentsJoinedByString:@" || "]; + + return predicateString; + +} + +- (BOOL) validatePredicate +{ + NSLog(@"%@ %s - subclasses must override to validate their own predicate formats", [self className], _cmd); + return NO; +} + +/* +if ( [[stringConditionValue stringValue] length] == 0 ) +{ + if ( _allowsEmptyCondition == NO ) + return nil; + else if ( [[stringOperationPop selectedItem] tag] == PDConditionNotContains ) + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses != \"%@\" && kMDItemAuthors != \"%@\"", @"^", @"^"]; + else + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses == %@ && kMDItemAuthors == %@", @"^", @"^"]; +} + +else if ( [[stringConditionValue stringValue] rangeOfCharacterFromSet:charSet].location != NSNotFound ) + return nil; + +switch ( [[stringOperationPop selectedItem] tag] ) +{ + +case PDConditionContains: + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses like[cd] \"*%@*\" || kMDItemAuthors like[cd] \"*%@*\"", + [stringConditionValue stringValue], [stringConditionValue stringValue]]; + break; + +case PDConditionNotContains: + predicateString = [NSString stringWithFormat: + @"not kMDItemAuthorEmailAddresses like[cd] \"*%@*\" && not kMDItemAuthors like[cd] \"*%@*\"", + [stringConditionValue stringValue], [stringConditionValue stringValue]]; + break; + +case PDConditionBeginsWith: + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses like[cd] \"%@*\" || kMDItemAuthors like[cd] \"%@*\"", + [stringConditionValue stringValue], [stringConditionValue stringValue]]; + break; + +case PDConditionEndsWith: + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses like[cd] \"*%@\" || kMDItemAuthors like[cd] \"*%@\"", + [stringConditionValue stringValue], [stringConditionValue stringValue]]; + break; + +case PDConditionIs: + predicateString = [NSString stringWithFormat: + @"kMDItemAuthorEmailAddresses ==[cd] \"%@\" || kMDItemAuthors ==[cd] \"%@\"", + [stringConditionValue stringValue], [stringConditionValue stringValue]]; + break; + +} + */ + +@end diff --git a/CustomFindPanel.h b/CustomFindPanel.h new file mode 100644 index 0000000..b5eb9e1 --- /dev/null +++ b/CustomFindPanel.h @@ -0,0 +1,17 @@ +// +// CustomFindPanel.h +// SproutedInterface +// +// Created by Philip Dow on 1/7/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface CustomFindPanel : NSWindow { + +} + +@end diff --git a/CustomFindPanel.m b/CustomFindPanel.m new file mode 100644 index 0000000..054ae5c --- /dev/null +++ b/CustomFindPanel.m @@ -0,0 +1,28 @@ +// +// CustomFindPanel.m +// SproutedInterface +// +// Created by Philip Dow on 1/7/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation CustomFindPanel + +- (BOOL)canBecomeMainWindow +{ + return NO; +} + +- (void)keyDown:(NSEvent *)theEvent +{ + if ( [theEvent keyCode] == 53 ) + [self close]; + else + [super keyDown:theEvent]; +} + +@end diff --git a/Display.png b/Display.png new file mode 100644 index 0000000000000000000000000000000000000000..9e70cc07e0064da938f76133df77ca652a86d87d GIT binary patch literal 1008 zcmVX1^@s6BEU{300004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#f=NU{RCwC7 zR?kZ#F%*88%v7yK6qXim-qu5lCsD9f);~hb&Zk}u!On`9VRX>)TkY*x&9VDJg6A22ic zw`5|@;Cr8OwlOz1_Z{S<%U_mP^TqtabN1O=EES=Z$zyn+)7P16_q4CCd|g>$i;Ii% zjIp&)C}aeKLGb(iEhS8+(~wLi;o{<=gw@Y_TU*;qe}BI*K0XfrBLxBhkqd=_aeI3^ zqdh!4d<+Id=v!9vFT)aZt%RB_e9vlcwX;?WgF2iwiyUv^=;`b01LD$ixtu2u@H-}% zo}PAH@%Hw%gY-=-mer~W9UUD&TzXBE9gtH~Q?R?c>pIEA#02c@?EDq>>FEjb`GRQE zB%#c*etdi^vTT=jJ^nq|QmF*lUs=#~F6yro$}~DU>RNBaH^V+YJ_3Gnz_liXR6jgC zgt4(PQOZR1M!XwVl9D>kb#;okDwLDUvT;Gpu+?f6US3{=%`I2TZ%>fX-U&j^g+iV4_bH@4au0^I>dRy@%BJ?g!9j;j3N=lu5$O8+6w->R ztW+v+aBu*L#1D0z(}a|z+IT#!RG*%niYy5Y1JxOZB6d|6iA3l)f^xYGLqkJ#7Xa;x z9RxJ-$jFH56}D;LHC#gqW;gtikVr_C+$Wmk$dHgu`6P$;&bg2pgrdc2+ z9|x8c(qc@9OGy<5N4Z>rSTqWglasFJV-)+vO@NDz#@@ijV!-6rV;Q<7Nw`t02tQOh z<&`|M-mGhAxDm{zx1xQm>0Yn5cz2ibba!{7e9a0*CzGsc7AXxD@nk7A@kJ%GJ3u&* zStZVQpS}m;(t3J&uFuYXip{6};27qdYa$ZKrm$zi=4f+kPq@HnM97)K(Rji#H4gh2 zjbV_yyaeLXySlo*U0q$R;fHJt3=D|h0XtgQt6w)(-^c3DS9ldPuQkV>Vz*=)9@|1>_I4|;ohb4a#6J3G6i7L-UN!szpPG+X;$3b2m{$j0#S eu=p?iEx-WOA#%OEAEg@r0000X1^@s6BEU{300009a7bBm000XU z000XU0RWnu7ytkYO=&|zP*7-ZbZ>KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde00d`2O+f$vv5tKEQIh}w03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(` z>RI+y?e7jKeZ#YO-C1U^YbK~#9!jF#VP6jv0-Kj+>%JDbf9Yuiv-6kCd=A~YMa z`seuOgU}F4eF#2TL`hMx5FvtZ{x{LZT~VJb7HbMMqzUH7tUH;R(}$V4GaF;{JnYWB z_uTWn=l2l`x_|%vEoa>&7r2%YL!A^w5RM{65fRX8t*RtR5+zBpa`EED%Rnw=X=&-T zh@6O`h&YZB5ma?VphymQaKCaq*;FyLPQ-tZN_t;wz4SIZd-Q zjvy#?!MT23-~nap{G}zz^}A?~&5d=oHr|k>NzYAAPR@j_V|;V!J8zC$y3_>LUM#+V$ikR=AhZ$RlDQOF8^iAdoquqH>& z6vPOsP>NIq*PLMc&4#!rikO_5D$J1ouH5mqi?vG49=2I+E7_NtzO;Fc=JQ zB7(6dw~PwQx39Cjy!=5S^Yin}|9S-l?%uxfao)>U*nGRgaDN|F#Q->KF~(w?@xJQy zdOUvo*qg4`>-osD&SIVWB;Ghl+1`n0G#UUn0Bc>IM_L8P+}zyAYwK%cDx-dk_wDvB z`$_5Onlcy+0CH2R`us5>g0&WB9nRX3S9iNzj4^b(UGJY9&=Hu*DkU$#>gp;{ z6fqnQJzyAygv~~!p$lA*eBuGmpFdyt%h2g`*xlXr0M=S4@b>ohICJLA$aj`yd0qp} zuz_k`i$$c0Qs+iBeDvrM#u$<$;o-xFJbn7q1FrqM!P=XRJkhg^Cr_S`Wf@tP@$A_% zoWg)|-KO8~({8tOz@Sk}5ktS<_v?eaVWUyh)w~?$QR?hSB*k&; zFO)PpJ6mb!f{`e#pS{N$1S4%NPkdt$f#}`P3n?S=FbW!hw?^r!qj<|gt*T|>8{++x zI7zvB^DYYuKYvibZ#S2H>$rMznT3VvvZ2wku^Ts(PVF%~PdGTdfwGoB!d$30x7ab!)0pOf>2R=)tC6Zb&g1Pyv(= z+1}cs)oS6!$H(>MpD*OcpXQ2t)sWzuv43d}?56?A(NzieY>^EtCufW|L1SQFzgG!g9i^@ z4~N4O>+9 + +extern NSString *kSproutedAppHelperURL; +extern NSString *kSproutedAppHelperFlags; +extern NSString *kSproutedAppHelperMetadata; +extern NSString *kSproutedAppHelperIcon; +extern NSString *kSproutedAppHelperEntityName; + +@interface DocumentMakerController : NSObject { + + id delegate; + id representedObject; + + NSManagedObjectContext *managedObjectContext; +} + +- (id) initWithOwner:(id)anObject managedObjectContext:(NSManagedObjectContext*)moc; + +- (int) numberOfViews; +- (NSView*) contentViewAtIndex:(int)index; +- (void) willSelectViewAtIndex:(int)index; +- (void) didSelectViewAtIndex:(int)index; +- (NSString*) titleOfViewAtIndex:(int)index; + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (NSManagedObjectContext*) managedObjectContext; +- (void) setManagedObjectContext:(NSManagedObjectContext*)moc; + +- (id) representedObject; +- (void) setRepresentedObject:(id)anObject; + +- (NSArray*) documentDictionaries:(NSError**)error; + +@end diff --git a/DocumentMakerController.m b/DocumentMakerController.m new file mode 100644 index 0000000..4aab1db --- /dev/null +++ b/DocumentMakerController.m @@ -0,0 +1,148 @@ +// +// DocumentMakerController.m +// SproutedInterface +// +// Created by Philip Dow on 9/28/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation DocumentMakerController + +- (id) init +{ + return [self initWithOwner:nil managedObjectContext:nil]; +} + +- (id) initWithOwner:(id)anObject managedObjectContext:(NSManagedObjectContext*)moc +{ + if ( self = [super init] ) + { + // subclasses should call super's implementation + [self setDelegate:anObject]; + [self setManagedObjectContext:moc]; + } + return self; +} + +- (void) dealloc +{ + // local variables + [representedObject release]; + [managedObjectContext release]; + + [super dealloc]; +} + +#pragma mark - + +- (int) numberOfViews +{ + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return 0; + + // subclasses must override and return the number of views/steps + // invovled in creating this particular kind of document +} + +- (NSView*) contentViewAtIndex:(int)index +{ + // subclasses should override and return the content view for the given index + // this allows subclasses to walk the user through + // the custom creation of a document however they see fit. + // the index is 1 based. 0 is where the user choose the kind of + // document they want to create. + + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return nil; +} + +- (void) willSelectViewAtIndex:(int)index +{ + // subclasses may override to perform setup + // before the view at index is display + // index is 1 based + + return; +} + +- (void) didSelectViewAtIndex:(int)index +{ + // subclasses may override to perform postprocessing + // for example setting the new first responder, + // which is recommended. + // index is 1 based + + return; +} + +- (NSString*) titleOfViewAtIndex:(int)index +{ + // subclasses must override to provide a localized + // description for the name of the view at index. + // index is one based. + + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return [NSString string]; +} + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (NSManagedObjectContext*) managedObjectContext +{ + return managedObjectContext; +} + +- (void) setManagedObjectContext:(NSManagedObjectContext*)moc +{ + if ( managedObjectContext != moc ) + { + [managedObjectContext release]; + managedObjectContext = [moc retain]; + } +} + +- (id) representedObject +{ + return representedObject; +} + +- (void) setRepresentedObject:(id)anObject +{ + if ( representedObject != anObject ) + { + [representedObject release]; + representedObject = [anObject retain]; + } +} + +#pragma mark - + +- (NSArray*) documentDictionaries:(NSError**)error +{ + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return nil; + + // return an array of dictionaries describing how the pasteboard data + // should be handled by Lex. each dictionary should include + // 1. kSproutedAppHelperURL -> NSURL, uniformly and uniquely indicating the data + // 2. kSproutedAppHelperFlags -> NSNumber, a set of flags indicating how the + // data should be handled, eg "force copy" + // 3. kSproutedAppHelperMetadata -> NSDictionary, contains key-value pairs + // of Spotlight metadata attributes + // + // These keys are defined in the plugin framework +} + +@end diff --git a/DragView.h b/DragView.h new file mode 100644 index 0000000..6159db6 --- /dev/null +++ b/DragView.h @@ -0,0 +1,17 @@ +// +// DragView.h +// SproutedInterface +// +// Created by Philip Dow on 9/14/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface DragView : NSView { + +} + +@end diff --git a/DragView.m b/DragView.m new file mode 100644 index 0000000..cdd834d --- /dev/null +++ b/DragView.m @@ -0,0 +1,30 @@ +// +// DragView.m +// SproutedInterface +// +// Created by Philip Dow on 9/14/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation DragView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + } + return self; +} + +- (void)drawRect:(NSRect)rect { + // Drawing code here. +} + +- (BOOL)mouseDownCanMoveWindow { + return NO; +} + +@end diff --git a/EmailBarSmall.png b/EmailBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..11a905d3cb8ed910199bf2acd6c53c2a9825d056 GIT binary patch literal 1818 zcmV+#2j%#QP)(^i6@bCzZ;~<+&V|)88*493WKY9EF%gf8tA6%M@c6;4h zy4GuLKHGfp;`!DF-n;mVg(vU=o-o5OU|E*XYPJ38R4O-|7*5U2%`D%$_fh2AckkR? z`{bc-eqnB6uieTF1vfdH4|DxOj$PJn4)e2uY6POhNFijE*L)AN}xqtC47g zUt9axN8xZ}D4)+|eS#461%_CqW1!h_@a9BEtr-r#Di!hIPRf{_on3nScIU4{LqlIH z=x7==Rbzhl>97AdGd-KTdi7Gl=jWq>5Ek010lnu!k}YiR_E2xjXzL1WCIHK3!LkBe zLJ%!DHiVIpWGbCb1wuoi?*A2xPfenus;SFYE>GS5@czQ*8}FcWU9zx7!ddhz4vbF# zg9z%SEtpyp`RO|dg+j1x%Oe-vE}gSETwl7r^u@+zkUaQWfhbn!psnrh>>SQ6erw@H z(FGp}gX3t^$HFhTWGRofbb^VPjN!D6GrfYIF9gPMNra8A9rDzf=(I-AX2_4#~#3O(?#SgbGP-NE5k$EA`K8;T^Xss)=TtNRq3 zr*K_7Lco&2_)YY52LYFbWA?ldz@l?a#iq1|dwXShX*87tW#u_V>2$g;fYMpi)J`{@ z7=e4>z$D9P0}MmKAa}c#186Ov(?m@z;Mx@5_o7b`WmHW8B?QC9W0Clye?JNMd^}OZ zfG?Fw=UlPuUb%dHFfpCYO4Vc9Bf+i-ju$W#pCHSV_;OzlRsXrAQC&@BOhKoCm(6z$VDFv;@F=m;jp zvp78XJIW0M`T3tx3=A@cg<+aF5f$WenX&o#YjdV)KJ{vt_gccBWn`LGkDWJ4Y?BMBnk&pP{rHR0S+dimv4{ zDA&4(4kyCb7Z<0;$0sm3SpX4@C?P{QBAO=efA_=h3}>zdB_~hrYY@U21XHtQVhgG9 zMVvM|FdY^_ON8I5fJ@$h!}zE+Z1`9ccNda)y}e!f?6cqhtyny8JP#5CouGC)ox@~u zM7vywqk6oH3PF`?h>qO=cjXs|E&mdiZv7n1wgR1r<81G9w7&Wag@96;;?R(7=!T0} zERskj6M<+n(&s)%XnBF4c&OESW6y5Zd ze?T)>WRx9>Q=JsVs43d0G<7W9SeTDS!^3`muyZjFyi{VSC+RO=zTPcNPTd!HmukW2 z7n^0y=M`^DF!N4}Oe)Z7Kbi0_+*mX%)AYKLBGkFdCb} zM1BOLBXPFsJ&u2yUEe(~UqqNv6f>l@p>p3y3o%TK-jMUe{L7Ei=|M1vYdWi;xYg0cdmC8k$+cpXGN?v(Sm^=7o2CxPSoB_Oh zllkVK078r)4A$J>u;=c@81xOE^MgI}LfAm*g~I;0`=0;<0Qp^lU{d~USpWb407*qo IM6N<$f(_wv)&Kwi literal 0 HcmV?d00001 diff --git a/English.lproj/FileInfo.strings b/English.lproj/FileInfo.strings new file mode 100644 index 0000000..533e43e --- /dev/null +++ b/English.lproj/FileInfo.strings @@ -0,0 +1,10 @@ + +"mditem title name" = "Title"; +"mditem kind name" = "Kind"; +"mditem size name" = "Size"; +"mditem size kb" = "KB on disk"; +"mditem size mb" = "MB on disk"; +"mditem size gb" = "GB on disk"; +"mditem created name" = "Created"; +"mditem modified name" = "Modified"; +"mditem lastopened name" = "Last opened"; \ No newline at end of file diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..befb935928a91b7a4f445b0cd6df7a65ec416b4a GIT binary patch literal 210 zcmW-bO%B0O7)8(6D#Wl66%zw7Vn8Ayx`Lu;&^E0Sc4U({ZC>*I+;{JJ@AnM}=&~Yb zPt28+Hwg!|hrOgy$;s?p`_Z~|J30?2T7Sh|^`iULx&lHvo;48*YHo5fw%*5bV|Jzz uW)cb$rTi1;mNAvn<73^Zq%FO0o9lhjcZ$rEZnggAmyI@J=oy=w`05{6P$Z-P literal 0 HcmV?d00001 diff --git a/English.lproj/InsertLink.nib/classes.nib b/English.lproj/InsertLink.nib/classes.nib new file mode 100644 index 0000000..8687110 --- /dev/null +++ b/English.lproj/InsertLink.nib/classes.nib @@ -0,0 +1,17 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {genericCancel = id; genericOkay = id; }; + CLASS = LinkController; + LANGUAGE = ObjC; + OUTLETS = { + linkField = NSTextField; + objectController = NSObjectController; + urlField = NSTextField; + }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/English.lproj/InsertLink.nib/info.nib b/English.lproj/InsertLink.nib/info.nib new file mode 100644 index 0000000..cc50b92 --- /dev/null +++ b/English.lproj/InsertLink.nib/info.nib @@ -0,0 +1,14 @@ + + + + + IBDocumentLocation + 370 131 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBSystem Version + 8P2137 + + diff --git a/English.lproj/InsertLink.nib/keyedobjects.nib b/English.lproj/InsertLink.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..96ac6c59fee5aac190b1b4e26506dea5328ca3ba GIT binary patch literal 6972 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 + + + + IBDocumentLocation + 52 56 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBSystem Version + 8P2137 + + diff --git a/English.lproj/IntegrationFileCopy.nib/keyedobjects.nib b/English.lproj/IntegrationFileCopy.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..14cc8f76cf7149d0a66a0ab2d3b05bc5dfd54c22 GIT binary patch literal 4290 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 literal 0 HcmV?d00001 diff --git a/English.lproj/Mediabar.strings b/English.lproj/Mediabar.strings new file mode 100644 index 0000000..19992d5 --- /dev/null +++ b/English.lproj/Mediabar.strings @@ -0,0 +1,27 @@ + +"add item title" = "Add Custom Item…"; +"edit item title" = "Edit Custom Item…"; +"remove item title" = "Remove Custom Item…"; + +"get info title" = "Get Info"; +"get info tip" = "Useful information about the selected resource"; + +"reveal in finder title" = "Reveal"; +"reveal in finder tip" = "Show the selected resource in the Finder"; + +"open in finder title" = "Open"; +"open in finder tip" = "Open the selected resource with the default application"; +"open with tip" = "Open the selection with %@"; + +"address record show title" = "Show"; +"address record show tip" = "Open in Address Book"; + +"address record email title" = "Email"; +"address record email tip" = "Begin a new email to the sender"; + +"address record browse title" = "Browse"; +"address record browse tip" = "Browse the entry's associated web site"; + + +"mail message compose title" = "Compose"; +"mail message compose tip" = "Begin a new email to the sender"; \ No newline at end of file diff --git a/English.lproj/NewMediabarItem.nib/classes.nib b/English.lproj/NewMediabarItem.nib/classes.nib new file mode 100644 index 0000000..5d633ca --- /dev/null +++ b/English.lproj/NewMediabarItem.nib/classes.nib @@ -0,0 +1,36 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = JournlerGradientView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + { + CLASS = MediabarItemApplicationPicker; + LANGUAGE = ObjC; + OUTLETS = {delegate = id; }; + SUPERCLASS = JournlerGradientView; + }, + {CLASS = NSObject; LANGUAGE = ObjC; }, + { + ACTIONS = { + cancel = id; + chooseApplication = id; + help = id; + save = id; + verifyDraggedImage = id; + }; + CLASS = NewMediabarItemController; + LANGUAGE = ObjC; + OUTLETS = { + appImageView = NSImageView; + applicationField = MediabarItemApplicationPicker; + appnameField = NSTextField; + delegate = id; + objectController = NSObjectController; + representedObject = id; + scriptText = NSTextView; + titleField = NSTextField; + }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/English.lproj/NewMediabarItem.nib/info.nib b/English.lproj/NewMediabarItem.nib/info.nib new file mode 100644 index 0000000..7a21a01 --- /dev/null +++ b/English.lproj/NewMediabarItem.nib/info.nib @@ -0,0 +1,16 @@ + + + + + IBDocumentLocation + 69 14 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOpenObjects + + 5 + + IBSystem Version + 8P2137 + + diff --git a/English.lproj/NewMediabarItem.nib/keyedobjects.nib b/English.lproj/NewMediabarItem.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..9d5e4fb66ede43b74f767e07d6ca924341cc1684 GIT binary patch literal 12702 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 literal 0 HcmV?d00001 diff --git a/English.lproj/PDFavoritesBar.strings b/English.lproj/PDFavoritesBar.strings new file mode 100644 index 0000000..6bd7a9d --- /dev/null +++ b/English.lproj/PDFavoritesBar.strings @@ -0,0 +1,5 @@ +"Favorites Name" = "Favorite's Name:"; +"Cancel" = "Cancel"; +"OK" = "OK"; + +"draw labels" = "Draw Labels"; \ No newline at end of file diff --git a/English.lproj/PDFontPreview.strings b/English.lproj/PDFontPreview.strings new file mode 100644 index 0000000..49df2e7 --- /dev/null +++ b/English.lproj/PDFontPreview.strings @@ -0,0 +1 @@ +"set font title" = "Set Font…"; \ No newline at end of file diff --git a/English.lproj/PDTabsView.strings b/English.lproj/PDTabsView.strings new file mode 100644 index 0000000..b46dc01 --- /dev/null +++ b/English.lproj/PDTabsView.strings @@ -0,0 +1,4 @@ +"new tab" = "New Tab"; +"close tab" = "Close Tab"; +"close other tabs" = "Close Other Tabs"; +"close tab tip" = "Close this tab"; \ No newline at end of file diff --git a/English.lproj/SproutedAboutBox.nib/classes.nib b/English.lproj/SproutedAboutBox.nib/classes.nib new file mode 100644 index 0000000..41e769e --- /dev/null +++ b/English.lproj/SproutedAboutBox.nib/classes.nib @@ -0,0 +1,98 @@ + + + + + IBClasses + + + CLASS + PDGradientView + LANGUAGE + ObjC + SUPERCLASS + PDBorderedView + + + ACTIONS + + relaunch + id + + CLASS + NSApplication + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + PDBorderedView + LANGUAGE + ObjC + SUPERCLASS + NSView + + + CLASS + NSView + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + ACTIONS + + doSomething + id + showAboutBox + id + + CLASS + SproutedAboutBoxController + LANGUAGE + ObjC + OUTLETS + + aboutText + NSTextView + additionalText + NSTextView + appnameField + NSTextField + imageView + NSImageView + versionField + NSTextField + + SUPERCLASS + NSWindowController + + + CLASS + NSCell + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + IBVersion + 1 + + diff --git a/English.lproj/SproutedAboutBox.nib/info.nib b/English.lproj/SproutedAboutBox.nib/info.nib new file mode 100644 index 0000000..b5d3140 --- /dev/null +++ b/English.lproj/SproutedAboutBox.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + ../Journler.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + IBSystem Version + 9E17 + targetFramework + IBCocoaFramework + + diff --git a/English.lproj/SproutedAboutBox.nib/keyedobjects.nib b/English.lproj/SproutedAboutBox.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..2091f9b206ddaba98f413ee6210bfb24d7b7c3d1 GIT binary patch literal 7281 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 J=TrXl{{Y|Rn704` literal 0 HcmV?d00001 diff --git a/English.lproj/Stats.nib/classes.nib b/English.lproj/Stats.nib/classes.nib new file mode 100644 index 0000000..776d57c --- /dev/null +++ b/English.lproj/Stats.nib/classes.nib @@ -0,0 +1,14 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = PDGradientView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + { + ACTIONS = {genericStop = id; }; + CLASS = StatsController; + LANGUAGE = ObjC; + OUTLETS = {charsField = NSTextField; parsField = NSTextField; wordsField = NSTextField; }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/English.lproj/Stats.nib/info.nib b/English.lproj/Stats.nib/info.nib new file mode 100644 index 0000000..2999e87 --- /dev/null +++ b/English.lproj/Stats.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBDocumentLocation + 95 15 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBOpenObjects + + 5 + + IBSystem Version + 8P2137 + + diff --git a/English.lproj/Stats.nib/keyedobjects.nib b/English.lproj/Stats.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..5d976ec7ecbf663e2c94abd53fddbc22bf23d3df GIT binary patch literal 5727 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 + + +@interface EtchedPopUpButton : NSPopUpButton { + +} + ++ (Class)cellClass; +-(void)setShadowColor:(NSColor *)color; + +@end diff --git a/EtchedPopUpButton.m b/EtchedPopUpButton.m new file mode 100644 index 0000000..5f42cb9 --- /dev/null +++ b/EtchedPopUpButton.m @@ -0,0 +1,43 @@ + +/* EtchedPopUpButton */ +// NOTE TO SELF: where did this come from? + +#import +#import + +@implementation EtchedPopUpButton + ++ (Class)cellClass +{ + return [EtchedPopUpButtonCell class]; +} + +- initWithCoder: (NSCoder *)origCoder +{ + if(![origCoder isKindOfClass: [NSKeyedUnarchiver class]]){ + self = [super initWithCoder: origCoder]; + } else { + NSKeyedUnarchiver *coder = (id)origCoder; + + NSString *oldClassName = [[[self superclass] cellClass] className]; + Class oldClass = [coder classForClassName: oldClassName]; + if(!oldClass) + oldClass = [[super superclass] cellClass]; + [coder setClass: [[self class] cellClass] forClassName: oldClassName]; + self = [super initWithCoder: coder]; + [coder setClass: oldClass forClassName: oldClassName]; + + [self setShadowColor:[NSColor whiteColor]]; + } + + return self; +} + +-(void)setShadowColor:(NSColor *)color +{ + EtchedPopUpButtonCell *cell = [self cell]; + [cell setShadowColor:color]; +} + + +@end diff --git a/EtchedPopUpButtonCell.h b/EtchedPopUpButtonCell.h new file mode 100644 index 0000000..a10585a --- /dev/null +++ b/EtchedPopUpButtonCell.h @@ -0,0 +1,14 @@ + +/* EtchedPopUpButtonCell */ +// NOTE TO SELF: where did this come from? + +#import + + +@interface EtchedPopUpButtonCell : NSPopUpButtonCell { + NSColor *mShadowColor; +} + +-(void)setShadowColor:(NSColor *)aColor; + +@end diff --git a/EtchedPopUpButtonCell.m b/EtchedPopUpButtonCell.m new file mode 100644 index 0000000..186b195 --- /dev/null +++ b/EtchedPopUpButtonCell.m @@ -0,0 +1,43 @@ + +/* EtchedPopUpButtonCell */ +// NOTE TO SELF: where did this come from? + +#import + + +@implementation EtchedPopUpButtonCell + +- (void) dealloc +{ + [mShadowColor release]; + [super dealloc]; +} + +-(void)setShadowColor:(NSColor *)aColor +{ + if ( mShadowColor != aColor ) + { + [mShadowColor release]; + mShadowColor = [aColor retain]; + } +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(id)controlView +{ + [NSGraphicsContext saveGraphicsState]; + NSShadow* theShadow = [[NSShadow alloc] init]; + [theShadow setShadowOffset:NSMakeSize(0, -1)]; + [theShadow setShadowBlurRadius:0.3]; + + [theShadow setShadowColor:mShadowColor]; + + [theShadow set]; + + [super drawInteriorWithFrame:cellFrame inView:controlView]; + + [NSGraphicsContext restoreGraphicsState]; + [theShadow release]; +} + + +@end diff --git a/EtchedText.h b/EtchedText.h new file mode 100644 index 0000000..4891467 --- /dev/null +++ b/EtchedText.h @@ -0,0 +1,14 @@ + +/* EtchedText */ +// NOTE TO SELF: where did this come from? + +#import + +@interface EtchedText : NSTextField +{ +} + ++ (Class)cellClass; +-(void)setShadowColor:(NSColor *)color; + +@end diff --git a/EtchedText.m b/EtchedText.m new file mode 100644 index 0000000..97e43e8 --- /dev/null +++ b/EtchedText.m @@ -0,0 +1,42 @@ + +/* EtchedText */ +// NOTE TO SELF: where did this come from? + +#import +#import + +@implementation EtchedText + ++ (Class)cellClass +{ + return [EtchedTextCell class]; +} + +- initWithCoder: (NSCoder *)origCoder +{ + if(![origCoder isKindOfClass: [NSKeyedUnarchiver class]]){ + self = [super initWithCoder: origCoder]; + } else { + NSKeyedUnarchiver *coder = (id)origCoder; + + NSString *oldClassName = [[[self superclass] cellClass] className]; + Class oldClass = [coder classForClassName: oldClassName]; + if(!oldClass) + oldClass = [[super superclass] cellClass]; + [coder setClass: [[self class] cellClass] forClassName: oldClassName]; + self = [super initWithCoder: coder]; + [coder setClass: oldClass forClassName: oldClassName]; + + [self setShadowColor:[NSColor whiteColor]]; + } + + return self; +} + +-(void)setShadowColor:(NSColor *)color +{ + EtchedTextCell *cell = [self cell]; + [cell setShadowColor:color]; +} + +@end diff --git a/EtchedTextCell.h b/EtchedTextCell.h new file mode 100644 index 0000000..debfecc --- /dev/null +++ b/EtchedTextCell.h @@ -0,0 +1,14 @@ + +/* EtchedTextCell */ +// NOTE TO SELF: where did this come from? + +#import + +@interface EtchedTextCell : NSTextFieldCell +{ + NSColor *mShadowColor; +} + +-(void)setShadowColor:(NSColor *)aColor; + +@end diff --git a/EtchedTextCell.m b/EtchedTextCell.m new file mode 100644 index 0000000..2012cda --- /dev/null +++ b/EtchedTextCell.m @@ -0,0 +1,41 @@ + +/* EtchedTextCell */ +// NOTE TO SELF: where did this come from? + +#import + +@implementation EtchedTextCell + +- (void) dealloc +{ + [mShadowColor release]; + [super dealloc]; +} + +-(void)setShadowColor:(NSColor *)aColor +{ + if ( mShadowColor != aColor ) + { + [mShadowColor release]; + mShadowColor = [aColor retain]; + } +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(id)controlView +{ + [NSGraphicsContext saveGraphicsState]; + NSShadow* theShadow = [[NSShadow alloc] init]; + [theShadow setShadowOffset:NSMakeSize(0, -1)]; + [theShadow setShadowBlurRadius:0.3]; + + [theShadow setShadowColor:mShadowColor]; + + [theShadow set]; + + [super drawInteriorWithFrame:cellFrame inView:controlView]; + + [NSGraphicsContext restoreGraphicsState]; + [theShadow release]; +} + +@end diff --git a/Forward.tif b/Forward.tif new file mode 100644 index 0000000000000000000000000000000000000000..d178fec0708f9295402e4632f0b0780944aa4a99 GIT binary patch literal 1324 zcmebEWzb?^U`cCG70Pt~!^O$gbl{;uMTn9tZ-=u|z>Xz$>SFavE_s@NQsnC>mFQ7Z z_2~1lVem=~nryQ5zpkQ4UiF~62q&+U5b)&HfXci&y_ zzWVHE{oV)pH?-f0Gd3Sd+%Tg?t6k>5X-ZUhc` zUydue`BtvoxBU7`gUVWK_MHD_@8YfYx*e}weE)rgjGef6WAB^)KYRD~^O})YiA(>veP9e|#DxK^< zuB*>~CbLw@Ym!a3qPNhVhVr==PVUy9|15D@n*3*(6KTGjFCUxE{~Y<)?Cj){hvw&k z*W6U|EDHH(!zcXaRO-y)xvbWHlanj;XD|Ob-}Pchs#yBPElnAfLG6DvDub@9)%Uq9 za@W@DeDPIRwJSy$UxN=WYfSx==GxbdOXkfhA#gs<)1$Bt%yy#niwfvk$bx|u_8>m zHMTr8xmB(0n@Rm+w{Mock9YjDo$zGFjn>KYe_FIoc`6zB&-fYp&*GU+BG)#qr@s7o&#UTLZJ+<0r+?pNYnA=8&wud1=H(J@7Ki`$ z|1<@7NqaB9s;6LLS1a^L(%z#`Z+?Z4{ly74%-LR=F5%Fcqp;y)vq2t@;|+cG2Up}; zG^GR%mb9}?uCi%WJ|wy%!kb&+#TwD1H76uh?UsjJv1}K3>*stUpMT*MhxQ5olr+Pn zcC)5<%0J>#<6lrMd^poy!<9|bHK<+m(UOR+!ki`TivJWBGkoO|>{&i(;bh5+M>2X| zyfQsDjbAI;wORvyiNu(GVn1nFfcPP zFfcMm0SQJZTN21-0<&2d7+6IZnW5sWKyfxGn+eDkWB|$o^)fJUFp5IOfg+4zFmXm} zMsXOMC5};w0cZk9J*y0(G@Px%C A_W%F@ literal 0 HcmV?d00001 diff --git a/ForwardDisabled.tif b/ForwardDisabled.tif new file mode 100644 index 0000000000000000000000000000000000000000..22a2cca5c83a38c362988867ead20491d3db1ac1 GIT binary patch literal 1364 zcmYj~3pmqz7{~vAm$~GYVr@t~E=8Qvg;_4uGsia3&^kiHa$ORW+3JkHQ?xE}(kOGV zlt?6wq{UL6<(5lCE|JTF6J<;x*Z>pXc+w-}iNQ2P^V&;rAE-|*Gn3)n%-5dbd5HIfDO4w@8q4BpW z>Gd=WuPyX#QON?`{x+$Qi=&qG!dNf=d}9@r4VDaYz&!Hk;d|ubqY*mKgmIPrCA|?D zE2dXo9y{q9Fm*L(RT34iZtc=T>4q7ML2=L3?ujKxI2_e$DMo@9MAWiOwgpEYwh8t< z+;SJ*aUm|Gw2xi!$CvEp&{$MWY0RfPonc@42HN;G51XHTeQJgbn!4NpQb&g(f8y8NaKnkcCb>DYMX+klY>kx~ z&Z7mZS@){O8OoyXwBIDs`ijwc<$20;!+sZ0FvLR;uS50quIE^I&MJ$A@AwRDYt+`i zwv`)0giW|%OLTMoCt}g2#<`uzmd%|l)=Zq)=NgE2(I*pXIfCNtDJ)Fsf?Dw@eKxHX z>_NLWt`F9p|3!dxXy4S8vmO0d?K0MbTQczBb^YXeSVuZV&jt0BVVt##}eqF31jlaNiJlTJ z1sQ@WKRqVzNu)nRQ0eE5?0|n6VhShlX=8Nw{IH0wkLQ2$--6%x^zddV{af+CK%n=% zMaaLZawZ|rZcW1OQOOf>`Ab+~`Zz-DnGwSCr)FxSir}mpsOP5$e{z<*`TPl^D<>xQ zSyOL?`Xo^9(tO=@GR-)Md}s=fxF0>$pH>HD@2eL)ia@s&5KnQ|8;OSFpfeLZ;+cJCq1poU?W z?Jezo)cJ5VCO@63=?)Bj6U``QhwUvRbx5wP8TJ` z)hG4I&3D`G9#~c?FR|s$C3ytJ(znyw?C^vkgJwdE;V9Zk(<9HY`K$$Mx4J%oh)B(M zNKVs6yAT8h#`#H?Z+O`fnuyxFO;0H6T^fII*IAb^$@ zP{t@J%l*R&0HEjq%FDc>)FWgpC*_TRv@gv9fHJ5f^HKxqe)pg~i2Tk9$sih#Zuom% l(HYeHm)$^pSytKsxBqXy*MDA`lU|WM)zw4*FxLWP|6h)SS0?}f literal 0 HcmV?d00001 diff --git a/ForwardPressed.tif b/ForwardPressed.tif new file mode 100644 index 0000000000000000000000000000000000000000..172efad0421e4afc6753cee904dde92b40afbc5c GIT binary patch literal 17704 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 literal 0 HcmV?d00001 diff --git a/HUDWindow.h b/HUDWindow.h new file mode 100644 index 0000000..ef075db --- /dev/null +++ b/HUDWindow.h @@ -0,0 +1,33 @@ +// +// HUDWindow.h +// HUDWindow +// +// Created by Matt Gemmell on 12/02/2006. +// Copyright 2006 Magic Aubergine. All rights reserved. +// + +#import +#import + +@interface HUDWindow : NSPanel { + BOOL forceDisplay; + BOOL closesOnEvent; + BOOL closesOnEscape; +} + +- (BOOL) closesOnEvent; +- (void) setClosesOnEvent:(BOOL)closes; + +- (BOOL) closesOnEscape; +- (void) setClosesOnEscape:(BOOL)closes; + +- (NSColor *)sizedHUDBackground; +- (void)addCloseWidget; + +@end + +@interface NSObject (HUDWindowDelegate) + +- (IBAction) runClose:(id)sender; + +@end diff --git a/HUDWindow.m b/HUDWindow.m new file mode 100644 index 0000000..5c12a9a --- /dev/null +++ b/HUDWindow.m @@ -0,0 +1,296 @@ +// +// HUDWindow.m +// HUDWindow +// +// Created by Matt Gemmell on 12/02/2006. +// Copyright 2006 Magic Aubergine. All rights reserved. +// + +#import + +@implementation HUDWindow + + +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(unsigned int)styleMask + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag +{ + unsigned int replacementMask = NSBorderlessWindowMask; + if ( styleMask & NSClosableWindowMask ) replacementMask |= NSClosableWindowMask; + + if (self = [super initWithContentRect:contentRect + styleMask:replacementMask + backing:bufferingType + defer:flag]) { + + [self setBackgroundColor: [NSColor clearColor]]; + [self setAlphaValue:1.0]; + [self setOpaque:NO]; + [self setHasShadow:YES]; + [self setMovableByWindowBackground:YES]; + forceDisplay = NO; + [self setBackgroundColor:[self sizedHUDBackground]]; + + if ( styleMask & NSClosableWindowMask ) + [self addCloseWidget]; + + [self setReleasedWhenClosed:YES]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowDidResize:) + name:NSWindowDidResizeNotification + object:self]; + + closesOnEvent = NO; + closesOnEscape = NO; + + return self; + } + return nil; +} + +- (void)awakeFromNib +{ + if ( [self styleMask] & NSClosableWindowMask ) + [self addCloseWidget]; +} + +- (void)addCloseWidget +{ + NSButton *closeButton = [[NSButton alloc] initWithFrame:NSMakeRect(3.0, [self frame].size.height - 16.0, 13.0, 13.0)]; + + [[self contentView] addSubview:closeButton]; + [closeButton setBezelStyle:NSRoundedBezelStyle]; + [closeButton setButtonType:NSMomentaryChangeButton]; + [closeButton setBordered:NO]; + [closeButton setImage:BundledImageWithName(@"hud_titlebar-close",@"com.sprouted.interface")]; + [closeButton setTitle:@""]; + [closeButton setImagePosition:NSImageBelow]; + [closeButton setTarget:self]; + [closeButton setFocusRingType:NSFocusRingTypeNone]; + + if ( [[self delegate] respondsToSelector:@selector(runClose:)] ) + { + [closeButton setTarget:[self delegate]]; + [closeButton setAction:@selector(runClose:)]; + } + else + { + [closeButton setTarget:self]; + [closeButton setAction:@selector(close)]; + } + [closeButton release]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:self]; + [super dealloc]; +} + +- (void)windowDidResize:(NSNotification *)aNotification +{ + [self setBackgroundColor:[self sizedHUDBackground]]; + if (forceDisplay) { + [self display]; + } +} + +- (void)setFrame:(NSRect)frameRect display:(BOOL)displayFlag animate:(BOOL)animationFlag +{ + forceDisplay = YES; + [super setFrame:frameRect display:displayFlag animate:animationFlag]; + forceDisplay = NO; +} + +- (NSColor *)sizedHUDBackground +{ + float alpha = 0.85; + float titlebarHeight = 19.0; + NSImage *bg = [[NSImage alloc] initWithSize:[self frame].size]; + [bg lockFocus]; + + // Make background path + NSRect bgRect = NSMakeRect(0, 0, [bg size].width, [bg size].height - titlebarHeight); + int minX = NSMinX(bgRect); + int midX = NSMidX(bgRect); + int maxX = NSMaxX(bgRect); + int minY = NSMinY(bgRect); + int midY = NSMidY(bgRect); + int maxY = NSMaxY(bgRect); + float radius = 6.0; + NSBezierPath *bgPath = [NSBezierPath bezierPath]; + + // Bottom edge and bottom-right curve + [bgPath moveToPoint:NSMakePoint(midX, minY)]; + [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY) + toPoint:NSMakePoint(maxX, midY) + radius:radius]; + + [bgPath lineToPoint:NSMakePoint(maxX, maxY)]; + [bgPath lineToPoint:NSMakePoint(minX, maxY)]; + + // Top edge and top-left curve + [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY) + toPoint:NSMakePoint(minX, midY) + radius:radius]; + + // Left edge and bottom-left curve + [bgPath appendBezierPathWithArcFromPoint:bgRect.origin + toPoint:NSMakePoint(midX, minY) + radius:radius]; + [bgPath closePath]; + + // Composite background color into bg + [[NSColor colorWithCalibratedWhite:0.1 alpha:alpha] set]; + [bgPath fill]; + + // Make titlebar path + NSRect titlebarRect = NSMakeRect(0, [bg size].height - titlebarHeight, [bg size].width, titlebarHeight); + minX = NSMinX(titlebarRect); + midX = NSMidX(titlebarRect); + maxX = NSMaxX(titlebarRect); + minY = NSMinY(titlebarRect); + midY = NSMidY(titlebarRect); + maxY = NSMaxY(titlebarRect); + NSBezierPath *titlePath = [NSBezierPath bezierPath]; + + // Bottom edge and bottom-right curve + [titlePath moveToPoint:NSMakePoint(minX, minY)]; + [titlePath lineToPoint:NSMakePoint(maxX, minY)]; + + // Right edge and top-right curve + [titlePath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, maxY) + toPoint:NSMakePoint(midX, maxY) + radius:radius]; + + // Top edge and top-left curve + [titlePath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY) + toPoint:NSMakePoint(minX, minY) + radius:radius]; + + [titlePath closePath]; + + // Titlebar + NSColor *titlebarColor = [NSColor colorWithCalibratedWhite:0.25 alpha:1.0]; + [titlebarColor set]; + [titlePath fill]; + + // Title + NSFont *titleFont = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; + NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init]; + [paraStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]]; + [paraStyle setAlignment:NSCenterTextAlignment]; + [paraStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + NSMutableDictionary *titleAttrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + titleFont, NSFontAttributeName, + [NSColor whiteColor], NSForegroundColorAttributeName, + [[paraStyle copy] autorelease], NSParagraphStyleAttributeName, + nil]; + + NSSize titleSize = [[self title] sizeWithAttributes:titleAttrs]; + // We vertically centre the title in the titlbar area, and we also horizontally + // inset the title by 19px, to allow for the 3px space from window's edge to close-widget, + // plus 13px for the close widget itself, plus another 3px space on the other side of + // the widget. + NSRect titleRect = NSInsetRect(titlebarRect, 19.0, (titlebarRect.size.height - titleSize.height) / 2.0); + [[self title] drawInRect:titleRect withAttributes:titleAttrs]; + [bg unlockFocus]; + + return [NSColor colorWithPatternImage:[bg autorelease]]; +} + +- (void)setTitle:(NSString *)value { + [super setTitle:value]; + [self windowDidResize:nil]; +} + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +#pragma mark - + +- (BOOL) closesOnEvent +{ + return closesOnEvent; +} + +- (void) setClosesOnEvent:(BOOL)closes +{ + closesOnEvent = closes; +} + +- (BOOL) closesOnEscape +{ + return closesOnEscape; +} + +- (void) setClosesOnEscape:(BOOL)closes +{ + closesOnEscape = closes; +} + +#pragma mark - + +- (void)keyDown:(NSEvent *)theEvent +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( closesOnEvent || ( closesOnEscape && [theEvent keyCode] == 53 ) ) + if ( [[self delegate] respondsToSelector:@selector(runClose:)] ) + [[self delegate] runClose:self]; + else + [self close]; + else + [super keyDown:theEvent]; +} + +- (void) mouseDown:(NSEvent*)theEvent +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( closesOnEvent ) + if ( [[self delegate] respondsToSelector:@selector(runClose:)] ) + [[self delegate] runClose:self]; + else + [self close]; + else + [super mouseDown:theEvent]; +} + +#pragma mark - + +- (void)resignKeyWindow +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( closesOnEvent ) + [[self delegate] runClose:self]; + else + [super resignKeyWindow]; + //[self close]; +} + +- (void)resignMainWindow +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( closesOnEvent ) + [[self delegate] runClose:self]; + else + [super resignMainWindow]; + //[self close]; +} + +@end diff --git a/Home.tif b/Home.tif new file mode 100644 index 0000000000000000000000000000000000000000..b0e0893ebd6c8074748cc69af488ee6809701813 GIT binary patch literal 1592 zcmYj~3pmqz7{~uh=F-Y0m&PtG(a3Fzs60AmDxtaOaf@71bD477(!UF)QzAuL>@N{& zPfkTDc`(;hYIB!)V$MWl4q-j~cXrOBbI$WV&+q*_pZEQ~KUY`47y#tsF913;8}xP5 ze)2XK=UWbV^z`Afyx56SSCaI%HX%8yCf*94-5I88vsz%cBfB*;Zt$F;CK8jQbJGT^ zc*((`sN$$+2xm~bi*{1YSc%1SD&$c*w3O`(NV$HZ2Hl1 zYChasV=wTj_kP+x{d~l9S-ZS@Hs*Ce^&Wr0==Zo9E8>zjWp$pJ=G&gx<6~7;)oCwC z-e2Hp__a%9DJc@g+7*0^sIe6gKxzg5l-k}pcy}+~dM4P^=aC;glTdFhiH!J~`f6mZ zPCM<}8Aj8{ycO1N$uqTZa^4mW6p)EnbB>;V3zwk1|H3rg7rHwtCz8DJg;oM zwj9PskcCVx0So!poD;j4tCfjed``8=Th);UQ|I5&5;8Q7dk1FqxbUo8xL7G6Hy)j1 z=9afwZ`>woT?FqS59fj(+FhKJXv{UmBwDYjiX%@g5bw|?{BB_RZk%cY-d=o9cJ<&= zjrO4PH)Gv-i@%H}9zo7}fp;?f3cU_vB3z9D8~x62{_)tCSMiW zj9OjK!z#ggVa%1&H=&6j@0{?$Z~GFd;wu}$Ol%cQm{eHHw1-5`)7X=eh3I=HwFqE5 zfpu6~#%2ZOKZqKRDe*tWT)F)Sny^JtAR*y3*ypsQ9IYL>a{1ZJCnr=iJ@t5V9V8rF zwCf1Pz}~S6lDdXDr_rI>xq4XA6u_)Tf#Qy8Ow0WKV0F`?4%-hYg?Fo9iv?|YU;3ZC z?wOdopEM~?P=V$qAwy|cIQA?)m@;rSFqRUX;Hx|P30iwOJF<-LHDnYqb>TRif(mo| z*eh|Hu!s<@J?NhX@>ZPUJJv2^F5Ar zrfvbAGU#kO7C^dUMt#FQ<})$oVi^d$9=AcOkU``XuxkO^EY#+*B;~!XqJ{ph&wG7w)BjrY$q?|b|^|A zBOD{lZ_!TGjndg_=;5{^(H5qO%BkpwnD`2+QHY+tyjz~?(}PDW?|B*Y(XN!Mnjh)B z=h=1mB-=o(mN@l=ju(cV&dhyW=#2HRtfiM~0Ak;1;|Q0R#bkAUy05U!sj{l_v53=o zhjuB3G*xY7$jVZ`#PMeJ;JOiCq9Z8NIOX;qL%!VE;9XrQW)h)YMbQfT+30z*Uzdg= zPoW+3r_Un!ifW_-8R%YA%HFG&|YOQ}9g-d;@T z!_4TwG**oRqF4bXMrmd=udYJRy(e6!YHc6Xd}DbI$3aHnBu%-8d0FnBhb|^tmTlY! z09z0MAO`>d0>H^0#5!YTyx|{~tsr#}a_e4R=8@~XLB<$BHkV}qKoOz7?qvp{@zW!= zBQ$@qd=x?pkX`tDA4x)J|H~E#+0I&lMtoOeFw|K#K literal 0 HcmV?d00001 diff --git a/HomePressed.tif b/HomePressed.tif new file mode 100644 index 0000000000000000000000000000000000000000..cf4116bb2cdb633697e341ddf3118a366878a320 GIT binary patch literal 18092 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 Z|Nmw1@5@yTdOd~1cGp!*XW9N+ + +@interface ImageAndTextCell : NSTextFieldCell { + + BOOL separatorCell; + BOOL updating; + + BOOL dim; + BOOL selected; + BOOL boldsWhenSelected; + int contentCount; + NSSize imageSize; + NSImage *image; + NSMutableParagraphStyle *_paragraph; +} + +- (BOOL) dim; +- (void) setDim:(BOOL)isDim; + +- (BOOL) updating; +- (void) setUpdating:(BOOL)isUpdating; + +- (BOOL) isSeparatorCell; +- (void) setIsSeparatorCell:(BOOL)separator; + +- (BOOL) isSelected; +- (void) setSelected:(BOOL)isSelected; + +- (BOOL) boldsWhenSelected; +- (void) setBoldsWhenSelected:(BOOL)doesBold; + +- (int) contentCount; +- (void) setContentCount:(int)count; + +- (NSSize) imageSize; +- (void) setImageSize:(NSSize)aSize; + +- (NSImage *)image; +- (void)setImage:(NSImage *)anImage; + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; +- (NSSize)cellSize; + +@end diff --git a/ImageAndTextCell.m b/ImageAndTextCell.m new file mode 100644 index 0000000..8a3eef1 --- /dev/null +++ b/ImageAndTextCell.m @@ -0,0 +1,588 @@ +/* + ImageAndTextCell.m + Copyright (c) 2001-2004, Apple Computer, Inc., all rights reserved. + Author: Chuck Pisula + + Milestones: + Initially created 3/1/01 + + Subclass of NSTextFieldCell which can display text and an image simultaneously. +*/ + +/* + IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in + consideration of your agreement to the following terms, and your use, installation, + modification or redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject to these + terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in + this original Apple software (the "Apple Software"), to use, reproduce, modify and + redistribute the Apple Software, with or without modifications, in source and/or binary + forms; provided that if you redistribute the Apple Software in its entirety and without + modifications, you must retain this notice and the following text and disclaimers in all + such redistributions of the Apple Software. Neither the name, trademarks, service marks + or logos of Apple Computer, Inc. may be used to endorse or promote products derived from + the Apple Software without specific prior written permission from Apple. Except as expressly + stated in this notice, no other rights or licenses, express or implied, are granted by Apple + herein, including but not limited to any patent rights that may be infringed by your + derivative works or by other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, + EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS + USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, + REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND + WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR + OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#import + +#import +#import + +@implementation ImageAndTextCell + +static int kMinBackgroundWidth = 20; + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) + { + imageSize = NSMakeSize(32,32); + contentCount = -1; + boldsWhenSelected = YES; + } + + return self; +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) + { + imageSize = NSMakeSize(32,32); + contentCount = -1; + boldsWhenSelected = YES; + } + + return self; +} + +- (void)dealloc { + + [image release]; + image = nil; + + if ( _paragraph ) [_paragraph release]; + _paragraph = nil; + + [super dealloc]; +} + +- copyWithZone:(NSZone *)zone { + ImageAndTextCell *cell = (ImageAndTextCell *)[super copyWithZone:zone]; + + cell->image = [image retain]; + cell->_paragraph = [_paragraph retain]; + + cell->imageSize = imageSize; + cell->separatorCell = separatorCell; + cell->updating = updating; + cell->contentCount = contentCount; + cell->selected = selected; + cell->dim = dim; + cell->boldsWhenSelected = boldsWhenSelected; + + return cell; +} + +#pragma mark - + +- (BOOL) dim +{ + return dim; +} + +- (void) setDim:(BOOL)isDim +{ + dim = isDim; +} + +- (BOOL) boldsWhenSelected +{ + return boldsWhenSelected; +} + +- (void) setBoldsWhenSelected:(BOOL)doesBold +{ + boldsWhenSelected = doesBold; +} + +- (int) contentCount +{ + return contentCount; +} + +- (void) setContentCount:(int)count +{ + contentCount = count; +} + +- (BOOL) updating +{ + return updating; +} + +- (void) setUpdating:(BOOL)isUpdating +{ + updating = isUpdating; +} + +- (BOOL) isSeparatorCell +{ + return separatorCell; +} + +- (void) setIsSeparatorCell:(BOOL)separator +{ + separatorCell = separator; +} + +- (NSSize) imageSize { + return imageSize; +} + +- (void) setImageSize:(NSSize)aSize { + imageSize = aSize; +} + +- (void)setImage:(NSImage *)anImage { + if (anImage != image) { + [image release]; + image = [anImage retain]; + } +} + +- (NSImage *)image { + return image; +} + +- (BOOL) isSelected +{ + return selected; +} + +- (void) setSelected:(BOOL)isSelected +{ + selected = isSelected; +} + +#pragma mark - + +- (NSRect)imageFrameForCellFrame:(NSRect)cellFrame { + if (image != nil) { + NSRect imageFrame; + imageFrame.size = [self imageSize]; + imageFrame.origin = cellFrame.origin; + imageFrame.origin.x += 3; + imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); + return imageFrame; + } + else + return NSZeroRect; +} + +- (NSSize)cellSize { + NSSize cellSize = [super cellSize]; + cellSize.width += (image ? [self imageSize].width : 0) + 3; + return cellSize; +} + +#pragma mark - + +- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent { + + NSRect textFrame, imageFrame; + NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [self imageSize].width, NSMinXEdge); + + NSMutableDictionary *attrs; + NSAttributedString *attrStringValue = [self attributedStringValue]; + + if ( attrStringValue != nil && [attrStringValue length] != 0) + attrs = [[[attrStringValue attributesAtIndex:0 effectiveRange:NULL] mutableCopyWithZone:[self zone]] autorelease]; + else + attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, nil]; + + if ([self isSelected]) { + // prepare the text in white. + //[attrs setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + [attrs setValue:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + + NSFont *originalFont = [attrs objectForKey:NSFontAttributeName]; + if ( originalFont ) { + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:originalFont toHaveTrait:NSBoldFontMask]; + if ( boldedFont ) + [attrs setValue:boldedFont forKey:NSFontAttributeName]; + } + + } + else { + // prepare the text in black. + [attrs setValue:[self textColor] forKey:NSForegroundColorAttributeName]; + } + + + //[textObj setTextColor:[NSColor blackColor]]; + //[textObj setTextColor:[NSColor blackColor] range:NSMakeRange(0,[[textObj string] length])]; + + // center the text and take into account the required inset + NSSize textSize = [[self stringValue] sizeWithAttributes:attrs]; + + int textHeight = textSize.height; + //int textWidth = textSize.width; + + textFrame.origin.y = textFrame.origin.y + (textFrame.size.height/2 - textHeight/2); + textFrame.size.height = textHeight; + //textFrame.size.width = textWidth; + + [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent]; +} + +- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength { + + NSRect textFrame, imageFrame; + NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [self imageSize].width, NSMinXEdge); + + NSMutableDictionary *attrs; + NSAttributedString *attrStringValue = [self attributedStringValue]; + + if ( attrStringValue != nil && [attrStringValue length] != 0) + attrs = [[[attrStringValue attributesAtIndex:0 effectiveRange:NULL] mutableCopyWithZone:[self zone]] autorelease]; + else + attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, nil]; + + if ([self isSelected]) { + // prepare the text in white. + //[attrs setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; + [attrs setValue:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + + NSFont *originalFont = [attrs objectForKey:NSFontAttributeName]; + if ( originalFont ) { + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:originalFont toHaveTrait:NSBoldFontMask]; + if ( boldedFont ) + [attrs setValue:boldedFont forKey:NSFontAttributeName]; + } + + } + else { + // prepare the text in black. + [attrs setValue:[self textColor] forKey:NSForegroundColorAttributeName]; + } + + + //[textObj setTextColor:[NSColor blackColor]]; + //[textObj setTextColor:[NSColor blackColor] range:NSMakeRange(0,[[textObj string] length])]; + + // center the text and take into account the required inset + NSSize textSize = [[self stringValue] sizeWithAttributes:attrs]; + + int textHeight = textSize.height; + //int textWidth = textSize.width; + + textFrame.origin.y = textFrame.origin.y + (textFrame.size.height/2 - textHeight/2); + textFrame.size.height = textHeight; + //textFrame.size.width = textWidth; + + [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength]; +} + +#pragma mark - + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + if ( ![self isSeparatorCell] ) + { + /* + if ([self isHighlighted]) { + + NSColor *gradientStart, *gradientEnd; + + NSRect controlBds = [controlView bounds]; + //NSRect gradientBounds = NSMakeRect(controlBds.origin.x, cellFrame.origin.y+1, + // controlBds.size.width, cellFrame.size.height-1); + + NSRect gradientBounds = NSMakeRect(controlBds.origin.x, cellFrame.origin.y, + controlBds.size.width, cellFrame.size.height-1); + + if (([[controlView window] firstResponder] == controlView) && [[controlView window] isMainWindow] && + [[controlView window] isKeyWindow]) { + + //bottomColor = [NSColor colorWithCalibratedRed:91.0/255.0 green:129.0/255.0 blue:204.0/255.0 alpha:1.0]; + gradientStart = [NSColor colorWithCalibratedRed:136.0/255.0 green:165.0/255.0 blue:212.0/255.0 alpha:1.0]; + gradientEnd = [NSColor colorWithCalibratedRed:102.0/255.0 green:133.0/255.0 blue:183.0/255.0 alpha:1.0]; + + } else { + + //bottomColor = [NSColor colorWithCalibratedRed:140.0/255.0 green:152.0/255.0 blue:176.0/255.0 alpha:0.9]; + gradientStart = [NSColor colorWithCalibratedRed:172.0/255.0 green:186.0/255.0 blue:207.0/255.0 alpha:0.9]; + gradientEnd = [NSColor colorWithCalibratedRed:152.0/255.0 green:170.0/255.0 blue:196.0/255.0 alpha:0.9]; + } + + [[NSBezierPath bezierPathWithRect:gradientBounds] linearGradientFillWithStartColor: + gradientStart endColor:gradientEnd]; + } + */ + + if (image != nil) { + + NSSize myImageSize; + NSRect imageFrame; + + myImageSize = [self imageSize]; + NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + myImageSize.width, NSMinXEdge); + + imageFrame.origin.x += 3; + imageFrame.size = myImageSize; + + if ([controlView isFlipped]) + imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2); + else + imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); + + //[image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver]; + + //#warning this seems like a lot of extra work just because a newly created item draws flipped + + NSImage *imageCopy = [[[NSImage alloc] initWithSize:[self imageSize]] autorelease]; + //[imageCopy setFlipped:[controlView isFlipped]]; + + [imageCopy lockFocus]; + + [[NSGraphicsContext currentContext] saveGraphicsState]; + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + + [image drawInRect:NSMakeRect(0,0,[self imageSize].width,[self imageSize].height) fromRect:NSMakeRect(0,0,[image size].width,[image size].height) + operation:NSCompositeSourceOver fraction:( [self dim] ? 0.5 : 1.0 )]; + + [[NSGraphicsContext currentContext] restoreGraphicsState]; + + [imageCopy unlockFocus]; + + //[imageCopy drawInRect:imageFrame fromRect:NSMakeRect(0,0,[imageCopy size].width,[imageCopy size].height) operation:NSCompositeSourceOver fraction:1.0]; + [imageCopy compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver]; + } + + } + + [super drawWithFrame:cellFrame inView:controlView]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + if ( [self isSeparatorCell] ) + { + NSRect controlBds = [controlView bounds]; + NSRect sepBounds = NSMakeRect(controlBds.origin.x + 4, cellFrame.origin.y + cellFrame.size.height/2 - 1, + controlBds.size.width - 8, 1); + + //[controlView lockFocus]; + + [[NSColor colorWithCalibratedWhite:0.94 alpha:0.7] set]; + NSRectFillUsingOperation(sepBounds, NSCompositeSourceOver); + + //[controlView unlockFocus]; + } + else + { + int textHeight; + int countWidth; + + NSRect inset = cellFrame; + NSMutableDictionary *attrs; + NSAttributedString *attrStringValue = [self attributedStringValue]; + + if ( attrStringValue != nil && [attrStringValue length] != 0) + attrs = [[[attrStringValue attributesAtIndex:0 effectiveRange:NULL] mutableCopyWithZone:[self zone]] autorelease]; + else + attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, nil]; + + // paragraph attribute + + if ( _paragraph == nil ) { + _paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]]; + [_paragraph setLineBreakMode:NSLineBreakByTruncatingTail]; + } + + [attrs setValue:_paragraph forKey:NSParagraphStyleAttributeName]; + + // shadow attribute + + //NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; + //[textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0.4 alpha:0.6]]; + //[textShadow setShadowOffset:NSMakeSize(0,-1)]; + + //[attrs setValue:textShadow forKey:NSShadowAttributeName]; + //[attrs setValue:( [self dim] ? [[self textColor] colorWithAlphaComponent:0.5] : [self textColor] ) forKey:NSForegroundColorAttributeName]; + + + if ([self isSelected]) + { + // prepare the text in white. + [attrs setValue:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + + // bold the text if that option has been requested + if ( [self boldsWhenSelected] ) + { + NSFont *originalFont = [attrs objectForKey:NSFontAttributeName]; + if ( originalFont ) { + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:originalFont toHaveTrait:NSBoldFontMask]; + if ( boldedFont ) + [attrs setValue:boldedFont forKey:NSFontAttributeName]; + } + } + } + else { + // prepare the text in black. + [attrs setValue:( [self dim] ? [[self textColor] colorWithAlphaComponent:0.5] : [self textColor] ) forKey:NSForegroundColorAttributeName]; + } + + + // modify the inset same + inset.origin.x += 2; + inset.size.width -= 4; + + // draw some status info + + if ( [self updating] ) + { + float height = cellFrame.size.height - cellFrame.size.height/5; + NSRect badgeFrame = NSMakeRect( cellFrame.origin.x + cellFrame.size.width - height - 4, + cellFrame.origin.y + cellFrame.size.height/2 - height/2, + height, height ); + + + NSBezierPath *updatingBadge = [NSBezierPath bezierPathWithOvalInRect:badgeFrame]; + [[NSColor colorWithCalibratedWhite:0.8 alpha:0.6] set]; + [updatingBadge fill]; + + NSBezierPath *arc = [NSBezierPath bezierPath]; + + [arc moveToPoint:NSMakePoint(badgeFrame.origin.x + badgeFrame.size.width/2, badgeFrame.origin.y + badgeFrame.size.height/2)]; + [arc appendBezierPathWithArcWithCenter:[arc currentPoint] radius:badgeFrame.size.height/2 + startAngle:-45 endAngle:-90 clockwise:NO]; + [arc closePath]; + + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.8] set]; + [arc fill]; + + // modify the inset + inset.size.width -= ( cellFrame.size.height - cellFrame.size.height/5 + 8 ); + } + + else if ( [self contentCount] > 0 ) + { + NSMutableDictionary *countAttrs; + NSColor *countBackground; + + NSFont *countFont = [NSFont fontWithName:@"LucidaGrande" size:10.0]; + if ( countFont == nil ) + countFont = [NSFont boldSystemFontOfSize:10]; + + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:countFont toHaveTrait:NSBoldFontMask]; + + countAttrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + boldedFont, NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, nil]; + + if ( [self isSelected] ) + { + countBackground = [NSColor whiteColor]; + [countAttrs setObject:[NSColor colorWithCalibratedRed:105/255.0 green:122/255.0 blue:145/255.0 alpha:1.0] forKey:NSForegroundColorAttributeName]; + } + else + { + [countAttrs setObject:( [self dim] ? [[NSColor whiteColor] colorWithAlphaComponent:0.8] : [NSColor whiteColor] ) forKey:NSForegroundColorAttributeName]; + countBackground = [NSColor colorWithCalibratedRed:141/255.0 green:160/255.0 blue:186/255.0 alpha:1.0]; + if ( [self dim] ) countBackground = [countBackground colorWithAlphaComponent:0.5]; + } + + NSString *countString = [NSString stringWithFormat:@"%i", [self contentCount]]; + NSSize countSize = [countString sizeWithAttributes:countAttrs]; + + countWidth = ( countSize.width + 10 ); + NSRect countRect = NSMakeRect( cellFrame.origin.x + cellFrame.size.width - countWidth, + cellFrame.origin.y + cellFrame.size.height/2 - countSize.height/2, + countSize.width, countSize.height ); + + if ( [controlView isFlipped] ) + countRect.origin.y++; + else + countRect.origin.y--; + + NSRect backgroundRect = countRect; + backgroundRect.origin.x -= 5; backgroundRect.size.width += 10; + backgroundRect.origin.y -= 1.5; backgroundRect.size.height += 1; + + if ( backgroundRect.size.width < kMinBackgroundWidth ) + { + // re-align the background + backgroundRect.origin.x = cellFrame.origin.x + cellFrame.size.width - kMinBackgroundWidth - 5; + backgroundRect.size.width = kMinBackgroundWidth; + + // recenter the text horizontally on the background + countRect.origin.x = cellFrame.origin.x + cellFrame.size.width - backgroundRect.size.width - 5 + ( backgroundRect.size.width/2 - countRect.size.width/2 ); + } + + // recenter the text vertically on the background + //countRect.origin.y = backgroundRect.origin.y + ( backgroundRect.size.height/2 - countSize.height/2 ); + + [countBackground set]; + [[NSBezierPath bezierPathWithRoundedRect:backgroundRect cornerRadius:7.4] fill]; + + [countString drawInRect:countRect withAttributes:countAttrs]; + + // modify the inset + inset.size.width -= (backgroundRect.size.width + 10); + } + + + // center the text and take into account the required inset + textHeight = [[self stringValue] sizeWithAttributes:attrs].height; + inset.origin.y = inset.origin.y + (inset.size.height/2 - textHeight/2); + inset.size.height = textHeight; + + // actually draw the title + [[self stringValue] drawInRect:inset withAttributes:attrs]; + } +} + +- (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + return nil; +} + +/* +- (NSColor*) textColor { + + if ( [self isHighlighted] ) + return [NSColor whiteColor]; + else + return [super textColor]; +} +*/ + +@end + diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..23b4502 --- /dev/null +++ b/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.sprouted.interface + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 101 + NSPrincipalClass + + + diff --git a/InfoBarSmall.png b/InfoBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..595a0776d246ac3492b91ef0d95d51c7338175ab GIT binary patch literal 1411 zcmV-}1$_F6P)Z9_AA9ke9r4Aqc{Ms8SG(-LD}MO~5fqDBYcom3gKuk?3itXho@*pUeXbcfi-q zNn8coD{vBxQldMOxP)%;xhlUrX|)3$b7B9V+TW(t|iyg5EL zc60dmn`iQ~Q$K-enFlhscX7vrC`Ws{`nDb4vwzP^ZEZ0zM1e9+OzDk~0+=S&k4-Eb zx^VvLuRov7eaJY!u$(VpiHaadOHUAK+OhrM(UYfl@9yph&|_u;7VV~0E=0k?Y(YXW zAVUoT5&>SkI8yoQ^H1I?-#L2Q46Nt9ALancrX(-9j z(7tZ(hRypAI1H$i36Nf9%qxn3>8y&ce=%_ChYbFj38PL{z%0PF7eR7V=Dw{v+ShdM zJVI#_YXJ0IHn6(2Z&y6tAeW0KY$~Wp&Nah@LUn0vlp%$h5sa@#OCpSNg;YiWJ_zkn znM0ODbUn5Eu%y(dYWpB4rQ$7*_c)FPZs`b60+^(rq`BxxWw3K25Ugv2B#P+&Gl$`c z2%>dipCMx|3BiJ`1<=^s)f8*$?IM>`_b~{D0xjWiywxJ-28Cr&g)PHIP!@4*FpSU6 zJ1{M)st}Q6DtJ;QI}VFb7@b+VhCp3Rjl>&TYZ!>GAam|2jP%Hfh2RSC1jb>bY^VsS zGM1*6?T8>>lscPK#Qf-)Ws)F75(F0&L6U0#n5N~lQg+_5os?^tJ~{41%WaC%i_oU) z$RYzeFmxLM*`Z);N|Co2NnL@imo2?KpROsgWu_-{>5*ZZd6c~rnP4WRi}K(})MDnp z3@A!U51r`-N!jpiEz@HlAvbrckj;;b)J{{^EXmNka)y9J8Y@Ez-hPN}l}ZofTr;j+0feS4X4Eh9HQaBk{W{}7}INzbAvEffkG z+EXHSJrhSTsQ8v`sR;IL3zJhF8iCjpgsiT@#NPv@@xkxDAQNpF01j^F?~MNT>Bsr( zEJL84@@`;0tD(2U#^IeYWOF4<&t|9(IF9TKQjyCjP|wtb>oJ$fN#X+@#UZH7ce-<3aT8TxxNNW|A6ifEsGTLN15v=Z~E&PJDlq zTr7BFXPIGF1rP;K=z->r9dEa8e&fwV%f=Kf-6{e{V;Qi1L22Fo4sn)j~NIvrHs|{ + +@interface IntegrationCopyFiles : NSWindowController +{ + IBOutlet NSObjectController *controller; + IBOutlet NSProgressIndicator *progress; + + NSString *noticeText; +} + +- (NSString*)noticeText; +- (void) setNoticeText:(NSString*)aString; + +- (void) runNotice; +- (void) endNotice; + +@end diff --git a/IntegrationCopyFiles.m b/IntegrationCopyFiles.m new file mode 100644 index 0000000..11720ff --- /dev/null +++ b/IntegrationCopyFiles.m @@ -0,0 +1,80 @@ + +// +// IntegrationCopyFiles.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation IntegrationCopyFiles + +- (id) init { + if ( self = [super initWithWindowNibName:@"IntegrationFileCopy"] ) + { + [self setNoticeText:NSLocalizedString(@"integration copying files",@"")]; + [self retain]; + } + + return self; +} + +- (void) windowDidLoad { + + [[self window] setHidesOnDeactivate:NO]; + //[progress setUsesThreadedAnimation:YES]; + +} + +- (void) dealloc +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + [noticeText release]; + [super dealloc]; +} + +#pragma mark - + +- (NSString*)noticeText +{ + return noticeText; +} + +- (void) setNoticeText:(NSString*)aString +{ + if ( noticeText != aString ) + { + [noticeText release]; + noticeText = [aString copyWithZone:[self zone]]; + } +} + +- (void) runNotice { + + [[self window] center]; + [[self window] makeKeyAndOrderFront:self]; + + [progress startAnimation:self]; + +} + +- (void) endNotice { + [progress stopAnimation:self]; + [[self window] close]; +} + +- (void)windowWillClose:(NSNotification *)aNotification +{ + [controller unbind:@"contentObject"]; + [controller setContent:nil]; + + [self autorelease]; +} + +@end diff --git a/JRLRFooter.h b/JRLRFooter.h new file mode 100644 index 0000000..11c83c3 --- /dev/null +++ b/JRLRFooter.h @@ -0,0 +1,15 @@ +// +// JRLRFooter.h +// SproutedInterface +// +// Created by Philip Dow on 7/30/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface JRLRFooter : NSView { +} + +@end diff --git a/JRLRFooter.m b/JRLRFooter.m new file mode 100644 index 0000000..2d3f848 --- /dev/null +++ b/JRLRFooter.m @@ -0,0 +1,47 @@ +// +// JRLRFooter.m +// SproutedInterface +// +// Created by Philip Dow on 7/30/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +@implementation JRLRFooter + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + + } + return self; +} + +- (void) dealloc { + + [super dealloc]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect { + // Drawing code here. + + NSRect bds = [self bounds]; + NSColor *gradientEnd = [NSColor colorWithCalibratedRed:254.0/255.0 green:254.0/255.0 blue:254.0/255.0 alpha:1.0]; + NSColor *gradientStart = [NSColor colorWithCalibratedRed:235.0/255.0 green:235.0/255.0 blue:235.0/255.0 alpha:1.0]; + + [[NSBezierPath bezierPathWithRect:bds] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [[NSColor lightGrayColor] set]; + NSFrameRect([self bounds]); +} + +@end diff --git a/JournlerGradientView.h b/JournlerGradientView.h new file mode 100644 index 0000000..1b7b0a7 --- /dev/null +++ b/JournlerGradientView.h @@ -0,0 +1,63 @@ +// +// JournlerGradientView.h +// SproutedInterface +// +// Created by Philip Dow on 10/20/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import // needed for Core Image + +@interface JournlerGradientView : NSView { + + NSColor *gradientStartColor; + NSColor *gradientEndColor; + NSColor *backgroundColor; + + int borders[4]; + BOOL bordered; + + BOOL usesBezierPath; + BOOL drawsGradient; + + NSColor *fillColor; + NSColor *borderColor; + + NSControlTint controlTint; +} + ++ (void) drawGradientInView:(NSView*)aView rect:(NSRect)aRect highlight:(BOOL)highlight shadow:(float)shadowLevel; + +- (int*) borders; +- (void) setBorders:(int*)sides; + +- (BOOL) bordered; +- (void) setBordered:(BOOL)flag; + +- (BOOL) drawsGradient; +- (void) setDrawsGradient:(BOOL)draws; + +- (BOOL) usesBezierPath; +- (void) setUsesBezierPath:(BOOL)bezier; + +- (NSColor*) fillColor; +- (void) setFillColor:(NSColor*)aColor; + +- (NSColor*) borderColor; +- (void) setBorderColor:(NSColor*)aColor; + +- (NSControlTint) controlTint; +- (void) setControlTint:(NSControlTint)aTint; + +- (NSColor *)gradientStartColor; +- (void)setGradientStartColor:(NSColor *)newGradientStartColor; +- (NSColor *)gradientEndColor; +- (void)setGradientEndColor:(NSColor *)newGradientEndColor; +- (NSColor *)backgroundColor; +- (void)setBackgroundColor:(NSColor *)newBackgroundColor; + +- (void) resetGradient; + +@end diff --git a/JournlerGradientView.m b/JournlerGradientView.m new file mode 100644 index 0000000..5b78275 --- /dev/null +++ b/JournlerGradientView.m @@ -0,0 +1,476 @@ +// +// JournlerGradientView.m +// SproutedInterface +// +// Created by Philip Dow on 10/20/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import "JournlerGradientView.h" + +#import +#import + +@implementation JournlerGradientView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + + [self setControlTint:[NSColor currentControlTint]]; + [self resetGradient]; + + fillColor = [[NSColor whiteColor] retain]; + borderColor = [[NSColor colorWithCalibratedRed:157.0/255.0 green:157.0/255.0 blue:157.0/255.0 alpha:1.0] retain]; + + bordered = NO; + + borders[0] = 0; // top + borders[1] = 0; // right + borders[2] = 0; // bottom + borders[3] = 0; // left + + drawsGradient = YES; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_controlTintChanged:) + name:NSControlTintDidChangeNotification object:NSApp]; + } + return self; +} + +- (void) dealloc { + [gradientStartColor release]; + [gradientEndColor release]; + [backgroundColor release]; + [fillColor release]; + [borderColor release]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +#pragma mark - + ++ (void) drawGradientInView:(NSView*)aView rect:(NSRect)aRect highlight:(BOOL)highlight shadow:(float)shadowLevel +{ + // Construct rounded rect path + NSRect boxRect = aRect; + NSRect bgRect = boxRect; + NSRect rect = aRect; + + int minX = NSMinX(bgRect); + int maxX = NSMaxX(bgRect); + int minY = NSMinY(bgRect); + int maxY = NSMaxY(bgRect); + + float fraction = ( highlight ? 0.5 : 0.5 ); + + NSBezierPath *bgPath = [NSBezierPath bezierPathWithRect:rect]; + NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; + + NSColor *backgroundColor = [NSColor windowBackgroundColor]; + NSColor *gradientStartColor, *gradientEndColor; + + if ( [aView isFlipped] ) + { + gradientEndColor = [[[[NSColor colorWithCalibratedWhite:0.92 alpha:0.6] + colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:fraction ofColor:[NSColor colorForControlTint:[NSColor currentControlTint]]] + shadowWithLevel:shadowLevel]; + + gradientStartColor = [[[[NSColor colorWithCalibratedWhite:0.82 alpha:0.6] + colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:fraction ofColor:[NSColor colorForControlTint:[NSColor currentControlTint]]] + shadowWithLevel:shadowLevel]; + } + else + { + gradientStartColor = [[[[NSColor colorWithCalibratedWhite:0.92 alpha:0.6] + colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:fraction ofColor:[NSColor colorForControlTint:[NSColor currentControlTint]]] + shadowWithLevel:shadowLevel]; + + gradientEndColor = [[[[NSColor colorWithCalibratedWhite:0.82 alpha:0.6] + colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:fraction ofColor:[NSColor colorForControlTint:[NSColor currentControlTint]]] + shadowWithLevel:shadowLevel]; + } + + // Draw solid color background + [backgroundColor set]; + [bgPath fill]; + + // Draw gradient background using Core Image + CIColor *startColor = [[[CIColor alloc] initWithColor:gradientStartColor] autorelease]; + CIColor *endColor = [[[CIColor alloc] initWithColor:gradientEndColor] autorelease]; + + CIFilter *myFilter = [CIFilter filterWithName:@"CILinearGradient"]; + [myFilter setDefaults]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(minY)] + forKey:@"inputPoint0"]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(maxY)] + forKey:@"inputPoint1"]; + [myFilter setValue:startColor + forKey:@"inputColor0"]; + [myFilter setValue:endColor + forKey:@"inputColor1"]; + CIImage *theImage = [myFilter valueForKey:@"outputImage"]; + + + // Get a CIContext from the NSGraphicsContext, and use it to draw the CIImage + CGRect dest = CGRectMake(minX, minY, maxX - minX, maxY - minY); + + CGPoint pt = CGPointMake(bgRect.origin.x, bgRect.origin.y); + + [nsContext saveGraphicsState]; + + [bgPath addClip]; + + [[nsContext CIContext] drawImage:theImage + atPoint:pt + fromRect:dest]; + + [nsContext restoreGraphicsState]; +} + +- (void)drawRect:(NSRect)rect { + + // Construct rounded rect path + NSRect boxRect = [self bounds]; + NSRect bgRect = boxRect; + + int minX = NSMinX(bgRect); + int maxX = NSMaxX(bgRect); + int minY = NSMinY(bgRect); + int maxY = NSMaxY(bgRect); + + NSBezierPath *bgPath = [NSBezierPath bezierPathWithRect:rect]; + NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; + + // Draw solid color background + [backgroundColor set]; + [bgPath fill]; + + // Draw gradient background using Core Image + + if ( [self drawsGradient] ) + { + + if ( [self usesBezierPath] ) + { + bgPath = [NSBezierPath bezierPathWithRect:boxRect]; + [bgPath linearGradientFillWithStartColor:gradientStartColor endColor:gradientEndColor]; + } + else + { + + CIColor *startColor = [[[CIColor alloc] initWithColor:gradientStartColor] autorelease]; + CIColor *endColor = [[[CIColor alloc] initWithColor:gradientEndColor] autorelease]; + + CIFilter *myFilter = [CIFilter filterWithName:@"CILinearGradient"]; + [myFilter setDefaults]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(minY)] + forKey:@"inputPoint0"]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(maxY)] + forKey:@"inputPoint1"]; + [myFilter setValue:startColor + forKey:@"inputColor0"]; + [myFilter setValue:endColor + forKey:@"inputColor1"]; + CIImage *theImage = [myFilter valueForKey:@"outputImage"]; + + + // Get a CIContext from the NSGraphicsContext, and use it to draw the CIImage + CGRect dest = CGRectMake(minX, minY, maxX - minX, maxY - minY); + + CGPoint pt = CGPointMake(bgRect.origin.x, bgRect.origin.y); + + [nsContext saveGraphicsState]; + + [bgPath addClip]; + + [[nsContext CIContext] drawImage:theImage + atPoint:pt + fromRect:dest]; + + [nsContext restoreGraphicsState]; + } + } + + if ( [self bordered] ) { + + NSPoint topLeft, topRight, bottomRight, bottomLeft; + + topLeft = NSMakePoint(0.5, boxRect.size.height-0.5); + topRight = NSMakePoint(boxRect.size.width, boxRect.size.height-0.5); + + bottomRight = NSMakePoint(boxRect.size.width-0.5, 0.5); + bottomLeft = NSMakePoint(0.5, 0.5); + + // does this actually work? + float scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; + if ( scaleFactor != 1.0 ) { + + // apply the scale factor + topLeft.x *= scaleFactor; + topLeft.y *= scaleFactor; + + topRight.x *= scaleFactor; + topRight.y *= scaleFactor; + + bottomRight.x *= scaleFactor; + bottomRight.y *= scaleFactor; + + bottomLeft.x *= scaleFactor; + bottomLeft.y *= scaleFactor; + + // adjust the points to integral boundaries + topLeft.x = ceil(topLeft.x); + topLeft.y = ceil(topLeft.y); + + topRight.x = ceil(topRight.x); + topRight.y = ceil(topRight.y); + + bottomRight.x = ceil(bottomRight.x); + bottomRight.y = ceil(bottomRight.y); + + bottomLeft.x = ceil(bottomLeft.x); + bottomLeft.y = ceil(bottomLeft.y); + + // convert back to user space + topLeft.x /= scaleFactor; + topLeft.y /= scaleFactor; + + topRight.x /= scaleFactor; + topRight.y /= scaleFactor; + + bottomRight.x /= scaleFactor; + bottomRight.y /= scaleFactor; + + bottomLeft.x /= scaleFactor; + bottomLeft.y /= scaleFactor; + } + + // + //draws an outline around the guy, just like with other views + NSBezierPath *borderPath = [NSBezierPath bezierPath]; + if ( borders[0] ) { + [borderPath moveToPoint:topLeft]; + [borderPath lineToPoint:topRight]; + } + if ( borders[1] ) { + [borderPath moveToPoint:topRight]; + [borderPath lineToPoint:bottomRight]; + } + if ( borders[2] ) { + [borderPath moveToPoint:bottomRight]; + [borderPath lineToPoint:bottomLeft]; + } + if ( borders[3] ) { + [borderPath moveToPoint:bottomLeft]; + [borderPath lineToPoint:topLeft]; + } + + [[self borderColor] set ]; + + [nsContext saveGraphicsState]; + [nsContext setShouldAntialias:NO]; + + [borderPath setLineWidth:1.0]; + [borderPath stroke]; + + [nsContext restoreGraphicsState]; + } +} + + +#pragma mark - + +- (void) resetGradient +{ + if ( [self respondsToSelector:@selector(addTrackingArea:)] ) + { + //10.5 - ends up no different that the pdgradientview + [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.82 alpha:0.8]]; // 1.0 + [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.92 alpha:0.8]]; // 1.0 + } + else + { + //10.4 + [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.92 alpha:0.6]]; // 1.0 + [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.82 alpha:0.6]]; // 1.0 + } + + [self setBackgroundColor:[NSColor windowBackgroundColor]]; // 1.0 +} + +#pragma mark - + +- (int*) borders { + return borders; +} + +- (void) setBorders:(int*)sides { + + borders[0] = sides[0]; + borders[1] = sides[1]; + borders[2] = sides[2]; + borders[3] = sides[3]; +} + +- (BOOL) bordered { + return bordered; +} + +#pragma mark - + +- (BOOL) drawsGradient +{ + return drawsGradient; +} + +- (void) setDrawsGradient:(BOOL)draws +{ + drawsGradient = draws; +} + +- (BOOL) usesBezierPath +{ + return usesBezierPath; +} + +- (void) setUsesBezierPath:(BOOL)bezier +{ + usesBezierPath = bezier; +} + +#pragma mark - + +- (void) setBordered:(BOOL)flag { + bordered = flag; +} + +- (NSColor*) fillColor { + return fillColor; +} + +- (void) setFillColor:(NSColor*)aColor { + + if ( fillColor != aColor ) { + [fillColor release]; + fillColor = [aColor copyWithZone:[self zone]]; + } +} + +- (NSColor*) borderColor { + return borderColor; +} + +- (void) setBorderColor:(NSColor*)aColor { + + if ( borderColor != aColor ) { + [borderColor release]; + borderColor = [aColor copyWithZone:[self zone]]; + } +} + +- (NSControlTint) controlTint +{ + return controlTint; +} + +- (void) setControlTint:(NSControlTint)aTint +{ + controlTint = aTint; + [self resetGradient]; +} + +#pragma mark - + +- (NSColor *)gradientStartColor +{ + return gradientStartColor; +} + +- (void)setGradientStartColor:(NSColor *)newGradientStartColor +{ + // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry. + NSColor *newCalibratedGradientStartColor; + if ( [self respondsToSelector:@selector(addTrackingArea:)] ) + { + newCalibratedGradientStartColor = [newGradientStartColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + } + else + { + newCalibratedGradientStartColor = [[newGradientStartColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:0.5 ofColor:[NSColor colorForControlTint:[self controlTint]]]; + } + + [newCalibratedGradientStartColor retain]; + [gradientStartColor release]; + gradientStartColor = newCalibratedGradientStartColor; + +} + + +- (NSColor *)gradientEndColor +{ + return gradientEndColor; +} + + +- (void)setGradientEndColor:(NSColor *)newGradientEndColor +{ + // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry. + NSColor *newCalibratedGradientEndColor; + + if ( [self respondsToSelector:@selector(addTrackingArea:)] ) + { + newCalibratedGradientEndColor = [newGradientEndColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + } + else + { + newCalibratedGradientEndColor = [[newGradientEndColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace] + blendedColorWithFraction:0.5 ofColor:[NSColor colorForControlTint:[self controlTint]]]; + } + + [newCalibratedGradientEndColor retain]; + [gradientEndColor release]; + gradientEndColor = newCalibratedGradientEndColor; +} + + +- (NSColor *)backgroundColor +{ + return backgroundColor; +} + + +- (void)setBackgroundColor:(NSColor *)newBackgroundColor +{ + [newBackgroundColor retain]; + [backgroundColor release]; + backgroundColor = newBackgroundColor; + [self setNeedsDisplay:YES]; +} + +#pragma mark - + +- (void) _controlTintChanged:(NSNotification*)aNotification +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + [self resetGradient]; + [self setNeedsDisplay:YES]; +} + +@end diff --git a/LabelPicker.h b/LabelPicker.h new file mode 100644 index 0000000..827975a --- /dev/null +++ b/LabelPicker.h @@ -0,0 +1,50 @@ +// +// LabelPicker.h +// SproutedInterface +// +// Created by Philip Dow on 11/12/05. +// Copyright 2005 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface LabelPicker : NSView { + + NSInteger _tag; + + id _target; + SEL _selector; + + NSImage *_labelImage; + NSImage *_labelSelectedImage; + NSImage *_labelHoverImage; + + NSInteger _labelSelection; + + NSRect _clearRect; + NSRect _redRect; + NSRect _orangeRect; + NSRect _yellowRect; + NSRect _greenRect; + NSRect _blueRect; + NSRect _purpleRect; + NSRect _greyRect; +} + +- (int) tag; +- (void) setTag:(int)aTag; + +- (id) target; +- (void) setTarget:(id)targetObject; + +- (SEL) action; +- (void) setAction:(SEL)targetSelector; + +- (NSInteger) labelSelection; +- (void) setLabelSelection:(NSInteger)value; + ++ (NSInteger) finderEquivalentForPickerLabel:(NSInteger)value; ++ (NSInteger) pickerEquivalentForFinderLabel:(NSInteger)value; + +@end diff --git a/LabelPicker.m b/LabelPicker.m new file mode 100644 index 0000000..93a27ad --- /dev/null +++ b/LabelPicker.m @@ -0,0 +1,238 @@ +// +// LabelPicker.m +// SproutedInterface +// +// Created by Philip Dow on 11/12/05. +// Copyright 2005 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import + +@implementation LabelPicker + ++ (void)initialize +{ + if ( self == [LabelPicker class] ) + { + [self exposeBinding:@"labelSelection"]; + } +} + +- (id)initWithFrame:(NSRect)frame +{ + if ( self = [super initWithFrame:frame] ) + { + // Initialization code here. + _labelImage = [BundledImageWithName(@"labelall.tif", @"com.sprouted.interface") retain]; + if ( _labelImage == nil ) NSLog(@"%@ %s - labelall.tif not found!",[self className],_cmd); + + _labelSelectedImage = [BundledImageWithName(@"labelselected.tif", @"com.sprouted.interface") retain]; + if ( _labelSelectedImage == nil ) NSLog(@"%@ %s - labelselected.tif not found!",[self className],_cmd); + + _labelHoverImage = [BundledImageWithName(@"labelhover.tif", @"com.sprouted.interface") retain]; + if ( _labelSelectedImage == nil ) NSLog(@"%@ %s - labelhover.tif not found!",[self className],_cmd); + + _clearRect = NSMakeRect(0,0,17,16); + + _redRect = NSMakeRect(22,0,17,16); + _orangeRect = NSMakeRect(40,0,17,16); + _yellowRect = NSMakeRect(58,0,17,16); + + _greenRect = NSMakeRect(76,0,17,16); + _blueRect = NSMakeRect(94,0,17,16); + _purpleRect = NSMakeRect(112,0,17,16); + _greyRect = NSMakeRect(130,0,17,16); + + _target = nil; + _tag = 0; + } + + return self; +} + +- (void) dealloc +{ + [_labelImage release], _labelImage = nil; + [_labelSelectedImage release], _labelSelectedImage = nil; + [_labelHoverImage release], _labelHoverImage = nil; + + [super dealloc]; +} + +#pragma mark - + +- (NSInteger) tag +{ + return _tag; +} + +- (void) setTag:(NSInteger)aTag +{ + _tag = aTag; +} + +- (id) target +{ + return _target; +} + +- (void) setTarget:(id)targetObject +{ + _target = targetObject; +} + +- (SEL) action { + return _selector; +} + +- (void) setAction:(SEL)targetSelector +{ + _selector = targetSelector; +} + +- (NSInteger) labelSelection +{ + return _labelSelection; +} + +- (void) setLabelSelection:(NSInteger)value +{ + [self willChangeValueForKey:@"labelSelection"]; + _labelSelection = value; + [self didChangeValueForKey:@"labelSelection"]; + [self setNeedsDisplay:YES]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect +{ + NSRect bds = [self bounds]; + NSRect targetSelectionRect; + + NSRect selectionRect = NSMakeRect( 0, 0, + [_labelSelectedImage size].width, + [_labelSelectedImage size].height ); + + NSRect sourceRect = NSMakeRect( 0, 0, + [_labelImage size].width, + [_labelImage size].height) ; + + NSRect destinationRect = NSMakeRect(0, + bds.size.height/2 - sourceRect.size.height/2, + sourceRect.size.width, + sourceRect.size.height ); + + switch ( [self labelSelection] ) + { + case 1: + targetSelectionRect = _redRect; + break; + case 2: + targetSelectionRect = _orangeRect; + break; + case 3: + targetSelectionRect = _yellowRect; + break; + case 4: + targetSelectionRect = _greenRect; + break; + case 5: + targetSelectionRect = _blueRect; + break; + case 6: + targetSelectionRect = _purpleRect; + break; + case 7: + targetSelectionRect = _greyRect; + break; + } + + if ( [self labelSelection] ) + { + // target the selection image + targetSelectionRect.size.height += ( bds.size.height/2 - targetSelectionRect.size.height/2 ); + [_labelSelectedImage drawInRect:targetSelectionRect + fromRect:selectionRect + operation:NSCompositeSourceOver + fraction:1.0]; + + // draw this particular color back over it + } + + [_labelImage drawInRect:destinationRect + fromRect:sourceRect + operation:NSCompositeSourceOver + fraction:1.0]; +} + +#pragma mark - + +- (void)mouseMoved:(NSEvent *)theEvent +{ + NSPoint mouseLoc; + NSInteger myX, myY; + + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + myX = mouseLoc.x; + myY = mouseLoc.y; +} + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + NSPoint mouseLoc; + NSInteger myX, myY; + NSInteger newPoint = -1; + + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + myX = mouseLoc.x; + myY = mouseLoc.y; + + if ( _labelSelection != 0 && NSPointInRect(mouseLoc,_clearRect) ) + newPoint = 0; + else if ( _labelSelection != 1 && NSPointInRect(mouseLoc,_redRect) ) + newPoint = 1; + else if ( _labelSelection != 2 && NSPointInRect(mouseLoc,_orangeRect) ) + newPoint = 2; + else if ( _labelSelection != 3 && NSPointInRect(mouseLoc,_yellowRect) ) + newPoint = 3; + else if ( _labelSelection != 4 && NSPointInRect(mouseLoc,_greenRect) ) + newPoint = 4; + else if ( _labelSelection != 5 && NSPointInRect(mouseLoc,_blueRect) ) + newPoint = 5; + else if ( _labelSelection != 6 && NSPointInRect(mouseLoc,_purpleRect) ) + newPoint = 6; + else if ( _labelSelection != 7 && NSPointInRect(mouseLoc,_greyRect) ) + newPoint = 7; + + if ( newPoint != -1 ) + { + [self setLabelSelection:newPoint]; + + if ( _target && [_target respondsToSelector:_selector] ) + [_target performSelector:_selector withObject:self]; + } +} + +#pragma mark - + ++ (NSInteger) finderEquivalentForPickerLabel:(NSInteger)value +{ + return [SproutedLabelConverter finderEquivalentForSproutedLabel:value]; +} + ++ (NSInteger) pickerEquivalentForFinderLabel:(NSInteger)value +{ + return [SproutedLabelConverter sproutedEquivalentForFinderLabel:value]; +} + + +@end diff --git a/LinkController.h b/LinkController.h new file mode 100644 index 0000000..b61a2af --- /dev/null +++ b/LinkController.h @@ -0,0 +1,36 @@ +// +// LinkController.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface LinkController : NSWindowController +{ + IBOutlet NSObjectController *objectController; + + IBOutlet NSTextField *linkField; + IBOutlet NSTextField *urlField; + + NSString *_linkString; + NSString *_URLString; +} + +- (id) initWithLink:(NSString*)link URL:(NSString*)url; + +- (int) runAsSheetForWindow:(NSWindow*)window attached:(BOOL)sheet; + +- (NSString*) linkString; +- (void) setLinkString:(NSString*)string; + +- (NSString*) URLString; +- (void) setURLString:(NSString*)string; + +- (IBAction)genericCancel:(id)sender; +- (IBAction)genericOkay:(id)sender; + +@end diff --git a/LinkController.m b/LinkController.m new file mode 100644 index 0000000..ca5976e --- /dev/null +++ b/LinkController.m @@ -0,0 +1,110 @@ +// +// LinkController.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation LinkController + +- (id) initWithLink:(NSString*)link URL:(NSString*)url { + + //if ( self = [super init] ) { + if ( self = [super initWithWindowNibName:@"InsertLink"] ) { + //[self window]; + + //[self setWindowFrameAutosaveName:@"InsertLink"]; + + _linkString = [link copyWithZone:[self zone]]; + _URLString = [url copyWithZone:[self zone]]; + + //[self setLinkString:link]; + //[self setURLString:url]; + + //[NSBundle loadNibNamed:@"InsertLink" owner:self]; + + } + + return self; + +} + +- (void) dealloc { + + [_linkString release]; + _linkString = nil; + [_URLString release]; + _URLString = nil; + + [super dealloc]; + +} + +- (void)windowWillClose:(NSNotification *)aNotification { + + [objectController unbind:@"objectContent"]; + [objectController setContent:nil]; + +} + +#pragma mark - + +- (NSString*) linkString { return _linkString; } + +- (void) setLinkString:(NSString*)string { + if ( _linkString != string ) { + [_linkString release]; + _linkString = [string copyWithZone:[self zone]]; + } +} + +- (NSString*) URLString { return _URLString; } + +- (void) setURLString:(NSString*)string { + if ( _URLString != string ) { + [_URLString release]; + _URLString = [string copyWithZone:[self zone]]; + } +} + +#pragma mark - + +- (int) runAsSheetForWindow:(NSWindow*)window attached:(BOOL)sheet { + + int result; + + if ( sheet ) + [NSApp beginSheet: [self window] modalForWindow: window modalDelegate: nil + didEndSelector: nil contextInfo: nil]; + + result = [NSApp runModalForWindow: [self window]]; + + if ( ![objectController commitEditing] ) + NSLog(@"%@ %s - unable to commit editing", [self className], _cmd); + + if ( sheet ) + [NSApp endSheet: [self window]]; + + [self close]; + + return result; + +} + +#pragma mark - + +- (IBAction)genericCancel:(id)sender +{ + [NSApp abortModal]; +} + +- (IBAction)genericOkay:(id)sender +{ + [NSApp stopModal]; +} + +@end diff --git a/MNLineNumberingRulerView.h b/MNLineNumberingRulerView.h new file mode 100644 index 0000000..36bf037 --- /dev/null +++ b/MNLineNumberingRulerView.h @@ -0,0 +1,101 @@ +// +// MNLineNumberingRulerView.h +// +// +// Created by Masatoshi Nishikata on 29/10/05. +// Copyright 2005 Masatoshi Nishikata. All rights reserved. +// http://homepage.mac.com/mnishikata/iblog/ + +//ORIGINAL +// +// MyTextView.m +// LineNumbering +// +// Created by Koen van der Drift on Sat May 01 2004. +// Copyright (c) 2004 Koen van der Drift. All rights reserved. +// + + +#import + +@class MNLineNumberingTextStorage; + +extern const int MNNoLineNumbering; +extern const int MNParagraphNumber; +extern const int MNCharacterNumber; +extern const int MNLineNumber; +extern const int MNDrawBookmarks; + + + +@interface MNLineNumberingRulerView : NSRulerView { + + //nib outlets + IBOutlet id dialogueView; + IBOutlet id radioButtons; + IBOutlet id textField; + + + NSTextView* textView; + NSLayoutManager* layoutManager; + + NSImage* markerImage; + + int rulerOption; + + NSMutableDictionary* marginAttributes; + + BOOL markerDeleteReservationFlag; + +} + +-(void)startSheet; +// Start 'Jump To...' sheet. + +-(BOOL)showParagraph:(unsigned)paragraphNum; + +-(BOOL)showLine:(unsigned)lineNum; + +-(BOOL)showCharacter:(unsigned)charIndex granularity:(NSSelectionGranularity)granularity; + // show line in document text view + // Granularity is one of NSSelectByCharacter, NSSelectByWord, NSSelectByParagraph, or -1(select by line) + +-(void)setVisible:(BOOL)flag; +-(BOOL)isVisible; +// Set and Return Ruler View visiblity. + + +-(void)setOption:(unsigned)option; +// option is +/* + extern const int MNNoLineNumbering; + extern const int MNParagraphNumber; + extern const int MNCharacterNumber; + extern const int MNLineNumber; + extern const int MNDrawBookmarks; +*/ + + + + + +////// private + + +-(IBAction)jumpButtonClicked:(id)sender; +-(unsigned)lineNumberAtIndex:(unsigned)charIndex; +-(unsigned)charIndexOfLineNumber:(unsigned)lineNumber; + +-(void)drawEmptyMargin; +-(void) drawParagraphNumbersInMargin; +-(void) drawNumbersInMargin; +-(void)drawOneNumberInMargin:(unsigned) aNumber inRect:(NSRect)r ; +-(void)drawMarkerInRect:(NSRect)lineRect; + +-(unsigned)characterIndexAtLocation:(float)pos; +-(NSRulerMarker*)newMarker; + + + + +@end diff --git a/MNLineNumberingRulerView.m b/MNLineNumberingRulerView.m new file mode 100644 index 0000000..ac87a82 --- /dev/null +++ b/MNLineNumberingRulerView.m @@ -0,0 +1,1095 @@ + + +#import +#import + +// Ruler thickness value +#define RULER_THICKNESS 25 + +#define MarkerAttributeName NSToolTipAttributeName + +// Margin of displaying bookmarked line in a context menu. +#define STRIP_PREVIEW_MARGIN 15 + +// Default +#define DEFAULT_OPTION MNParagraphNumber | MNDrawBookmarks + + +const int MNNoLineNumbering = 0x00; +const int MNParagraphNumber = 0x03; +const int MNCharacterNumber = 0x02; +const int MNLineNumber = 0x01; +const int MNDrawBookmarks = 0x10; + + + + +@implementation MNLineNumberingRulerView + +/* +- (id)initWithScrollView:(NSScrollView *)aScrollView orientation:(NSRulerOrientation)orientation +{ + + if ( self = [super initWithScrollView:(NSScrollView *)aScrollView + orientation:(NSRulerOrientation)orientation]) + { + + //load nib + [NSBundle loadNibNamed:@"MNLineNumbering" owner:self]; + + + + // Set default width + [self setRuleThickness:RULER_THICKNESS]; + + // Marker config + [self setReservedThicknessForMarkers:0]; + [self setClientView:self]; // Markers ask me if I can add a marker. + + // Add a dummy marker to draw properly + + markerImage = [[NSImage alloc] initByReferencingFile: + [[NSBundle bundleForClass:[self class]] pathForResource:@"marker" ofType:@"tiff"]]; + + NSRulerMarker* aMarker = [self newMarker]; + [self addMarker:aMarker]; + [self removeMarker:aMarker]; + + + // Set letter attributes + marginAttributes = [[NSMutableDictionary alloc] init]; + [marginAttributes setObject:[NSFont labelFontOfSize:9] forKey: NSFontAttributeName]; + [marginAttributes setObject:[NSColor darkGrayColor] forKey: NSForegroundColorAttributeName]; + + + + rulerOption = DEFAULT_OPTION; + + + markerDeleteReservationFlag = NO; + + // + textView = [aScrollView documentView]; + layoutManager = [textView layoutManager]; + + + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowDidUpdate:) + name:NSWindowDidUpdateNotification + object:[aScrollView window]]; + + + + + } + + return self; +} +*/ + +- (void)windowDidUpdate:(NSNotification *)notification +{ + [self display]; +} + +-(void)startSheet +{ + [[NSApplication sharedApplication] beginSheet:dialogueView + modalForWindow:[self window] + modalDelegate:self + didEndSelector:NULL + contextInfo:NULL]; +} + +- (IBAction)jumpButtonClicked:(id)sender +{ + if( [sender tag] != 1 ) // jump & close or cancel + { + [dialogueView orderOut:self]; + [[NSApplication sharedApplication] endSheet:dialogueView]; + } + + if( [sender tag] == -1 ) //cancel + return; + + //check radio buttons + int tag = [radioButtons selectedRow]; + + int number = [textField intValue]; + + if( tag == 0 ) //paragraph + [self showParagraph:number]; + + else if( tag == 1 )//line + [self showLine:number]; + + else if( tag == 2 ) + [self showCharacter:number -1 granularity:NSSelectByCharacter]; + + [self display]; +} + +-(BOOL)showParagraph:(unsigned)paragraphNum +{ + //search paragraph number .... can be faster + + + unsigned charIndex = 0; + unsigned paragraph = 0; + + for( charIndex = 0; charIndex < [ [textView textStorage] length]; charIndex++ ) + { + unichar characterToCheck = [[[textView textStorage] string] characterAtIndex:charIndex]; + + + if (characterToCheck == '\n' || characterToCheck == '\r' || + characterToCheck == 0x2028 || characterToCheck == 0x2029) + paragraph++; + + if( paragraph == paragraphNum ) + break; + } + + + + return [self showCharacter:charIndex granularity:NSSelectByParagraph]; +} + + + +-(BOOL)showLine:(unsigned)lineNum +{ + + unsigned targetCharIndex = [self charIndexOfLineNumber:lineNum ]; + + return [self showCharacter:targetCharIndex granularity:-1]; +} + +-(unsigned)lineNumberAtIndex:(unsigned)charIndex +{ + unsigned index = 0; + unsigned lineNumber = 1; + NSRange lineRange; + + //convert charindex to glyphIndex + + unsigned glyphIndex = [layoutManager glyphRangeForCharacterRange:NSMakeRange(charIndex,1) + actualCharacterRange:NULL].location; + + // Skip all lines that are visible at the top of the text view (if any) + while ( index < glyphIndex ) + { + ++lineNumber; + + [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange]; + index = NSMaxRange( lineRange ); + } + + return lineNumber; +} + + +-(unsigned)charIndexOfLineNumber:(unsigned)lineNumber +{ + unsigned indexLine = 0; + unsigned charIndex = 0; + NSRange lineRange; + + // Skip all lines that are visible at the top of the text view (if any) + while ( indexLine < lineNumber ) + { + ++indexLine; + + [layoutManager lineFragmentRectForGlyphAtIndex:charIndex effectiveRange:&lineRange]; + charIndex = NSMaxRange( lineRange ); + } + + return charIndex -1; +} + +-(BOOL)showCharacter:(unsigned)charIndex granularity:(NSSelectionGranularity)granularity + // show line in document text view + // Granularity is one of NSSelectByCharacter, NSSelectByWord, NSSelectByParagraph, or -1(select by line) +{ + NSRange lineRange; + + + // Return if text view is empty + if([[textView textStorage] length] < charIndex +1 ) return NO; + + + // Show in textView + if( granularity == -1 ) + { + + [layoutManager lineFragmentRectForGlyphAtIndex: + [layoutManager glyphRangeForCharacterRange:NSMakeRange(charIndex,1) + actualCharacterRange:NULL].location effectiveRange:&lineRange]; + + + // Now lineRange is glyph range of the line + // Convert lineRange(glyph range) --> lineRange(char range) + lineRange = [layoutManager characterRangeForGlyphRange: lineRange + actualGlyphRange:NULL]; + [textView setSelectedRange:lineRange]; + } + else + { + [textView setSelectedRange: + [textView selectionRangeForProposedRange:NSMakeRange(charIndex,1) granularity:granularity]]; + + } + + [textView scrollRangeToVisible: [textView selectedRange]]; + return YES; +} + + +-(void)setVisible:(BOOL)flag +{ + if( flag == YES ) + [self setRuleThickness:RULER_THICKNESS]; + else + [self setRuleThickness:0]; + +} +-(BOOL)isVisible +{ + if( [self ruleThickness] == 0 ) + return NO; + else + return YES; + +} +-(void)setOption:(unsigned)option +{ + rulerOption = option; + [self display]; +} + +- (void) dealloc +{ + //NSLog(@"view dealloc"); + [layoutManager setDelegate:NULL]; + + [[NSNotificationCenter defaultCenter] removeObserver:self ]; + + + textView = NULL; + layoutManager = NULL; + [markerImage release]; + + [marginAttributes release]; + + [super dealloc]; +} + +#pragma mark Drawing + +-(void)drawRect:(NSRect)rect +{ + if( ! [[self window] isKeyWindow] ) return; + + [super drawRect:rect]; + + +} + +- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect + //Draw numbers +{ + + + + + + if( [self isVisible] ) + { + + // *** (1) draw background *** + [self drawEmptyMargin ]; + + // *** (2) draw numbers *** + [self drawNumbersInMargin ]; + + + } + +} + + + + + +-(void)drawEmptyMargin +{ + + + NSRect aRect = NSMakeRect(0,0,[self ruleThickness],[self frame].size.height); + /* + These values control the color of our margin. Giving the rect the 'clear' + background color is accomplished using the windowBackgroundColor. Change + the color here to anything you like to alter margin contents. + */ + + aRect.origin.x += 1; + [[NSColor controlHighlightColor] set]; + [NSBezierPath fillRect: aRect]; + + + // These points should be set to the left margin width. + NSPoint top = NSMakePoint([self frame].size.width, aRect.origin.y + aRect.size.height); + NSPoint bottom = NSMakePoint([self frame].size.width, aRect.origin.y); + + + // This draws the dark line separating the margin from the text area. + [[NSColor darkGrayColor] set]; + [NSBezierPath setDefaultLineWidth:1.0]; + [NSBezierPath strokeLineFromPoint:top toPoint:bottom]; + + +} + + + +-(void) drawParagraphNumbersInMargin:(unsigned)startParagraph start:(unsigned)start_index end:(unsigned)end_index +{ + + + unsigned index; + for ( index = start_index; index < end_index; ) + { + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + + + unsigned glyphIndex = [layoutManager glyphRangeForCharacterRange:NSMakeRange(paragraphRange.location,1) + actualCharacterRange:NULL].location; + + NSRect drawingRect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange: NULL]; + + + + [self drawOneNumberInMargin:startParagraph inRect:drawingRect]; + + index = NSMaxRange( [layoutManager glyphRangeForCharacterRange:paragraphRange + actualCharacterRange:NULL] ); + + startParagraph++; + + } + + + +} + + +-(void) drawNumbersInMargin +{ + //NSLog(@"drawNumbersInMargin"); + + UInt32 index, lineNumber; + NSRange lineRange; + NSRect lineRect; + + NSTextContainer* textContainer = [[layoutManager firstTextView] textContainer]; + + // Only get the visible part of the scroller view + NSRect documentVisibleRect = [[[layoutManager firstTextView] enclosingScrollView] documentVisibleRect]; + + // Find the glyph range for the visible glyphs + NSRange glyphRange = [layoutManager glyphRangeForBoundingRect: documentVisibleRect inTextContainer: textContainer]; + + + // Calculate the start and end indexes for the glyphs + unsigned start_index = glyphRange.location; + unsigned end_index = glyphRange.location + glyphRange.length; + + // + NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + // Calculate the start and end char indexes + unsigned start_charIndex = charRange.location; + unsigned end_charIndex = charRange.location + charRange.length; + + + index = 0; + lineNumber = 1; + + unsigned start_paragraphNumber; + start_paragraphNumber = [(MNLineNumberingTextStorage*)[textView textStorage] paragraphNumberAtIndex:start_charIndex]; + + // Skip all lines that are visible at the top of the text view (if any) + while (index < start_index) + { + lineRect = [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange]; + index = NSMaxRange( lineRange ); + ++lineNumber; + } + + for ( index = start_index; index < end_index; lineNumber++ ) + { + lineRect = [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange]; + + + if ( ( rulerOption & 0x0F ) == MNParagraphNumber ) + { + + + + } + else if( ( rulerOption & 0x0F ) == MNLineNumber ) + { + [self drawOneNumberInMargin:lineNumber inRect:lineRect]; + + + } + else if ( ( rulerOption & 0x0F ) == MNCharacterNumber ) // draw character numbers + { + [self drawOneNumberInMargin:index +1 inRect:lineRect]; + } + + + index = NSMaxRange( lineRange ); + + + + } + + ///paragraph + + if ( ( rulerOption & 0x0F ) == MNParagraphNumber ) + { + [self drawParagraphNumbersInMargin:start_paragraphNumber start:(unsigned)start_charIndex end:(unsigned)end_charIndex ]; + } +} + + +-(void)drawOneNumberInMargin:(unsigned) aNumber inRect:(NSRect)r +{ + + + //draw a number + r = [textView convertRect:r toView:self]; //Convert coordinates + + NSString *s; + NSSize stringSize; + + s = [NSString stringWithFormat:@"%d", aNumber, nil]; + if( aNumber == 0 ) + s = @"-"; + stringSize = [s sizeWithAttributes:marginAttributes]; + + // Simple algorithm to center the line number next to the glyph. + [s drawAtPoint: NSMakePoint( [self ruleThickness] - stringSize.width, + r.origin.y + ((r.size.height / 2) - (stringSize.height / 2))) + withAttributes:marginAttributes]; + + +} + + +- (void)drawMarkersInRect:(NSRect)aRect +{ + //NSLog(@"drawMarkersInRect %@",NSStringFromRect(aRect)); + + if( (rulerOption & 0x10) == 0 ) + return; + + + + + // *** (0) remove existing markers *** + // Delete markers unless while dragging. + + NSArray* existingMarkers = [self markers]; + + unsigned hoge = 0; + for( hoge = 0; hoge < [existingMarkers count]; hoge++) + { + if( ! [[existingMarkers objectAtIndex:hoge] isDragging] ) + [self removeMarker:[existingMarkers objectAtIndex:hoge]]; + + } + + + + + // Only get the visible part of the scroller view + NSRect documentVisibleRect = [[[layoutManager firstTextView] enclosingScrollView] documentVisibleRect]; + + // Find the glyph range for the visible glyphs + NSRange glyphRange = [layoutManager glyphRangeForBoundingRect: documentVisibleRect inTextContainer: [textView textContainer]]; + + NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + + + + + for( hoge = charRange.location; hoge < NSMaxRange(charRange) ; hoge ++ ) + { + + if ( [(MNLineNumberingTextStorage*)[textView textStorage] hasBookmarkAtIndex:hoge inTextView:textView] ) + { + + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(hoge, 1) granularity:NSSelectByParagraph]; + + + + unsigned glyphIndex = [layoutManager glyphRangeForCharacterRange:NSMakeRange(paragraphRange.location,1) + actualCharacterRange:NULL].location; + + NSRect drawingRect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange: NULL]; + drawingRect.size.height = [markerImage size].height; + + [self drawMarkerInRect:drawingRect ]; + + + + } + } + + + +} + +-(void)drawMarkerInRect:(NSRect)lineRect + // check if a marker should be drawn and draw it if necessary +{ + + lineRect = [textView convertRect:lineRect toView:self]; + + + NSArray* markerObjects = [self markers]; + unsigned hoge; + BOOL exist = NO; + for(hoge = 0; hoge < [markerObjects count]; hoge++) + { + //get represented object + NSRulerMarker* marker = [markerObjects objectAtIndex:hoge]; + + + if( [[marker representedObject] isEqualToString:NSStringFromRect(lineRect) ] ) + { + //if( ! [marker isDragging] ) + // [marker setMarkerLocation: lineRect.origin.y + (lineRect.size.height / 2) ]; + [marker drawRect:lineRect]; + + exist = YES; + } + + + } + + if( exist == NO ) + { + + NSRulerMarker* aMarker = [self newMarker]; + [aMarker setMarkerLocation: lineRect.origin.y + (lineRect.size.height / 2) ]; + [aMarker drawRect:lineRect]; + [aMarker setMovable:YES]; + [aMarker setRemovable:YES]; + [aMarker setRepresentedObject: NSStringFromRect(lineRect) ]; + [self addMarker:aMarker]; + + } +} + + + +/////////// + +-(unsigned)characterIndexAtLocation:(float)pos +{ + + //convert + float viewPos = [textView convertPoint:NSMakePoint(0,pos) fromView:[[self window] contentView]].y; + + NSRect sweepRect = NSMakeRect( 0,viewPos,100,viewPos+1); + + NSRange glyphRange = [layoutManager glyphRangeForBoundingRect:sweepRect inTextContainer:[textView textContainer] ]; + NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + + //NSLog(@"characterIndexAtLocation = %d",charRange.location); + return charRange.location; +} + + + +#pragma mark Adding, moving, and removing markers + + +-(NSRulerMarker*)newMarker +{ + + NSRulerMarker* aMarker = [[NSRulerMarker alloc] initWithRulerView:self + markerLocation:-10 //invisible at first + image:markerImage + imageOrigin:NSMakePoint(0,8)]; + [aMarker autorelease]; + return aMarker; +} + + +- (void)mouseDown:(NSEvent *)theEvent +{ + //NSLog(@"mouseDown"); + + // add a new marker + if( (rulerOption & 0x10) != MNDrawBookmarks ) return; + + //retrieve mouse location + markerDeleteReservationFlag = NO; + NSPoint mousePosition = [theEvent locationInWindow]; + + //adding or removing a marker + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + + if( [(MNLineNumberingTextStorage*)[textView textStorage] hasBookmarkAtIndex:clickedIndex inTextView:textView]== NO) // adding a new marker + { + [(MNLineNumberingTextStorage*)[textView textStorage] setBookmarkAtIndex:clickedIndex flag:YES inTextView:textView]; + + + }else + markerDeleteReservationFlag = YES; + // if clicked on an existing marker, turn flag on + // This flag is used in mouseUp to delete existing marker + +} + + + + + +-(void)mouseUp:(NSEvent *)theEvent + // deleting a marker +{ + + //NSLog(@"mouseUp"); + + if(markerDeleteReservationFlag == YES) + { + //delete + NSPoint mousePosition = [theEvent locationInWindow]; + + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + [(MNLineNumberingTextStorage*)[textView textStorage] setBookmarkAtIndex:clickedIndex flag:NO inTextView:textView]; + } + + //[self display]; + markerDeleteReservationFlag = NO; + +} + + +- (void)mouseDragged:(NSEvent *)theEvent + // dragging marker +{ + //NSLog(@"mouseDragged"); + + + + if( (rulerOption & 0x10) != MNDrawBookmarks ) return; + + NSPoint mousePosition = [theEvent locationInWindow]; + + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + if( [(MNLineNumberingTextStorage*)[textView textStorage] hasBookmarkAtIndex:clickedIndex inTextView:textView]== YES) //start moving + { + + NSArray* markerObjects = [self markers]; + unsigned hoge; + for(hoge = 0; hoge < [markerObjects count]; hoge++) + { + //get represented object + id ii = [[markerObjects objectAtIndex:hoge] representedObject]; + NSRect identifyingRect = NSRectFromString( ii ); + + float yy = [self convertPoint:mousePosition fromView:[[self window] contentView]].y; + + if( identifyingRect.origin.y <= yy && yy <= NSMaxY(identifyingRect) ) break; + + + } + //NSLog(@"%d, %d", [markerObjects count], hoge); + [ [markerObjects objectAtIndex:hoge] trackMouse:theEvent adding:NO]; + + } + markerDeleteReservationFlag = NO; // turn delete flag off +} + +#pragma mark Defining marker behaviour + +// These are answers to the ruler marker which is asking the client (this ruler view) +// for approvals. + +// ADD +- (BOOL)rulerView:(NSRulerView *)aRulerView shouldAddMarker:(NSRulerMarker *)aMarker +{ + //display update + + return YES; +} + +/* + - (float)rulerView:(NSRulerView *)aRulerView willAddMarker:(NSRulerMarker *)aMarker atLocation:(float)location + { + + + }*/ + +- (void)rulerView:(NSRulerView *)aRulerView didAddMarker:(NSRulerMarker *)aMarker +{ + + // add dictionary + NSPoint mousePosition = [[self window] mouseLocationOutsideOfEventStream]; + + + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + [(MNLineNumberingTextStorage*)[textView textStorage] setBookmarkAtIndex:clickedIndex flag:YES inTextView:textView]; + + + + //[self display]; + //NSLog(@"** ADD **"); +} + +//MOVE +- (BOOL)rulerView:(NSRulerView *)aRulerView shouldMoveMarker:(NSRulerMarker *)aMarker +{ + //display update + + NSPoint mousePosition = [[self window] mouseLocationOutsideOfEventStream]; + + + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + [(MNLineNumberingTextStorage*)[textView textStorage] setBookmarkAtIndex:clickedIndex flag:NO inTextView:textView]; + + + + return YES; +} + +/* + - (float)rulerView:(NSRulerView *)aRulerView willMoveMarker:(NSRulerMarker *)aMarker toLocation:(float)location + { + + + }*/ + +- (void)rulerView:(NSRulerView *)aRulerView didMoveMarker:(NSRulerMarker *)aMarker +{ + // add dictionary + NSPoint mousePosition = [[self window] mouseLocationOutsideOfEventStream]; + + + unsigned clickedIndex; + clickedIndex = [self characterIndexAtLocation:mousePosition.y]; + + [(MNLineNumberingTextStorage*)[textView textStorage] setBookmarkAtIndex:clickedIndex flag:YES inTextView:textView]; + + + + + //[self display]; //NSLog(@"** BOOKMARK MOVED **"); + + +} + +//REMOVE +- (BOOL)rulerView:(NSRulerView *)aRulerView shouldRemoveMarker:(NSRulerMarker *)aMarker +{ + return YES; +} + +- (void)rulerView:(NSRulerView *)aRulerView didRemoveMarker:(NSRulerMarker *)aMarker +{ + //Do nothing here because the marker was already removed when the moving started. + + //NSLog(@"** BOOKMARK REMOVED 2**"); + + +} + + +#pragma mark Context Menu + +-(void)menu_selected {} // dummy method. +-(void)menu_selected_main:(NSNotification *)notification + // this is called when contextual menu is selected +{ + + NSMenuItem* aMenuItem = [[notification userInfo] objectForKey:@"MenuItem"]; + int tag = [aMenuItem tag]; + if( tag == -2 ) // clear bookmarks + { + + [[textView textStorage] removeAttribute:MarkerAttributeName range:NSMakeRange(0,[[textView textStorage] length]) ]; + + [self display]; + + + }else if( tag >= 0 ) + { + + + [self showCharacter:tag granularity:-1]; + + + }else if( tag == -10 ) + { + [self setOption:(rulerOption & 0x10) | MNNoLineNumbering]; + } + else if( tag == -11 ) + { + [self setOption:(rulerOption & 0x10) | MNLineNumber]; + } + else if( tag == -12 ) + { + [self setOption:(rulerOption & 0x10) | MNCharacterNumber]; + } + else if( tag == -13 ) + { + [self setOption:(rulerOption & 0x10) | MNParagraphNumber]; + } + else if( tag == -14 ) + { + if( (rulerOption & 0x10) == MNDrawBookmarks ) + [self setOption:(rulerOption & 0x0F) ]; + else + [self setOption:(rulerOption & 0x0F) | MNDrawBookmarks ]; + } + else if( tag == -15 ) + { + [self setVisible:![self isVisible]]; + } + else if( tag == -7 ) + { + [self startSheet]; + } + +} + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + NSMenuItem* aMenuItem; + NSMenu* menu = [[NSMenu alloc] init]; + + + //create bookmark array + NSMutableArray* bookmarks = [[[NSMutableArray alloc] init] autorelease]; + + unsigned hoge; + //NSRange __range; + for( hoge = 0; hoge < [[textView textStorage] length] ;hoge++ ) + { + + unichar characterToCheck = [[[textView textStorage] string] characterAtIndex:hoge]; + + + if (characterToCheck == '\n' || characterToCheck == '\r' || + characterToCheck == 0x2028 || characterToCheck == 0x2029) + { + id marker = [[textView textStorage] attribute:MarkerAttributeName atIndex:hoge + longestEffectiveRange:NULL inRange:NSMakeRange(0,[[textView textStorage] length])]; + + if( marker != NULL ) + { + if( [marker boolValue] ) + { + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(hoge, 1) granularity:NSSelectByParagraph]; + + [bookmarks addObject:NSStringFromRange(paragraphRange)]; + } + + } + + } + } + + + + + //set up menu + + if( (rulerOption & 0x10) == MNDrawBookmarks ) + { + if([bookmarks count] == 0) + { + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"No Bookmarks" action:@selector(dummy) + keyEquivalent:@""]; + [aMenuItem setEnabled:NO]; + [menu addItem:[aMenuItem autorelease]]; + }else + { + // Add each bookmark + unsigned hoge; + for(hoge = 0; hoge < [bookmarks count]; hoge++) + { + unsigned charIndex = NSRangeFromString( [bookmarks objectAtIndex:hoge] ).location; + NSMenuItem* aMenuItem = [[NSMenuItem alloc] initWithTitle:@"" + action:@selector(menu_selected) + keyEquivalent:@""]; + + unsigned glyphIndex = [[textView layoutManager] glyphRangeForCharacterRange:NSMakeRange(charIndex,1) actualCharacterRange:NULL].location; + //prepare bookmark preview stip + + //set target rect + NSRect aRect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:NULL]; + + aRect.origin.y -= STRIP_PREVIEW_MARGIN; + aRect.size.height += STRIP_PREVIEW_MARGIN * 2; + if( aRect.size.width > 500 ) aRect.size.width = 500; + + // strip preview + NSImage* stripImage = [[NSImage alloc] initWithSize:aRect.size]; + [stripImage setFlipped:YES]; + [stripImage lockFocus]; + + NSRect clipViewRect = [[[textView enclosingScrollView] contentView] bounds]; + + + NSPoint originalOrigin = [textView bounds].origin; + NSRect originalFrame = [textView frame]; + + + [textView setBoundsOrigin:NSMakePoint(0, -aRect.origin.y )]; + [textView setFrame:NSMakeRect(0, -aRect.origin.y ,originalFrame.size.width, originalFrame.size.height)]; + [textView drawRect:NSMakeRect(0,0,aRect.size.width,aRect.size.height)]; + + + [textView setBoundsOrigin:originalOrigin]; + [textView setFrame:originalFrame]; + [[[textView enclosingScrollView] contentView] setBounds:clipViewRect]; + + + [[NSColor darkGrayColor] set]; + [NSBezierPath setDefaultLineWidth:2.0]; + [NSBezierPath strokeRect: NSMakeRect(0,0,aRect.size.width, aRect.size.height)]; + + [stripImage unlockFocus]; + + + + [aMenuItem setImage:[stripImage autorelease]]; + + [aMenuItem setTag:charIndex]; // Tag as character index + [aMenuItem setTarget:self]; + [aMenuItem setToolTip:[NSString stringWithFormat:@"Char:%d Line:%d Paragraph:%d", + charIndex +1, [self lineNumberAtIndex:charIndex],[(MNLineNumberingTextStorage*)[textView textStorage] paragraphNumberAtIndex:charIndex]]]; + [menu addItem:[aMenuItem autorelease]]; + } + } + + //////// + [menu addItem:[NSMenuItem separatorItem]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Clear Bookmarks" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-2]; + [aMenuItem setTarget:self]; + [menu addItem:[aMenuItem autorelease]]; + } + + //Add other items + + + //////// + NSMenu* submenu = [[NSMenu alloc] init]; + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"No Line Numbering" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-10]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( (rulerOption & 0x0F) == MNNoLineNumbering ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Line Number" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-11]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( (rulerOption & 0x0F) == MNLineNumber ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Character Number" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-12]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( (rulerOption & 0x0F) == MNCharacterNumber ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Paragraph Number" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-13]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( (rulerOption & 0x0F) == MNParagraphNumber ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Show Bookmarks" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-14]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( (rulerOption & 0x10) == MNDrawBookmarks ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Hide Ruler" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-15]; + [aMenuItem setTarget:self]; + [aMenuItem setState:( ![self isVisible] ? NSOnState : NSOffState)]; + [submenu addItem:[aMenuItem autorelease]]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"View as" action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-6]; + [aMenuItem setTarget:self]; + [menu addItem:[aMenuItem autorelease]]; + [menu setSubmenu:[submenu autorelease] forItem:aMenuItem]; + + + //////// + aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Jump to..." action:@selector(menu_selected) + keyEquivalent:@""]; + [aMenuItem setTag:-7]; + [aMenuItem setTarget:self]; + [menu addItem:[aMenuItem autorelease]]; + + + //////// + //OBSERVE CONTEXT MENU + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menu_selected_main:) + name:NSMenuDidSendActionNotification object:menu]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menu_selected_main:) + name:NSMenuDidSendActionNotification object:submenu]; + + return [menu autorelease]; + +} + + +@end diff --git a/MNLineNumberingTextStorage.h b/MNLineNumberingTextStorage.h new file mode 100644 index 0000000..4aa5f67 --- /dev/null +++ b/MNLineNumberingTextStorage.h @@ -0,0 +1,32 @@ + +#import + +extern const NSString* MarkerAttributeName; + +@interface MNLineNumberingTextStorage : NSTextStorage +{ + NSMutableAttributedString *m_attributedString; + + + + +} + +-(BOOL)hasBookmarkAtIndex:(unsigned)index inTextView:(NSTextView*)textView; + // Check if the paragraph contains index is bookmarked. + +-(void)setBookmarkAtIndex:(unsigned)index flag:(BOOL)flag inTextView:(NSTextView*)textView; + // Set bookmark to the paragraph contains index. + + // ** note ** + // Bookmarks are added to paragraphs, not characters. + // A bookmark is stored as an attribute 'MarkerAttributeName' embedded to return code. + + +-(unsigned)paragraphNumberAtIndex:(unsigned)index; + // return paragraph number contains index + + + + +@end diff --git a/MNLineNumberingTextStorage.m b/MNLineNumberingTextStorage.m new file mode 100644 index 0000000..33c42cf --- /dev/null +++ b/MNLineNumberingTextStorage.m @@ -0,0 +1,140 @@ +// +// FugoCompletionTextStorage.m +// SampleApp +// +// Created by Masatoshi Nishikata on 13/02/06. +// Copyright 2006 __MyCompanyName__. All rights reserved. +// + +#import + +#define UNIQUECODE [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]] + + +//const NSString* MarkerAttributeName = @"MarkerAttributeName"; +#define MarkerAttributeName NSToolTipAttributeName + +@interface MNLineNumberingTextStorage ( NSTextStorage ) + + +- (NSString *)string; +- (NSDictionary *)attributesAtIndex:(unsigned)index effectiveRange:(NSRangePointer)aRange; +- (void)replaceCharactersInRange:(NSRange)aRange withString:(NSString *)str; +- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange; + +@end + + + +@implementation MNLineNumberingTextStorage + +- (id)init { + self = [super init]; + if (self) { + + // fundamental + m_attributedString = [[NSMutableAttributedString alloc] init]; + + + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [m_attributedString release]; + + + [super dealloc]; +} + + + +-(BOOL)hasBookmarkAtIndex:(unsigned)index inTextView:(NSTextView*)textView +{ + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + id attribute = [self attribute:MarkerAttributeName atIndex:NSMaxRange(paragraphRange) -1 effectiveRange:NULL]; + if( attribute != NULL ) + { + return [attribute boolValue] ; + } + return NO; +} + +-(void)setBookmarkAtIndex:(unsigned)index flag:(BOOL)flag inTextView:(NSTextView*)textView +{ + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + [self addAttribute:MarkerAttributeName value:[NSNumber numberWithBool:flag] range:NSMakeRange(NSMaxRange(paragraphRange)-1,1)]; +} + + + +-(unsigned)paragraphNumberAtIndex:(unsigned)index +{ + int paragraphNumber = 1; + NSString* str = [self string]; + + unsigned hoge; + for( hoge = 0; hoge < [str length]; hoge ++ ) + { + if( index <= hoge ) + break; + + unichar characterToCheck = [str characterAtIndex:hoge]; + + if (characterToCheck == '\n' || characterToCheck == '\r' || + characterToCheck == 0x2028 || characterToCheck == 0x2029) + + paragraphNumber++; + + } + + return paragraphNumber; + +} + +@end + + +// ######## fundamental subclassing ########## +@implementation MNLineNumberingTextStorage (NSTextStorage) + +- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str +{ + + [m_attributedString replaceCharactersInRange:range withString:str]; + + int lengthChange = [str length] - range.length; + [self edited:NSTextStorageEditedCharacters range:range changeInLength:lengthChange]; + +} + + +- (NSString *)string +{ + return [m_attributedString string]; +} + +- (NSDictionary *)attributesAtIndex:(unsigned)index effectiveRange:(NSRangePointer)aRange +{ + return [m_attributedString attributesAtIndex:index effectiveRange:aRange]; +} + + + +- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)range +{ + [m_attributedString setAttributes:attributes range:range]; + [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; + +} + + +@end + diff --git a/MNLineNumberingTextView.h b/MNLineNumberingTextView.h new file mode 100644 index 0000000..f12837f --- /dev/null +++ b/MNLineNumberingTextView.h @@ -0,0 +1,52 @@ +// +// MNLineNumberingRulerView.h +// +// +// Created by Masatoshi Nishikata on 29/10/05. +// Copyright 2005 Masatoshi Nishikata. All rights reserved. +// http://homepage.mac.com/mnishikata/iblog/ + +//ORIGINAL +// +// MyTextView.m +// LineNumbering +// +// Created by Koen van der Drift on Sat May 01 2004. +// Copyright (c) 2004 Koen van der Drift. All rights reserved. +// + +/* + + + LineNumberingRulerView shows paragraph number, line number and character number. + Furthermore, it can handle bookmarks like debug marker in Xcode. + + Bookmarks are embedded to return code as an attribute 'MarkerAttributeName' (Bool value YES as NSNumber). + As a default text view saving process using RTFFromRange... , the bookmark attribute is not saved. + If you want to save them, extract that attribute and save separatory. + + + */ + + +#import + +@class MNLineNumberingRulerView; +@class MNLineNumberingTextStorage; + +@interface MNLineNumberingTextView : NSTextView { + +} + +-(void)toggleGutterVisiblity; +// Show and Hide gutter (ruler view). + +-(void)jumpTo; +// Show 'Jump To...' sheet + + +- (void)textStorageDidProcessEditing:(NSNotification *)aNotification; +-(int)paragraphNumberAtIndex:(int)index; + + +@end diff --git a/MNLineNumberingTextView.m b/MNLineNumberingTextView.m new file mode 100644 index 0000000..3c1e677 --- /dev/null +++ b/MNLineNumberingTextView.m @@ -0,0 +1,128 @@ +// +// LineNumberingTextView.m +// SampleApp +// +// Created by Masatoshi Nishikata on 06/03/24. +// Copyright 2006 __MyCompanyName__. All rights reserved. +// + +#import + + +@implementation MNLineNumberingTextView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + + + + + + + } + return self; +} + +- (void) awakeFromNib +{ + MNLineNumberingTextStorage* ts = [[MNLineNumberingTextStorage alloc] init]; + + [[self layoutManager] replaceTextStorage:ts]; + + [[self textStorage] setDelegate:self]; + + + NSScrollView* scrollView = [self enclosingScrollView]; + + + + // *** set up main text View *** // + //textView setting -- add ruler to textView + MNLineNumberingRulerView* aNumberingRulerView = + [[MNLineNumberingRulerView alloc] initWithScrollView:scrollView + orientation:NSVerticalRuler]; + + [scrollView setVerticalRulerView:aNumberingRulerView ]; + + //configuration + [scrollView setHasVerticalRuler:YES]; + [scrollView setHasHorizontalRuler:NO]; + + [scrollView setRulersVisible:YES]; + + [aNumberingRulerView release]; + +} + +/* +- (void)awakeFromNib +{ + + + if ([[self superclass] instancesRespondToSelector:@selector(awakeFromNib)]) { + [super awakeFromNib]; + } + +} +*/ + +-(void)dealloc +{ + + [super dealloc]; +} + + + + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + NSMenuItem* customMenuItem; + NSMenu* aContextMenu = [super menuForEvent:theEvent]; + + + //add separator + customMenuItem = [NSMenuItem separatorItem]; + [customMenuItem setRepresentedObject:@"MN"]; + [aContextMenu addItem:customMenuItem ]; + + + + // + customMenuItem = [[NSMenuItem alloc] initWithTitle:@"Show/Hide Gutter" + action:@selector(toggleGutterVisiblity) keyEquivalent:@""]; + [customMenuItem setRepresentedObject:@"MN"]; + [aContextMenu addItem:customMenuItem ]; + [customMenuItem release]; + // + + // + customMenuItem = [[NSMenuItem alloc] initWithTitle:@"Jump to..." + action:@selector(jumpTo) keyEquivalent:@""]; + [customMenuItem setRepresentedObject:@"MN"]; + [aContextMenu addItem:customMenuItem ]; + [customMenuItem release]; + + + return aContextMenu; +} + +-(void)toggleGutterVisiblity +{ + NSRulerView* rv = [[self enclosingScrollView] verticalRulerView]; + [rv setVisible:![rv isVisible]]; +} + +-(void)jumpTo +{ + [[[self enclosingScrollView] verticalRulerView] startSheet]; +} + +- (void)textStorageDidProcessEditing:(NSNotification *)aNotification +{ + [[[self enclosingScrollView] verticalRulerView] setNeedsDisplay:YES]; +} + +@end diff --git a/MUPhotoCell.h b/MUPhotoCell.h new file mode 100644 index 0000000..a5867ee --- /dev/null +++ b/MUPhotoCell.h @@ -0,0 +1,23 @@ +// +// MUPhotoCell.h +// SproutedInterface +// +// Created by Philip Dow on 1/19/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Or was this originally part of the MUPhotoView package? +// I subclassed to PDPhotoView and don't recall if I added this as well + +#import + + +@interface MUPhotoCell : NSImageCell { + + NSString *imageTitle; +} + +- (NSString*) title; +- (void) setTitle:(NSString*)aString; + +@end diff --git a/MUPhotoCell.m b/MUPhotoCell.m new file mode 100644 index 0000000..9a01654 --- /dev/null +++ b/MUPhotoCell.m @@ -0,0 +1,137 @@ +// +// MUPhotoCell.m +// SproutedInterface +// +// Created by Philip Dow on 1/19/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Or was this originally part of the MUPhotoView package? +// I subclassed to PDPhotoView and don't recall if I added this as well + +#import + + +@implementation MUPhotoCell + +- (id)initImageCell:(NSImage *)anImage +{ + if ( self = [super initImageCell:anImage] ) + { + [self setImageFrameStyle:NSImageFrameNone]; + [self setImageScaling:NSScaleProportionally]; + + [self setAlignment:NSCenterTextAlignment]; + [self setImageAlignment:NSImageAlignTop]; + + [self setBezeled:NO]; + [self setBordered:YES]; + } + + return self; +} + +- (void) dealloc +{ + [imageTitle release]; + [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone +{ + MUPhotoCell *newObject = [[[self class] allocWithZone:zone] initImageCell:[self image]]; + + [newObject setTitle:[self title]]; + [newObject setImageFrameStyle:[self imageFrameStyle]]; + [newObject setImageScaling:[self imageScaling]]; + + [newObject setAlignment:[self alignment]]; + [newObject setImageAlignment:[self imageAlignment]]; + + [newObject setBezeled:[self isBezeled]]; + [newObject setBordered:[self isBordered]]; + + return newObject; +} + + +- (BOOL)isOpaque +{ + return NO; +} + +- (NSString*) title +{ + return imageTitle; +} + +- (void) setTitle:(NSString*)aString +{ + if ( imageTitle != aString ) + { + [imageTitle release]; + imageTitle = [aString copyWithZone:[self zone]]; + } +} + +#pragma mark - +// #warning should take into account font metrics, etc + +- (NSRect)imageRectForBounds:(NSRect)theRect +{ + NSRect adjustedImageFrame = theRect; + if ( [self title] != nil ) + adjustedImageFrame.size.height -= 30; + + return adjustedImageFrame; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect +{ + NSRect adjustedTitleFrame = theRect; + if ( [self objectValue] != nil ) + { + adjustedTitleFrame.origin.y = adjustedTitleFrame.origin.y + adjustedTitleFrame.size.height - 30; + adjustedTitleFrame.size.height = 30; + } + + return adjustedTitleFrame; +} + +#pragma mark - + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + // that draws the frame and photo interior (drawInterior is called, can't override) in a restricted space, leaving us room for the title + [super drawWithFrame:[self imageRectForBounds:cellFrame] inView:controlView]; + + NSMutableParagraphStyle *paragraph = [[[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]] autorelease]; + [paragraph setLineBreakMode:NSLineBreakByWordWrapping]; + [paragraph setAlignment:NSCenterTextAlignment]; + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + paragraph, NSParagraphStyleAttributeName, nil]; + + if ( [self title] != nil ) + { + NSRect targetTitleRect; + NSRect originalTitleRect = [self titleRectForBounds:cellFrame]; + NSSize titleSize = [[self title] sizeWithAttributes:attributes]; + + if ( titleSize.width > originalTitleRect.size.width ) + targetTitleRect = NSMakeRect( originalTitleRect.origin.x, + originalTitleRect.origin.y + ( originalTitleRect.size.height/2 - titleSize.height/2 ), + originalTitleRect.size.width, 30 ); + + else + targetTitleRect = NSMakeRect( originalTitleRect.origin.x + ( originalTitleRect.size.width/2 - titleSize.width/2 ), + originalTitleRect.origin.y + ( originalTitleRect.size.height/2 - titleSize.height/2 ), + titleSize.width, 30 ); + + [[self title] drawInRect:targetTitleRect withAttributes:attributes]; + } +} + +@end diff --git a/MUPhotoView.h b/MUPhotoView.h new file mode 100644 index 0000000..bd09ac8 --- /dev/null +++ b/MUPhotoView.h @@ -0,0 +1,317 @@ +// +// +// MUPhotoView +// +// Copyright (c) 2006 Blake Seely +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// * You include a link to http://www.blakeseely.com in your final product. +// +// Version History: +// +// Version 1.0 - April 17, 2006 - Initial Release +// Version 1.1 - April 29, 2006 - Photo removal support, Added support for reduced-size drawing during live resize +// Version 1.2 - September 24, 2006 - Updated selection behavior, Changed to MIT license, Fixed issue where no images would show, fixed autoscroll + +// Modified for the iMedia project http://imedia.karelia.com/ + +#import + +extern NSString *ShowCaptionChangedNotification; + +//! MUPhotoView displays a grid of photos similar to iPhoto's main photo view. The class gives developers several options for providing images - via bindings or delegation. + +//! MUPhotoView displays a resizeable grid of photos, similar to iPhoto's photo view functionality. MUPhotoView provides developers with two different options for passing photo information to the view +//! Most importantly, MUPhotoView currently only deals with an array of photos. It also does not know how to find NSImage objects +//! that are inside another object - it expects NSImage objects. The first method for providing those objects it by binding an array of NSImage objects to the "photosArray" key of the view. +//! If this key has been bound, MUPhotoView will fetch all the images it displays from that binding. The second method is to have a delegate object provide the photos. MUPhotoView will only +//! call the delegate's photo methods if the photosArray key has not been bound. Please see the MUPhotoViewDelegate category documentation for descriptions of the methods. +@interface MUPhotoView : NSView { + // Please do not access ivars directly - use the accessor methods documented below + IBOutlet id delegate; + + BOOL sendsLiveSelectionUpdates; + BOOL useHighQualityResize; + BOOL showCaptions; + + NSMutableArray *photosArray; + NSMutableArray *photosFastArray; + NSIndexSet *selectedPhotoIndexes; + NSMutableIndexSet *dragSelectedPhotoIndexes; + + NSColor *backgroundColor; + BOOL useShadowBorder; + BOOL useOutlineBorder; + NSShadow *borderShadow; + NSShadow *noShadow; + NSColor *borderOutlineColor; + + BOOL useBorderSelection; + BOOL useShadowSelection; + NSColor *selectionBorderColor; + NSColor *shadowBoxColor; + float selectionBorderWidth; + + // spacing photos + float photoSize; + float photoVerticalSpacing; + float photoHorizontalSpacing; + + + NSSize gridSize; + unsigned columns; + unsigned rows; + + BOOL mouseDown; + BOOL potentialDragDrop; + NSPoint mouseDownPoint; + NSPoint mouseCurrentPoint; + NSTimer *autoscrollTimer; + NSTimer *photoResizeTimer; + NSDate *photoResizeTime; + BOOL isDonePhotoResizing; + + NSArray *liveResizeSubviews; + + + BOOL drawDropHilite; +} + +#pragma mark - +// Delegate Methods +#pragma mark Delegate Methods +/** Returns the current delegate **/ +- (id)delegate; +/** Sets the delegate. See the MUPhotoViewDelegate category for information about which delegate methods will get called and when.**/ +- (void)setDelegate:(id)del; + +#pragma mark - +// Photos Methods +#pragma mark Photo Methods +/** Returns the array of NSImage objects that MUPhotoView is currently drawing from. If nothing has been bound to the "photosArray" key and + there has not been a call to -setPhotosArray, then this will probably return nil. If this method returns nil, then at draw time, the MUPhotoView will attempt to ask + its delegate for the count of photos and for photos at each index. **/ +- (NSArray *)photosArray; +/** Sets the array of NSImage objects that MUPhotoView uses to draw itself. If you call this method and pass nil, and the delegate is NOT nil, it will ask the delegate for + the photos. **/ +- (void)setPhotosArray:(NSArray *)aPhotosArray; + +#pragma mark - +// Selection Management +#pragma mark Selection Management + /** Returns the current NSIndexSet indicating which photos are currently selected. If this is nil, then the view is asking its delegate for the selection index information. **/ +- (NSIndexSet *)selectedPhotoIndexes; +/** Sets the NSIndexSet that the view will use to indicate which photos need to appear selected in the view. By setting this value to nil, MUPhotoView will ask the delegate for + this information. **/ +- (void)setSelectedPhotoIndexes:(NSIndexSet *)aSelectedPhotoIndexes; + +#pragma mark - +// Selection Style +#pragma mark Selection Style + /** Indicates whether the view is drawing "selected" photos with a 3px border around the photo. The appearnce is similar to iPhoto's selection style. The default value is YES. **/ +- (BOOL)useBorderSelection; +/** Tells the view whether or not to indicated "selected" photos by drawing a 3px border around the photo. The appearnce is similar to iPhoto's selection style. + The default value is YES. **/ +- (void)setUseBorderSelection:(BOOL)flag; +/** Returns the current color that thew view is using to draw selection borders. If -useBorderSelection returns NO, it doesn't matter what color is returned from this method. + The initial value for selectionBorderColor is the user's current selection color. **/ +- (NSColor *)selectionBorderColor; +/** Tells the view what color border should be drawn around a "selected" photo. If -useBorderSelection returns NO, calling this method will not have any effect until + -setUseBorderSelection:YES is callled. The selection border color defaults to the user's current selection color. **/ +- (void)setSelectionBorderColor:(NSColor *)aSelectionBorderColor; +/** Indicates whether the view indicates "selected" photos by drawing a semi-transparent rounded box around the photo. The default value is NO. **/ +- (BOOL)useShadowSelection; + /** By setting this value to YES, you tell MUPhotoView to indicate a "selected" photo by drawing a semi-transparent rounded rectangle around the photo. The color and opacity + of the rounded rectangle depend on the current background color of the view: for lighter colors, MUPhotoView will use a semi-transparent black; for darker colors, the color will + be a semi-transparent white.**/ +- (void)setUseShadowSelection:(BOOL)flag; + + /** Indicates whether the view is drawing with a high-quality, though possibly slower, algorithm for image interpolation. The default value is NO; the default setting for the machine is used. **/ +- (BOOL)useHighQualityResize; + /** By setting this value to YES, you tell MUPhotoView to draw with a higher-quality image, sacrificing speed. **/ +- (void)setUseHighQualityResize:(BOOL)flag; + +/** Indicates whether captions should be shown below the photo */ +- (BOOL)showCaptions; +/** By setting this value to YES, you tell MUPhotoView to draw captions below the thumbnails. **/ +- (void)setShowCaptions:(BOOL)flag; + +#pragma mark - +// Appearance +#pragma mark Appearance + /** Indicates whether the view is drawing a drop-shadow around each photo. The default value is YES. **/ +- (BOOL)useShadowBorder; +/** Passing YES to this method will cause the view to draw a drop shadow around each photo. The default value is YES. **/ +- (void)setUseShadowBorder:(BOOL)flag; +/** Indicates whether the view is currently set to draw a 1px, 50% white border around each photo. The default value is YES. **/ +- (BOOL)useOutlineBorder; +/** Tells the view whether or not to draw a 1px, 50% white border around each photo. The default value is YES. **/ +- (void)setUseOutlineBorder:(BOOL)flag; +/** Returns the current color being used to paint the background before drawing photos. The default value is [NSColor whiteColor]. **/ +- (NSColor *)backgroundColor; +/** Tells the view to use a new color when drawing the background. If -useShadowSelection is YES, updating the background color may also affect the color being used to draw + the shadow selection indicator. **/ +- (void)setBackgroundColor:(NSColor *)aBackgroundColor; +/** Returns the current pixel size that photos are scaled to. When drawing, a photo is scalled proportionately so it's longest side is this number of pixels. **/ +- (float)photoSize; +/** Tells the view to draw photos scaled so their longest side is aPhotoSize pixels long. This will cause the visible area of the view to be redrawn - and the view will attempt to + keep the currently-visible photos near the center of the scroll area. **/ +- (void)setPhotoSize:(float)aPhotoSize; + +- (IBAction)takePhotoSizeFrom:(id)sender; + +#pragma mark - +// Seriously, Don't Mess With Texas +#pragma mark Seriously, Don't Mess With Texas +// haven't tested changing these behaviors yet - there's no reason they shouldn't work... but use at your own risk. +- (float)photoVerticalSpacing; +- (void)setPhotoVerticalSpacing:(float)aPhotoVerticalSpacing; +- (float)photoHorizontalSpacing; +- (void)setPhotoHorizontalSpacing:(float)aPhotoHorizontalSpacing; +- (NSColor *)borderOutlineColor; +- (void)setBorderOutlineColor:(NSColor *)aBorderOutlineColor; +- (NSColor *)shadowBoxColor; +- (void)setShadowBoxColor:(NSColor *)aShadowBoxColor; +- (float)selectionBorderWidth; +- (void)setSelectionBorderWidth:(float)aSelectionBorderWidth; + +@end + +#pragma mark - +// Delegate Methods +#pragma mark Delegate Methods +/// The MUPhotoViewDelegate category defines the methods that a MUPhotoView may call, and that you can use provide drag and drop, double-click, selection and even photo display support +/** The MUPhotoViewDelegate category provides default implementations of all the methods the MUPhotoView may call. Overriding each of them is optional - the default implementations + return no results, nil results, or zero as appropriate. **/ +@interface NSObject (MUPhotoViewDelegate) + +/** The view will call this method if all of the following are true: (a) a valid array of NSImage objects has not been bound to the @"photosArray" key, (b) + -setPhotosArray: has not been called and passed a valid, non-nil array, and (c) the delegate is not nil. **/ +- (unsigned)photoCountForPhotoView:(MUPhotoView *)view; +/** The view will call this method if all of the following are true: (a) a valid array of NSImage objects has not been bound to the @"photosArray" key, (b) + -setPhotosArray: has not been called and passed a valid, non-nil array, and (c) the delegate is not nil. The delegate should return the NSImage appropriate + to draw at the specified index. **/ +- (NSImage *)photoView:(MUPhotoView *)view photoAtIndex:(unsigned)index; + +/** If the view depends on the delegate for photos (instead of bindings), it will call this method during a live resize operation. It expects a very small version + of the photo at the specified index in order to speed drawing in the live resize. Overriding this method is optional. The default implementation returns nil, + which forces the view to use the regular photos during resize. Avoid doing any time-consuming image manipulation in this method or there will be no benefit + to drawing the small images. Ideally, you would only create a small version once - either ahead of time or during this call - and then reuse it. **/ +- (NSImage *)photoView:(MUPhotoView *)view fastPhotoAtIndex:(unsigned)index; + +- (NSString *)photoView:(MUPhotoView *)view titleForPhotoAtIndex:(unsigned)index; + // If a title is returned it will be drawn under the photo, if that option is set. + +// selection methods - will only get called if photoSelectionIndexes has not been bound +/** The view will call this method if all of the following are true: (a) a valid NSIndexSet has not been bound to the @"photoSelectionIndexes" key, (b) + -setPhotoSelectionIndexes: has not been called and passed a valid, non-nil NSIndexSet, and (c) the delegate is not nil. The delegate should return an NSIndexSet filled + with indexes appropriately representing which photos should be drawn as "selected" .**/ +- (NSIndexSet *)selectionIndexesForPhotoView:(MUPhotoView *)view; +/** The view will call this method if all of the following are true: (a) a valid NSIndexSet has not been bound to the @"photoSelectionIndexes" key, (b) + -setPhotoSelectionIndexes: has not been called and passed a valid, non-nil NSIndexSet, and (c) the delegate is not nil. If the delegate implements this method, + it can modify the proposed selection and return an appropriate NSIndexSet. You should only implement this method if, for some reason, you want to manipulate or look + at the selection indexes before the view marks them as selected. **/ +- (NSIndexSet *)photoView:(MUPhotoView *)view willSetSelectionIndexes:(NSIndexSet *)indexes; +/** The view will call this method if all of the following are true: (a) a valid NSIndexSet has not been bound to the @"photoSelectionIndexes" key, (b) + -setPhotoSelectionIndexes: has not been called and passed a valid, non-nil NSIndexSEt, and (c) the delegate is not nil. The delegate should do whatever work necessary to + mark the specified indexes as selected. (i.e. a subsequent call to -selectionIndexesForPhotoView: should most likely return this set or an identical one. **/ +- (void)photoView:(MUPhotoView *)view didSetSelectionIndexes:(NSIndexSet *)indexes; + +// drag and drop +/** A delegate would use this method to specify whether the view should support drag operations. (i.e. whether the view should allow photos to be dragged out of the view. + The semantics are identical to the -[NSDraggingSource draggingSourceOperationmaskForLocal] **/ +- (unsigned int)photoView:(MUPhotoView *)view draggingSourceOperationMaskForLocal:(BOOL)isLocal; +/** The view will call this method at drag time. The delegate should pass an array indicating the types that it will put on the pasteboard for a given set of images. If + you provide an implementation for -photoView:draggingSourceOperationMaskForLocal: that returns anything other than NO, you should also implement this method and indicate + which types you will support. **/ +//- (NSArray *)pasteboardDragTypesForPhotoView:(MUPhotoView *)view; +/** The view will call this method when it is about to initiate a drag. It will call this method once for *each* combination type returned from -pasteboardDragTypesForPhotoView: + and each photo currently being dragged. The delegate should return the appropriate data for the given type. If you provide any implementation of + -photoView:draggingSourceOperationMaskForLocal that returns anything other than NO, you should also implement this method. **/ +//- (NSData *)photoView:(MUPhotoView *)view pasteboardDataForPhotoAtIndex:(unsigned)index dataType:(NSString *)type; +- (void)photoView:(MUPhotoView *)view fillPasteboardForDrag:(NSPasteboard *)pboard; + +// drag and drop receiving - Equivalent to the NSDraggingDestination methods +- (NSDragOperation)photoView:(MUPhotoView *)view draggingEntered:(id )sender; +- (void)photoView:(MUPhotoView *)view draggingExited:(id )sender; +- (BOOL)photoView:(MUPhotoView *)view performDragOperation:(id )sender; +- (BOOL)photoView:(MUPhotoView *)view prepareForDragOperation:(id )sender; +- (void)photoView:(MUPhotoView *)view concludeDragOperation:(id )sender; + +// double-click support +/** The view will call this delegate method when the user double-clicks on the photo at the specified index. If you do not wish to support any double-click behavior, then you + don't need to override this method. **/ +- (void)photoView:(MUPhotoView *)view doubleClickOnPhotoAtIndex:(unsigned)index withFrame:(NSRect)frame; + +// photo removal support +/** The view will call this delegate method when the user selects photos and presses the delete key. The delegate should use this method to alter the photos that will + be removed by returning an appropriate NSIndexSet. The delegate will get this method even if the photos array is set via bindings. If the photos array is not set + via bindings, overriding this method is still optional. The default implementation of this method simply returns the an empty index set. **/ +- (NSIndexSet *)photoView:(MUPhotoView *)view willRemovePhotosAtIndexes:(NSIndexSet *)indexes; + +/** The view will call this delegate method when the user selects photos and presses the delete key. The view will first call the willRemovePhotosAtIndexes: method to give + the delegate a chance to modify the behavior. If the photo array is set via bindings, the view will remove the specified photos and then call this method. Note that in that + case, the indexes passed to this method no longer have meaning because the array has already been modified. If the photos array is NOT set via bindings, the delegate should + override this method and do the appropriate removals itself. The default implementation does nothing. **/ +- (void)photoView:(MUPhotoView *)view didRemovePhotosAtIndexes:(NSIndexSet *)indexes; + +// Tool tip support +- (NSString *)photoView:(MUPhotoView *)view tooltipForPhotoAtIndex:(unsigned)index; + +@end + + +// private methods. Do not call or override. +@interface MUPhotoView (PrivateAPI) + +// set internal grid and my frame based on array size, photo size, and width +- (void)updateGridAndFrame; + +// will fetch from the internal array if not nil, from delegate otherwise +- (unsigned)photoCount; +- (NSImage *)photoAtIndex:(unsigned)index; +- (NSImage *)fastPhotoAtIndex:(unsigned)index; +- (void)updatePhotoResizing; +- (NSString *)titleAtIndex:(unsigned)index; + +// This may be the actual photo, or a fast photo, or a placeholder image +- (NSImage*) currentDisplayImageAtIndex:(unsigned)thisPhotoIndex allowsShadows:(BOOL *)allowShadows; + +// placement and hit detection + +// The central powerhouse for determining geometry distribution on a given index, with a given photo and title. +// By consolidating a lot of this stuff into one freakin' method name, we are assured that hit detection matches +// up with drawing, even as optional features like caption titles bloom... - DCJ, July 2007 +- (void)getDrawingRectsAtIndex:(unsigned)photoIndex withPhoto:(NSImage *)cellPhoto withTitle:(NSString*)title outGridRect:(NSRect *)outGridRect outPhotoRect:(NSRect *)outPhotoRect outTitleRect:(NSRect *)outTitleRect; + +- (NSSize)scaledPhotoSizeForSize:(NSSize)size; +- (NSImage *)scalePhoto:(NSImage *)image; +- (unsigned)photoIndexForPoint:(NSPoint)point; +- (NSRange)photoIndexRangeForRect:(NSRect)rect; +- (NSRect)gridRectForIndex:(unsigned)index; +- (NSRect)rectCenteredInRect:(NSRect)rect withSize:(NSSize)size; +- (NSRect)photoRectForIndex:(unsigned)index; +- (NSSize)sizeOfTitleWithCurrentAttributes:(NSString*)title; + +// selection +- (BOOL)isPhotoSelectedAtIndex:(unsigned)index; +- (NSIndexSet *)selectionIndexes; +- (void)setSelectionIndexes:(NSIndexSet *)indexes; +- (NSBezierPath *)shadowBoxPathForRect:(NSRect)rect; + +// photo removal +- (void)removePhotosAtIndexes:(NSIndexSet *)indexes; + +// scaling +- (NSImage *)scaleImage:(NSImage *)image toSize:(float)size; + +// For fast re-drawing during drag and selection +- (void)dirtyDisplayRectsForNewSelection:(NSIndexSet *)newSelection oldSelection:(NSIndexSet *)oldSelection; +@end diff --git a/MUPhotoView.m b/MUPhotoView.m new file mode 100644 index 0000000..2518dd3 --- /dev/null +++ b/MUPhotoView.m @@ -0,0 +1,2168 @@ +// +// MUPhotoView +// +// Copyright (c) 2006 Blake Seely +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// * You include a link to http://www.blakeseely.com in your final product. +// +// Version History: +// +// Version 1.0 - April 17, 2006 - Initial Release +// Version 1.1 - April 29, 2006 - Photo removal support, Added support for reduced-size drawing during live resize +// Version 1.2 - September 24, 2006 - Updated selection behavior, Changed to MIT license, Fixed issue where no images would show, fixed autoscroll + +// Modified for the iMedia project http://imedia.karelia.com/ + +#import "MUPhotoView.h" + +NSString *ShowCaptionChangedNotification = @"ShowCaptionChangedNotification"; + +@implementation MUPhotoView + +#pragma mark - +// Initializers and Dealloc +#pragma mark Initializers and Dealloc + ++ (void)initialize +{ + if ( self == [MUPhotoView class] ) + { + // Only do some work when not called because one of our subclasses does not implement +initialize + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSDictionary *defaultsBase = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithFloat:75.0], @"MUPhotoSize", nil]; + [defaults registerDefaults:defaultsBase]; + + [self exposeBinding:@"photosArray"]; + [self exposeBinding:@"selectedPhotoIndexes"]; + [self exposeBinding:@"backgroundColor"]; + [self exposeBinding:@"photoSize"]; + [self exposeBinding:@"useShadowBorder"]; + [self exposeBinding:@"useOutlineBorder"]; + [self exposeBinding:@"useShadowSelection"]; + [self exposeBinding:@"useOutlineSelection"]; + + [self setKeys:[NSArray arrayWithObject:@"backgroundColor"] triggerChangeNotificationsForDependentKey:@"shadowBoxColor"]; + + [pool release]; +} +} + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) { + + delegate = nil; + sendsLiveSelectionUpdates = NO; + useHighQualityResize = NO; + photosArray = nil; + photosFastArray = nil; + selectedPhotoIndexes = nil; + dragSelectedPhotoIndexes = [[NSMutableIndexSet alloc] init]; + + [self setBackgroundColor:[NSColor grayColor]]; + + useShadowBorder = YES; + useOutlineBorder = YES; + + borderShadow = [[NSShadow alloc] init]; + [borderShadow setShadowColor:[NSColor colorWithCalibratedWhite:0. alpha:.5]]; + [borderShadow setShadowOffset:NSMakeSize(0.0, -2.0)]; + [borderShadow setShadowBlurRadius:4.0]; + + noShadow = [[NSShadow alloc] init]; + [noShadow setShadowOffset:NSMakeSize(0,0)]; + [noShadow setShadowBlurRadius:0.0]; + [self setBorderOutlineColor:[NSColor colorWithCalibratedWhite:0.5 alpha:1.0]]; + + + useShadowSelection = NO; + useBorderSelection = YES; + [self setSelectionBorderColor:[NSColor selectedControlColor]]; + selectionBorderWidth = 3.0; + [self setShadowBoxColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.5]]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + photoSize = [defaults floatForKey:@"MUPhotoSize"]; + photoVerticalSpacing = 25.0; + photoHorizontalSpacing = 25.0; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(resetCaptionShowing:) + name:ShowCaptionChangedNotification + object:nil]; + + photoResizeTimer = nil; + photoResizeTime = [[NSDate date] retain]; + isDonePhotoResizing = YES; + } + + return self; +} + +- (void)dealloc +{ + [dragSelectedPhotoIndexes release], dragSelectedPhotoIndexes = nil; + [photoResizeTime release], photoResizeTime = nil; + + [borderShadow release], borderShadow = nil; + [noShadow release], noShadow = nil; + + [self setBorderOutlineColor:nil]; + [self setSelectionBorderColor:nil]; + [self setShadowBoxColor:nil]; + [self setBackgroundColor:nil]; + [self setPhotosArray:nil]; + [self setSelectedPhotoIndexes:nil]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +#pragma mark - +// Drawing Methods +#pragma mark Drawing Methods + +- (BOOL)isOpaque +{ + return YES; +} + +- (BOOL)isFlipped +{ + return YES; +} + +static NSDictionary *sTitleAttributes = nil; + +- (void)drawRect:(NSRect)rect +{ + [self removeAllToolTips]; + + // draw the background color + [[self backgroundColor] set]; + [NSBezierPath fillRect:rect]; + + // get the number of photos + unsigned photoCount = [self photoCount]; + if (0 == photoCount) + return; + + // update internal grid size, adjust height based on the new grid size + // because I may not find out that the photos array has changed until I draw and read the photos from the delegate, this call has to stay here + [self updateGridAndFrame]; + + // any other setup + if (useHighQualityResize) { + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + } + + /**** BEGIN Drawing Photos ****/ + NSRange rangeToDraw = [self photoIndexRangeForRect:rect]; // adjusts for photoCount if the rect goes outside my range + unsigned thisPhotoIndex; + unsigned lastIndex = rangeToDraw.location + rangeToDraw.length; + // Our version of photoIndexRangeForRect: returns one item more in the range than the MUPhotoView 1.2 version. Hence we also + // must do one less iteration so here we do < instead of <= + for (thisPhotoIndex = rangeToDraw.location; thisPhotoIndex < lastIndex; thisPhotoIndex++) { + + // Get the image at the current index - a gray bezier anywhere in the view means it asked for an image, but got nil for that index + BOOL allowShadows = YES; + NSImage* photo = [self currentDisplayImageAtIndex:thisPhotoIndex allowsShadows:&allowShadows]; + + // set it to draw correctly in a flipped view (will restore it after drawing) + BOOL isFlipped = [photo isFlipped]; + [photo setFlipped:YES]; + + NSString* title = [self titleAtIndex:thisPhotoIndex]; + NSRect gridRect = NSZeroRect; + NSRect photoRect = NSZeroRect; + NSRect titleRect = NSZeroRect; + + // Note this will automatically cause the photo to scale as necessary + [self getDrawingRectsAtIndex:thisPhotoIndex withPhoto:photo withTitle:title outGridRect:&gridRect outPhotoRect:&photoRect outTitleRect:&titleRect]; + + //**** BEGIN Background Drawing - any drawing that technically goes under the image ****/ + #if 0 // Debugging Aid - Enable this to fill each gridRect with a different gray + [[NSColor colorWithCalibratedWhite:(float)(thisPhotoIndex % 5) / 4.0 alpha:0.8] set]; + [NSBezierPath fillRect:gridRect]; + #endif + // kSelectionStyleShadowBox draws a semi-transparent rounded rect behind/around the image + if ([self isPhotoSelectedAtIndex:thisPhotoIndex] && [self useShadowSelection]) { + NSBezierPath *shadowBoxPath = [self shadowBoxPathForRect:gridRect]; + [shadowBoxColor set]; + [shadowBoxPath fill]; + } + + //**** END Background Drawing ****/ + + // kBorderStyleShadow - set the appropriate shadow + // Don't draw the shadow if we have a border and the item is selected, or if shadows are disabled for this image + if ([self useShadowBorder] && (allowShadows == YES) && + ([self useBorderSelection] == NO || [[self selectionIndexes] containsIndex:thisPhotoIndex] == NO)) { + + [borderShadow set]; + } + + // draw the current photo + NSRect imageRect = NSMakeRect(0, 0, [photo size].width, [photo size].height); + [photo drawInRect:photoRect fromRect:imageRect operation:NSCompositeSourceOver fraction:1.0]; + + // register the tooltip area + [self addToolTipRect:photoRect owner:self userData:nil]; + + // restore the photo's flipped status + [photo setFlipped:isFlipped]; + + // kBorderStyleShadow - remove the shadow after drawing the image + [noShadow set]; + + //**** BEGIN Foreground Drawing - includes outline borders, selection rectangles ****/ + if ([self isPhotoSelectedAtIndex:thisPhotoIndex] && [self useBorderSelection]) { + NSBezierPath *selectionBorder = [NSBezierPath bezierPathWithRect:NSInsetRect(photoRect,-3.0,-3.0)]; + [selectionBorder setLineWidth:[self selectionBorderWidth]]; + [[self selectionBorderColor] set]; + [selectionBorder stroke]; + } else if ([self useOutlineBorder]) { + photoRect = NSInsetRect(photoRect,0.5,0.5); // line up the 1px border so it completely fills a single row of pixels + NSBezierPath *outlinePath = [NSBezierPath bezierPathWithRect:photoRect]; + [outlinePath setLineWidth:1.0]; + [borderOutlineColor set]; + [outlinePath stroke]; + } + + //**** END Foreground Drawing ****// + + // draw title + if (title) + { + // center rect + NSMutableString *s1 = [NSMutableString stringWithString:[title substringToIndex:[title length] / 2]]; + NSMutableString *s2 = [NSMutableString stringWithString:[title substringFromIndex:[title length] / 2]]; + NSSize titleSize = [self sizeOfTitleWithCurrentAttributes:title]; + while (titleSize.width > NSWidth(titleRect)) + { + [s1 deleteCharactersInRange:NSMakeRange([s1 length] - 1, 1)]; + [s2 deleteCharactersInRange:NSMakeRange(0, 1)]; + + title = [NSString stringWithFormat:@"%@...%@", s1, s2]; + titleSize = [title sizeWithAttributes:sTitleAttributes]; + } + titleRect.origin.x = NSMidX(titleRect) - (titleSize.width / 2); + titleRect.size.width = titleSize.width; + + [title drawInRect:titleRect withAttributes:sTitleAttributes]; + } + + } + + //**** END Drawing Photos ****// + + //**** BEGIN Selection Rectangle ****// + if (mouseDown) { + [noShadow set]; + [[NSColor whiteColor] set]; + + float minX = (mouseDownPoint.x < mouseCurrentPoint.x) ? mouseDownPoint.x : mouseCurrentPoint.x; + float minY = (mouseDownPoint.y < mouseCurrentPoint.y) ? mouseDownPoint.y : mouseCurrentPoint.y; + float maxX = (mouseDownPoint.x > mouseCurrentPoint.x) ? mouseDownPoint.x : mouseCurrentPoint.x; + float maxY = (mouseDownPoint.y > mouseCurrentPoint.y) ? mouseDownPoint.y : mouseCurrentPoint.y; + NSRect selectionRectangle = NSMakeRect(minX,minY,maxX-minX,maxY-minY); + [NSBezierPath strokeRect:selectionRectangle]; + + [[NSColor colorWithDeviceRed:0.8 green:0.8 blue:0.8 alpha:0.5] set]; + [NSBezierPath fillRect:selectionRectangle]; + } + //**** END Selection Rectangle ****// + +} + +- (void)forceRedisplay +{ + [self setNeedsDisplay:YES]; +} + +- (void)setNeedsDisplayInRect:(NSRect)invalidatedRect +{ + // Make the view redraw some more pixels, to avoid the "disappearing shadows on scroll" problem + if ([[borderShadow shadowColor] alphaComponent]!=0.0) { + NSRect shadowRect = invalidatedRect; + shadowRect.origin.x += [borderShadow shadowOffset].width; + shadowRect.origin.y -= [borderShadow shadowOffset].height; + shadowRect = NSInsetRect(shadowRect, -[borderShadow shadowBlurRadius], -[borderShadow shadowBlurRadius]); + invalidatedRect = NSUnionRect(invalidatedRect, shadowRect); + } + [super setNeedsDisplayInRect:invalidatedRect]; +} + + +- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData +{ + unsigned idx = [self photoIndexForPoint:point]; + if (idx < [self photoCount]) + { + return [delegate photoView:self tooltipForPhotoAtIndex:[self photoIndexForPoint:point]]; + } + return nil; +} + + + +#pragma mark - +// Delegate Accessors +#pragma mark Delegate Accessors + +- (id)delegate +{ + return delegate; +} + +- (void)setDelegate:(id)del +{ + [self willChangeValueForKey:@"delegate"]; + delegate = del; + [self didChangeValueForKey:@"delegate"]; +} + +#pragma mark - +// Photos Methods +#pragma mark Photo Methods + +- (NSArray *)photosArray +{ + //NSLog(@"in -photosArray, returned photosArray = %@", photosArray); + return photosArray; +} + +- (void)setPhotosArray:(NSArray *)aPhotosArray +{ + //NSLog(@"in -setPhotosArray:, old value of photosArray: %@, changed to: %@", photosArray, aPhotosArray); + if (photosArray != aPhotosArray) { + [photosArray release]; + [self willChangeValueForKey:@"photosArray"]; + photosArray = [aPhotosArray mutableCopy]; + [self didChangeValueForKey:@"photosArray"]; + + // update live resize array + if (nil != photosFastArray) { + [photosFastArray release]; + } + photosFastArray = [[NSMutableArray alloc] initWithCapacity:[aPhotosArray count]]; + unsigned i; + for (i = 0; i < [photosArray count]; i++) + { + [photosFastArray addObject:[NSNull null]]; + } + + // update internal grid size, adjust height based on the new grid size + [self scrollPoint:([self frame].origin)]; + [self setNeedsDisplayInRect:[self visibleRect]]; + } +} + +#pragma mark - +// Selection Management +#pragma mark Selection Management + +- (NSIndexSet *)selectedPhotoIndexes +{ + //NSLog(@"in -selectedPhotoIndexes, returned selectedPhotoIndexes = %@", selectedPhotoIndexes); + return selectedPhotoIndexes; +} + +- (void)setSelectedPhotoIndexes:(NSIndexSet *)aSelectedPhotoIndexes +{ + //NSLog(@"in -setSelectedPhotoIndexes:, old value of selectedPhotoIndexes: %@, changed to: %@", selectedPhotoIndexes, aSelectedPhotoIndexes); + if ((selectedPhotoIndexes != aSelectedPhotoIndexes) && (![selectedPhotoIndexes isEqualToIndexSet:aSelectedPhotoIndexes])) { + + // Set the selection and send KVO + [selectedPhotoIndexes release]; + [self willChangeValueForKey:@"selectedPhotoIndexes"]; + selectedPhotoIndexes = [aSelectedPhotoIndexes copy]; + [self didChangeValueForKey:@"selectedPhotoIndexes"]; + + } +} + +#pragma mark - +// Selection Style +#pragma mark Selection Style + +- (BOOL)useBorderSelection +{ + //NSLog(@"in -useBorderSelection, returned useBorderSelection = %@", useBorderSelection ? @"YES": @"NO"); + return useBorderSelection; +} + +- (void)setUseBorderSelection:(BOOL)flag +{ + //NSLog(@"in -setUseBorderSelection, old value of useBorderSelection: %@, changed to: %@", (useBorderSelection ? @"YES": @"NO"), (flag ? @"YES": @"NO")); + [self willChangeValueForKey:@"useBorderSelection"]; + useBorderSelection = flag; + [self didChangeValueForKey:@"useBorderSelection"]; + + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +- (NSColor *)selectionBorderColor +{ + //NSLog(@"in -selectionBorderColor, returned selectionBorderColor = %@", selectionBorderColor); + return selectionBorderColor; +} + +- (void)setSelectionBorderColor:(NSColor *)aSelectionBorderColor +{ + //NSLog(@"in -setSelectionBorderColor:, old value of selectionBorderColor: %@, changed to: %@", selectionBorderColor, aSelectionBorderColor); + if (selectionBorderColor != aSelectionBorderColor) { + [selectionBorderColor release]; + [self willChangeValueForKey:@"selectionBorderColor"]; + selectionBorderColor = [aSelectionBorderColor copy]; + [self didChangeValueForKey:@"selectionBorderColor"]; + } +} + +- (BOOL)useShadowSelection +{ + //NSLog(@"in -useShadowSelection, returned useShadowSelection = %@", useShadowSelection ? @"YES": @"NO"); + return useShadowSelection; +} + +- (void)setUseShadowSelection:(BOOL)flag +{ + //NSLog(@"in -setUseShadowSelection, old value of useShadowSelection: %@, changed to: %@", (useShadowSelection ? @"YES": @"NO"), (flag ? @"YES": @"NO")); + [self willChangeValueForKey:@"useShadowSelection"]; + useShadowSelection = flag; + [self willChangeValueForKey:@"useShadowSelection"]; + + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +#pragma mark - +// Appearance +#pragma mark Appearance + +- (BOOL)useShadowBorder +{ + //NSLog(@"in -useShadowBorder, returned useShadowBorder = %@", useShadowBorder ? @"YES": @"NO"); + return useShadowBorder; +} + +- (void)setUseShadowBorder:(BOOL)flag +{ + //NSLog(@"in -setUseShadowBorder, old value of useShadowBorder: %@, changed to: %@", (useShadowBorder ? @"YES": @"NO"), (flag ? @"YES": @"NO")); + [self willChangeValueForKey:@"useShadowBorder"]; + useShadowBorder = flag; + [self didChangeValueForKey:@"useShadowBorder"]; + + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +- (BOOL)useOutlineBorder +{ + //NSLog(@"in -useOutlineBorder, returned useOutlineBorder = %@", useOutlineBorder ? @"YES": @"NO"); + return useOutlineBorder; +} + +- (void)setUseOutlineBorder:(BOOL)flag +{ + //NSLog(@"in -setUseOutlineBorder, old value of useOutlineBorder: %@, changed to: %@", (useOutlineBorder ? @"YES": @"NO"), (flag ? @"YES": @"NO")); + [self willChangeValueForKey:@"useOutlineBorder"]; + useOutlineBorder = flag; + [self didChangeValueForKey:@"useOutlineBorder"]; + + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +- (NSColor *)backgroundColor +{ + //NSLog(@"in -backgroundColor, returned backgroundColor = %@", backgroundColor); + return [[backgroundColor retain] autorelease]; +} + +- (void)setBackgroundColor:(NSColor *)aBackgroundColor +{ + //NSLog(@"in -setBackgroundColor:, old value of backgroundColor: %@, changed to: %@", backgroundColor, aBackgroundColor); + if (backgroundColor != aBackgroundColor) { + [backgroundColor release]; + [self willChangeValueForKey:@"backgroundColor"]; + backgroundColor = [aBackgroundColor copy]; + [self didChangeValueForKey:@"backgroundColor"]; + + // adjust the shadow box selection color based on the background color. values closer to white use black and vice versa + NSColor *newShadowBoxColor; + float whiteValue = 0.0; + if ([backgroundColor numberOfComponents] >= 3) { + float red, green, blue; + [backgroundColor getRed:&red green:&green blue:&blue alpha:NULL]; + whiteValue = (red + green + blue) / 3; + } else if ([backgroundColor numberOfComponents] >= 1) { + [backgroundColor getWhite:&whiteValue alpha:NULL]; + } + + if (0.5 > whiteValue) + newShadowBoxColor = [NSColor colorWithDeviceWhite:1.0 alpha:0.5]; + else + newShadowBoxColor = [NSColor colorWithDeviceWhite:0.0 alpha:0.5]; + [self setShadowBoxColor:newShadowBoxColor]; + } +} + +- (BOOL)useHighQualityResize +{ + return useHighQualityResize; +} + +- (void)setUseHighQualityResize:(BOOL)flag +{ + useHighQualityResize = flag; +} + +- (BOOL)showCaptions +{ + return showCaptions; +} + +- (void)setShowCaptions:(BOOL)flag +{ + showCaptions = flag; +} + +- (void) resetCaptionShowing:(NSNotification *)notification +{ + NSDictionary *ui = [notification userInfo]; + BOOL flag = [[ui objectForKey:@"flag"] boolValue]; + [self setShowCaptions:flag]; +} + +- (float)photoSize +{ + //NSLog(@"in -photoSize, returned photoSize = %f", photoSize); + return photoSize; +} + +- (void)setPhotoSize:(float)aPhotoSize +{ + //NSLog(@"in -setPhotoSize, old value of photoSize: %f, changed to: %f", photoSize, aPhotoSize); + [self willChangeValueForKey:@"photoSize"]; + photoSize = aPhotoSize; + [self didChangeValueForKey:@"photoSize"]; + + // update internal grid size, adjust height based on the new grid size + // to make sure the same photos stay in view, get a visible photos' index, then scroll to that photo after the update + NSRect visibleRect = [self visibleRect]; + float heightRatio = visibleRect.origin.y / [self frame].size.height; + visibleRect.origin.y = heightRatio * [self frame].size.height; + [self scrollRectToVisible:visibleRect]; + + [self viewWillStartLiveResize]; + + [self setNeedsDisplayInRect:[self visibleRect]]; + + // update time for live resizing + if (nil != photoResizeTime) { + [photoResizeTime release]; + photoResizeTime = nil; + } + isDonePhotoResizing = NO; + photoResizeTime = [[NSDate date] retain]; + + + if (photoResizeTimer) { + [photoResizeTimer invalidate]; + photoResizeTimer = nil; + } + + // note that the timer retains the target + photoResizeTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 + target:self + selector:@selector(updatePhotoResizing) + userInfo:nil + repeats:YES]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setFloat:aPhotoSize forKey:@"MUPhotoSize"]; +} + +- (IBAction)takePhotoSizeFrom:(id)sender // allow hooking up to a slider +{ + if ([sender respondsToSelector:@selector(doubleValue)]) + { + mouseCurrentPoint = mouseDownPoint = NSZeroPoint; + [self setPhotoSize:[sender doubleValue]]; + //fake a bounds resize notification + [[NSNotificationCenter defaultCenter] postNotificationName:NSViewFrameDidChangeNotification + object:self]; + if ([[self selectionIndexes] count] > 0) + { + unsigned lastSelectedIndex = [[self selectionIndexes] lastIndex]; + NSRect r = [self photoRectForIndex:lastSelectedIndex]; + r.origin.y -= photoVerticalSpacing; + r.size.height += photoVerticalSpacing; + + [self scrollRectToVisible:r]; + } + } +} + +#pragma mark - +// Don't Mess With Texas +#pragma mark Don't Mess With Texas +// haven't tested changing these behaviors yet - there's no reason they shouldn't work... but use at your own risk. + +- (float)photoVerticalSpacing +{ + //NSLog(@"in -photoVerticalSpacing, returned photoVerticalSpacing = %f", photoVerticalSpacing); + return photoVerticalSpacing; +} + +- (void)setPhotoVerticalSpacing:(float)aPhotoVerticalSpacing +{ + //NSLog(@"in -setPhotoVerticalSpacing, old value of photoVerticalSpacing: %f, changed to: %f", photoVerticalSpacing, aPhotoVerticalSpacing); + [self willChangeValueForKey:@"photoVerticalSpacing"]; + photoVerticalSpacing = aPhotoVerticalSpacing; + [self didChangeValueForKey:@"photoVertificalSpacing"]; + + // update internal grid size, adjust height based on the new grid size + NSRect visibleRect = [self visibleRect]; + float heightRatio = visibleRect.origin.y / [self frame].size.height; + visibleRect.origin.y = heightRatio * [self frame].size.height; + [self scrollRectToVisible:visibleRect]; + [self setNeedsDisplayInRect:[self visibleRect]]; + + + // update time for live resizing + if (nil != photoResizeTime) { + [photoResizeTime release]; + photoResizeTime = nil; + } + isDonePhotoResizing = NO; + photoResizeTime = [[NSDate date] retain]; + if (nil == photoResizeTimer) { + // the timer retains the target + photoResizeTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 + target:self + selector:@selector(updatePhotoResizing) + userInfo:nil + repeats:YES]; + } +} + +- (float)photoHorizontalSpacing +{ + //NSLog(@"in -photoHorizontalSpacing, returned photoHorizontalSpacing = %f", photoHorizontalSpacing); + return photoHorizontalSpacing; +} + +- (void)setPhotoHorizontalSpacing:(float)aPhotoHorizontalSpacing +{ + //NSLog(@"in -setPhotoHorizontalSpacing, old value of photoHorizontalSpacing: %f, changed to: %f", photoHorizontalSpacing, aPhotoHorizontalSpacing); + [self willChangeValueForKey:@"photoHorizontalSpacing"]; + photoHorizontalSpacing = aPhotoHorizontalSpacing; + [self didChangeValueForKey:@"photoHorizontalSpacing"]; + + // update internal grid size, adjust height based on the new grid size + NSRect visibleRect = [self visibleRect]; + float heightRatio = visibleRect.origin.y / [self frame].size.height; + visibleRect.origin.y = heightRatio * [self frame].size.height; + [self scrollRectToVisible:visibleRect]; + [self setNeedsDisplayInRect:[self visibleRect]]; + + // update time for live resizing + if (nil != photoResizeTime) { + [photoResizeTime release]; + photoResizeTime = nil; + } + isDonePhotoResizing = NO; + photoResizeTime = [[NSDate date] retain]; + if (nil == photoResizeTimer) { + // the timer retains the target + photoResizeTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 + target:self + selector:@selector(updatePhotoResizing) + userInfo:nil + repeats:YES]; + } +} + + +- (NSColor *)borderOutlineColor +{ + //NSLog(@"in -borderOutlineColor, returned borderOutlineColor = %@", borderOutlineColor); + return borderOutlineColor; +} + +- (void)setBorderOutlineColor:(NSColor *)aBorderOutlineColor +{ + //NSLog(@"in -setBorderOutlineColor:, old value of borderOutlineColor: %@, changed to: %@", borderOutlineColor, aBorderOutlineColor); + if (borderOutlineColor != aBorderOutlineColor) { + [borderOutlineColor release]; + [self willChangeValueForKey:@"borderOutlineColor"]; + borderOutlineColor = [aBorderOutlineColor copy]; + [self didChangeValueForKey:@"borderOutlineColor"]; + + [self setNeedsDisplayInRect:[self visibleRect]]; + } +} + +- (NSColor *)shadowBoxColor +{ + //NSLog(@"in -shadowBoxColor, returned shadowBoxColor = %@", shadowBoxColor); + return shadowBoxColor; +} + +- (void)setShadowBoxColor:(NSColor *)aShadowBoxColor +{ + //NSLog(@"in -setShadowBoxColor:, old value of shadowBoxColor: %@, changed to: %@", shadowBoxColor, aShadowBoxColor); + if (shadowBoxColor != aShadowBoxColor) { + [shadowBoxColor release]; + shadowBoxColor = [aShadowBoxColor copy]; + + [self setNeedsDisplayInRect:[self visibleRect]]; + } + +} +- (float)selectionBorderWidth +{ + //NSLog(@"in -selectionBorderWidth, returned selectionBorderWidth = %f", selectionBorderWidth); + return selectionBorderWidth; +} + +- (void)setSelectionBorderWidth:(float)aSelectionBorderWidth +{ + //NSLog(@"in -setSelectionBorderWidth, old value of selectionBorderWidth: %f, changed to: %f", selectionBorderWidth, aSelectionBorderWidth); + selectionBorderWidth = aSelectionBorderWidth; +} + + +#pragma mark - +// Mouse Event Methods +#pragma mark Mouse Event Methods + +- (void) mouseDown:(NSEvent *) event +{ + mouseDown = YES; + mouseDownPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + mouseCurrentPoint = mouseDownPoint; + + unsigned clickedIndex = [self photoIndexForPoint:mouseDownPoint]; + NSRect photoRect = [self photoRectForIndex:clickedIndex]; + unsigned int flags = [event modifierFlags]; + NSMutableIndexSet* indexes = [[self selectionIndexes] mutableCopy]; + BOOL imageHit = NSPointInRect(mouseDownPoint, photoRect); + + if (imageHit) { + if (flags & NSCommandKeyMask) { + // Flip current image selection state. + if ([indexes containsIndex:clickedIndex]) { + [indexes removeIndex:clickedIndex]; + } else { + [indexes addIndex:clickedIndex]; + } + } else { + if (flags & NSShiftKeyMask) { + // Add range to selection. + if ([indexes count] == 0) { + [indexes addIndex:clickedIndex]; + } else { + unsigned int origin = (clickedIndex < [indexes lastIndex]) ? clickedIndex :[indexes lastIndex]; + unsigned int length = (clickedIndex < [indexes lastIndex]) ? [indexes lastIndex] - clickedIndex : clickedIndex - [indexes lastIndex]; + + length++; + [indexes addIndexesInRange:NSMakeRange(origin, length)]; + } + } else { + if (![self isPhotoSelectedAtIndex:clickedIndex]) { + // Photo selection without modifiers. + [indexes removeAllIndexes]; + [indexes addIndex:clickedIndex]; + } + } + } + + potentialDragDrop = YES; + } else { + if ((flags & NSShiftKeyMask) == 0) { + [indexes removeAllIndexes]; + } + potentialDragDrop = NO; + } + + [self setSelectionIndexes:indexes]; + [indexes release]; +} + +- (void)mouseDragged:(NSEvent *)event +{ + if (0 == columns) return; + mouseCurrentPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + + // if the mouse has moved less than 5px in either direction, don't register the drag yet + float xFromStart = fabs((mouseDownPoint.x - mouseCurrentPoint.x)); + float yFromStart = fabs((mouseDownPoint.y - mouseCurrentPoint.y)); + if ((xFromStart < 5) && (yFromStart < 5)) { + return; + + } else if (potentialDragDrop && (nil != delegate)) { + // create a drag image + unsigned clickedIndex = [self photoIndexForPoint:mouseDownPoint]; + NSImage *clickedImage = [self photoAtIndex:clickedIndex]; + BOOL flipped = [clickedImage isFlipped]; + [clickedImage setFlipped:YES]; + NSSize scaledSize = [self scaledPhotoSizeForSize:[clickedImage size]]; + if (nil == clickedImage) { // creates a red image, which should let the user/developer know something is wrong + clickedImage = [[[NSImage alloc] initWithSize:NSMakeSize(photoSize,photoSize)] autorelease]; + [clickedImage lockFocus]; + [[NSColor redColor] set]; + [NSBezierPath fillRect:NSMakeRect(0,0,photoSize,photoSize)]; + [clickedImage unlockFocus]; + } + NSImage *dragImage = [[NSImage alloc] initWithSize:scaledSize]; + + // draw the drag image as a semi-transparent copy of the image the user dragged, and optionally a red badge indicating the number of photos + [dragImage lockFocus]; + [clickedImage drawInRect:NSMakeRect(0,0,scaledSize.width,scaledSize.height) fromRect:NSMakeRect(0,0,[clickedImage size].width,[clickedImage size].height) operation:NSCompositeCopy fraction:0.7]; + [dragImage unlockFocus]; + + [clickedImage setFlipped:flipped]; + + // if there's more than one image, put a badge on the photo + if ([[self selectionIndexes] count] > 1) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; + [attributes setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + [attributes setObject:[NSFont fontWithName:@"Helvetica" size:14] forKey:NSFontAttributeName]; + NSAttributedString *badgeString = [[NSAttributedString alloc] initWithString:[[NSNumber numberWithInt:[[self selectionIndexes] count]] stringValue] attributes:attributes]; + NSSize stringSize = [badgeString size]; + int diameter = stringSize.width; + if (stringSize.height > diameter) diameter = stringSize.height; + diameter += 5; + + // calculate the badge circle + int maxY = [dragImage size].height - 5; + int maxX = [dragImage size].width - 5; + int minY = maxY - diameter; + int minX = maxX - diameter; + NSBezierPath *circle = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(minX,minY,maxX-minX,maxY-minY)]; + + // draw the string + NSPoint point; + point.x = maxX - ((maxX - minX) / 2) - 1 - (stringSize.width / 2); + point.y = maxY - diameter + (stringSize.height / 2) - 6; + + NSAffineTransform *t = [NSAffineTransform transform]; + [t translateXBy:0 yBy:maxY]; + [t scaleXBy:1 yBy:-1]; + + [dragImage lockFocus]; + [t concat]; + [[NSColor colorWithDeviceRed:1 green:0.1 blue:0.1 alpha:0.7] set]; + [circle fill]; + [badgeString drawAtPoint:point]; + [t invert]; + [t concat]; + [dragImage unlockFocus]; + + [badgeString release]; + [attributes release]; + } + + [dragImage setFlipped:YES]; + + // get the pasteboard and register the returned types with delegate as the owner + NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pb declareTypes:[NSArray array] owner:nil]; // clear the pasteboard + [delegate photoView:self fillPasteboardForDrag:pb]; + + // place the cursor in the center of the drag image + NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil]; + NSSize imageSize = [dragImage size]; + p.x = p.x - imageSize.width / 2; + p.y = p.y + imageSize.height / 2; + + [self dragImage:dragImage at:p offset:NSZeroSize event:event pasteboard:pb source:self slideBack:YES]; + + [dragImage release]; + + } else { + // adjust the mouse current point so that it's not outside the frame + NSRect frameRect = [self frame]; + if (mouseCurrentPoint.x < NSMinX(frameRect)) + mouseCurrentPoint.x = NSMinX(frameRect); + if (mouseCurrentPoint.x > NSMaxX(frameRect)) + mouseCurrentPoint.x = NSMaxX(frameRect); + if (mouseCurrentPoint.y < NSMinY(frameRect)) + mouseCurrentPoint.y = NSMinY(frameRect); + if (mouseCurrentPoint.y > NSMaxY(frameRect)) + mouseCurrentPoint.y = NSMaxY(frameRect); + + // determine the rect for the current drag area + float minX, maxX, minY, maxY; + minX = (mouseCurrentPoint.x < mouseDownPoint.x) ? mouseCurrentPoint.x : mouseDownPoint.x; + minY = (mouseCurrentPoint.y < mouseDownPoint.y) ? mouseCurrentPoint.y : mouseDownPoint.y; + maxX = (mouseCurrentPoint.x > mouseDownPoint.x) ? mouseCurrentPoint.x : mouseDownPoint.x; + maxY = (mouseCurrentPoint.y > mouseDownPoint.y) ? mouseCurrentPoint.y : mouseDownPoint.y; + if (maxY > NSMaxY(frameRect)) + maxY = NSMaxY(frameRect); + if (maxX > NSMaxX(frameRect)) + maxX = NSMaxX(frameRect); + + NSRect selectionRect = NSMakeRect(minX,minY,maxX-minX,maxY-minY); + + unsigned minIndex = [self photoIndexForPoint:NSMakePoint(minX, minY)]; + unsigned xRun = [self photoIndexForPoint:NSMakePoint(maxX, minY)] - minIndex + 1; + unsigned yRun = [self photoIndexForPoint:NSMakePoint(minX, maxY)] - minIndex + 1; + unsigned selectedRows = (yRun / columns); + + // Save the current selection (if any), then populate the drag indexes + // this allows us to shift band select to add to the current selection. + [dragSelectedPhotoIndexes removeAllIndexes]; + [dragSelectedPhotoIndexes addIndexes:[self selectionIndexes]]; + + // add indexes in the drag rectangle + unsigned i; + for (i = 0; i <= selectedRows; i++) { + unsigned rowStartIndex = (i * columns) + minIndex; + unsigned j; + for (j = rowStartIndex; j < (rowStartIndex + xRun); j++) { + if (NSIntersectsRect([self photoRectForIndex:j],selectionRect)) + [dragSelectedPhotoIndexes addIndex:j]; + } + } + + // if requested, set the selection. this could cause a rapid series of KVO notifications, so if this is false, the view tracks + // the selection internally, but doesn't pass it to the bindings or the delegates until the drag is over. + // This will cause an appropriate redraw. + if (sendsLiveSelectionUpdates) + { + [self setSelectionIndexes:dragSelectedPhotoIndexes]; + } + + // autoscrolling + if (autoscrollTimer == nil) { + // the timer retains the target: must invalidate or dealloc wont be called on the photo view! + autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 + target:self + selector:@selector(autoscroll) + userInfo:nil + repeats:YES]; + } + + [[self superview] autoscroll:event]; + + [self setNeedsDisplayInRect:[self visibleRect]]; + } + +} + + +- (void)mouseUp:(NSEvent *)event +{ + // Double-click Handling + if ([event clickCount] == 2) { + // There could be more than one selected photo. In that case, call the delegates doubleClickOnPhotoAtIndex routine for + // each selected photo. + unsigned int selectedIndex = [[self selectionIndexes] firstIndex]; + while (selectedIndex != NSNotFound) { + [delegate photoView:self doubleClickOnPhotoAtIndex:selectedIndex withFrame:[self photoRectForIndex:selectedIndex]]; + selectedIndex = [[self selectionIndexes] indexGreaterThanIndex:selectedIndex]; + } + } + else if (0 < [dragSelectedPhotoIndexes count]) { // finishing a drag selection + // move the drag indexes into the main selection indexes - firing off KVO messages or delegate messages + [self setSelectionIndexes:dragSelectedPhotoIndexes]; + [dragSelectedPhotoIndexes removeAllIndexes]; + } + + if (autoscrollTimer != nil) { + [autoscrollTimer invalidate]; + autoscrollTimer = nil; + } + + mouseDown = NO; + mouseCurrentPoint = mouseDownPoint = NSZeroPoint; + + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal +{ + if (nil != delegate) + return [delegate photoView:self draggingSourceOperationMaskForLocal:isLocal]; + else + return NSDragOperationNone; +} + +- (void)autoscroll +{ + mouseCurrentPoint = [self convertPoint:[[NSApp currentEvent] locationInWindow] fromView:nil]; + [[self superview] autoscroll:[NSApp currentEvent]]; + + [self mouseDragged:[NSApp currentEvent]]; +} + + +- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation +{ + if (operation == NSDragOperationDelete) + [self removePhotosAtIndexes:[self selectionIndexes]]; +} + + + +#pragma mark - +#pragma mark Drag Receiving + +- (NSDragOperation)draggingEntered:(id )sender +{ + if ([delegate respondsToSelector:@selector(photoView:draggingEntered:)]) + { + NSDragOperation result = [delegate photoView:self draggingEntered:sender]; + if (result != NSDragOperationNone) + { + drawDropHilite = YES; + [self setNeedsDisplay:YES]; + } + return result; + } + else + return NSDragOperationNone; +} + + +- (void)draggingExited:(id )sender +{ + if ([delegate respondsToSelector:@selector(photoView:draggingExited:)]) + [delegate photoView:self draggingExited:sender]; + + if (drawDropHilite) + { + drawDropHilite = NO; + [self setNeedsDisplay:YES]; + } +} + + +- (BOOL)prepareForDragOperation:(id )sender +{ + BOOL result; + if ([delegate respondsToSelector:@selector(photoView:prepareForDragOperation:)]) + result = [delegate photoView:self prepareForDragOperation:sender]; + else + result = YES; + + if (drawDropHilite) + { + drawDropHilite = NO; + [self setNeedsDisplay:YES]; + } + return result; +} + +- (BOOL)performDragOperation:(id )sender +{ + if ([delegate respondsToSelector:@selector(photoView:performDragOperation:)]) + return [delegate photoView:self performDragOperation:sender]; + else + return NO; +} + +- (void)concludeDragOperation:(id )sender +{ + if ([delegate respondsToSelector:@selector(photoView:concludeDragOperation:)]) + [delegate photoView:self concludeDragOperation:sender]; +} + + + +#pragma mark - +// Responder Method +#pragma mark Responder Methods + +- (BOOL)acceptsFirstResponder +{ + return([self photoCount] > 0); +} + +- (BOOL)resignFirstResponder +{ + [self setNeedsDisplay:YES]; + return YES; +} + +- (BOOL)becomeFirstResponder +{ + [self setNeedsDisplay:YES]; + return YES; +} + +- (void)keyDown:(NSEvent *)theEvent +{ + NSString* eventKey = [theEvent charactersIgnoringModifiers]; + unichar keyChar = 0; + + if ([eventKey length] == 1) + { + keyChar = [eventKey characterAtIndex:0]; + if (keyChar == ' ') + { + unsigned int selectedIndex = [[self selectionIndexes] firstIndex]; + + while (selectedIndex != NSNotFound) + { + [delegate photoView:self doubleClickOnPhotoAtIndex:selectedIndex withFrame:[self photoRectForIndex:selectedIndex]]; + selectedIndex = [[self selectionIndexes] indexGreaterThanIndex:selectedIndex]; + } + return; + } + else if ((keyChar == NSCarriageReturnCharacter) || (keyChar == NSEnterCharacter)) { + [super keyDown:theEvent]; + return; + } + } + + + [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; +} + +- (void)deleteBackward:(id)sender +{ + if (0 < [[self selectionIndexes] count]) { + [self removePhotosAtIndexes:[self selectionIndexes]]; + } +} + +- (void)selectAll:(id)sender +{ + if (0 < [self photoCount]) { + NSIndexSet *allIndexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, [self photoCount])]; + [self setSelectionIndexes:allIndexes]; + [allIndexes release]; + } +} + +- (void)insertTab:(id)sender +{ + [[self window] selectKeyViewFollowingView:self]; +} + +- (void)insertBackTab:(id)sender +{ + [[self window] selectKeyViewPrecedingView:self]; +} + +- (void)moveLeft:(id)sender +{ + NSIndexSet* indexes = [self selectionIndexes]; + NSMutableIndexSet* newIndexes = [[NSMutableIndexSet alloc] init]; + + if (([indexes count] > 0) && (![indexes containsIndex:0])) + { + [newIndexes addIndex:[indexes firstIndex] - 1]; + } + else + { + if ((([indexes count] == 0) || ([indexes count] == [self photoCount])) && ([self photoCount] > 0)) + { + [newIndexes addIndex:[self photoCount] - 1]; + } + } + + if ([newIndexes count] > 0) + { + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes firstIndex]]]; + } + + [newIndexes release]; +} + +- (void)moveLeftAndModifySelection:(id)sender +{ + NSIndexSet *indexes = [self selectionIndexes]; + if (([indexes count] > 0) && (![indexes containsIndex:0])) { + NSMutableIndexSet *newIndexes = [indexes mutableCopy]; + [newIndexes addIndex:([newIndexes firstIndex] - 1)]; + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes firstIndex]]]; + [newIndexes release]; + } +} + +- (void)moveRight:(id)sender +{ + NSIndexSet* indexes = [self selectionIndexes]; + NSMutableIndexSet* newIndexes = [[NSMutableIndexSet alloc] init]; + + if (([indexes count] > 0) && (![indexes containsIndex:[self photoCount] - 1])) + { + [newIndexes addIndex:[indexes lastIndex] + 1]; + } + else + { + if ((([indexes count] == 0) || ([indexes count] == [self photoCount])) && ([self photoCount] > 0)) + { + [newIndexes addIndex:0]; + } + } + + if ([newIndexes count] > 0) + { + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes lastIndex]]]; + } + + [newIndexes release]; +} + +- (void)moveRightAndModifySelection:(id)sender +{ + NSIndexSet *indexes = [self selectionIndexes]; + if (([indexes count] > 0) && (![indexes containsIndex:([self photoCount] - 1)])) { + NSMutableIndexSet *newIndexes = [indexes mutableCopy]; + [newIndexes addIndex:([newIndexes lastIndex] + 1)]; + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes lastIndex]]]; + [newIndexes release]; + } +} + +- (void)moveDown:(id)sender +{ + NSIndexSet* indexes = [self selectionIndexes]; + NSMutableIndexSet* newIndexes = [[NSMutableIndexSet alloc] init]; + unsigned int destinationIndex = [indexes lastIndex] + columns; + unsigned int lastIndex = [self photoCount] - 1; + + if (([indexes count] > 0) && (destinationIndex <= lastIndex)) + { + [newIndexes addIndex:destinationIndex]; + } + else + { + if ((([indexes count] == 0) || ([indexes count] == [self photoCount])) && ([self photoCount] > 0)) + { + [newIndexes addIndex:0]; + } + } + + if ([newIndexes count] > 0) + { + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes lastIndex]]]; + } + + [newIndexes release]; +} + +- (void)moveDownAndModifySelection:(id)sender +{ + NSIndexSet *indexes = [self selectionIndexes]; + unsigned int destinationIndex = [indexes lastIndex] + columns; + unsigned int lastIndex = [self photoCount] - 1; + + if (([indexes count] > 0) && (destinationIndex <= lastIndex)) { + NSMutableIndexSet *newIndexes = [indexes mutableCopy]; + NSRange addRange; + addRange.location = [indexes lastIndex] + 1; + addRange.length = columns; + [newIndexes addIndexesInRange:addRange]; + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes lastIndex]]]; + [newIndexes release]; + } +} + +- (void)moveUp:(id)sender +{ + NSIndexSet* indexes = [self selectionIndexes]; + NSMutableIndexSet* newIndexes = [[NSMutableIndexSet alloc] init]; + + if (([indexes count] > 0) && ([indexes firstIndex] >= columns)) + { + [newIndexes addIndex:[indexes firstIndex] - columns]; + } + else + { + if ((([indexes count] == 0) || ([indexes count] == [self photoCount])) && ([self photoCount] > 0)) + { + [newIndexes addIndex:[self photoCount] - 1]; + } + } + + if ([newIndexes count] > 0) + { + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:[newIndexes firstIndex]]]; + } + + [newIndexes release]; +} + +- (void)moveUpAndModifySelection:(id)sender +{ + NSMutableIndexSet *indexes = [[self selectionIndexes] mutableCopy]; + if (([indexes count] > 0) && ([indexes firstIndex] >= columns)) { + [indexes addIndexesInRange:NSMakeRange(([indexes firstIndex] - columns), columns + 1)]; + [self setSelectionIndexes:indexes]; + [self scrollRectToVisible:[self gridRectForIndex:[indexes firstIndex]]]; + } + [indexes release]; +} + +- (void)scrollToEndOfDocument:(id)sender +{ + [self scrollRectToVisible:[self gridRectForIndex:([self photoCount] - 1)]]; +} + +- (void)scrollToBeginningOfDocument:(id)sender +{ + [self scrollPoint:NSZeroPoint]; +} + +- (void)scrollPageDown:(id)sender +{ + NSScrollView* scrollView = [self enclosingScrollView]; + NSRect r = [scrollView documentVisibleRect]; + [self scrollPoint:NSMakePoint(NSMinX(r), NSMaxY(r) - [scrollView verticalPageScroll])]; +} + +- (void)scrollPageUp:(id)sender +{ + NSScrollView* scrollView = [self enclosingScrollView]; + NSRect r = [scrollView documentVisibleRect]; + [self scrollPoint:NSMakePoint(NSMinX(r), (NSMinY(r) - NSHeight(r)) + [scrollView verticalPageScroll])]; +} + +- (void)moveToEndOfLine:(id)sender +{ + NSIndexSet *indexes = [self selectionIndexes]; + if ([indexes count] > 0) { + unsigned int destinationIndex = ([indexes lastIndex] + columns) - ([indexes lastIndex] % columns) - 1; + if (destinationIndex >= [self photoCount]) { + destinationIndex = [self photoCount] - 1; + } + NSIndexSet *newIndexes = [[NSIndexSet alloc] initWithIndex:destinationIndex]; + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:destinationIndex]]; + [newIndexes release]; + } +} + +- (void)moveToEndOfLineAndModifySelection:(id)sender +{ + NSMutableIndexSet *indexes = [[self selectionIndexes] mutableCopy]; + if ([indexes count] > 0) { + unsigned int destinationIndexPlusOne = ([indexes lastIndex] + columns) - ([indexes lastIndex] % columns); + if (destinationIndexPlusOne >= [self photoCount]) { + destinationIndexPlusOne = [self photoCount]; + } + [indexes addIndexesInRange:NSMakeRange(([indexes lastIndex]), (destinationIndexPlusOne - [indexes lastIndex]))]; + [self setSelectionIndexes:indexes]; + [self scrollRectToVisible:[self gridRectForIndex:[indexes lastIndex]]]; + } + [indexes release]; +} + +- (void)moveToBeginningOfLine:(id)sender +{ + NSIndexSet *indexes = [self selectionIndexes]; + if ([indexes count] > 0) { + unsigned int destinationIndex = [indexes firstIndex] - ([indexes firstIndex] % columns); + NSIndexSet *newIndexes = [[NSIndexSet alloc] initWithIndex:destinationIndex]; + [self setSelectionIndexes:newIndexes]; + [self scrollRectToVisible:[self gridRectForIndex:destinationIndex]]; + [newIndexes release]; + } +} + +- (void)moveToBeginningOfLineAndModifySelection:(id)sender +{ + NSMutableIndexSet *indexes = [[self selectionIndexes] mutableCopy]; + if ([indexes count] > 0) { + unsigned int destinationIndex = [indexes firstIndex] - ([indexes firstIndex] % columns); + [indexes addIndexesInRange:NSMakeRange(destinationIndex, ([indexes firstIndex] - destinationIndex))]; + [self setSelectionIndexes:indexes]; + [self scrollRectToVisible:[self gridRectForIndex:destinationIndex]]; + } + [indexes release]; +} + +- (void)moveToBeginningOfDocument:(id)sender +{ + if (0 < [self photoCount]) { + [self setSelectionIndexes:[NSIndexSet indexSetWithIndex:0]]; + [self scrollPoint:NSZeroPoint]; + } +} + +- (void)moveToBeginningOfDocumentAndModifySelection:(id)sender +{ + NSMutableIndexSet *indexes = [[self selectionIndexes] mutableCopy]; + if ([indexes count] > 0) { + [indexes addIndexesInRange:NSMakeRange(0, [indexes firstIndex])]; + [self setSelectionIndexes:indexes]; + [self scrollRectToVisible:NSZeroRect]; + } + [indexes release]; +} + +- (void)moveToEndOfDocument:(id)sender +{ + if (0 < [self photoCount]) { + [self setSelectionIndexes:[NSIndexSet indexSetWithIndex:([self photoCount] - 1)]]; + [self scrollRectToVisible:[self gridRectForIndex:([self photoCount] - 1)]]; + } +} + +- (void)moveToEndOfDocumentAndModifySelection:(id)sender +{ + NSMutableIndexSet *indexes = [[self selectionIndexes] mutableCopy]; + if ([indexes count] > 0) { + [indexes addIndexesInRange:NSMakeRange([indexes lastIndex], ([self photoCount] - [indexes lastIndex]))]; + [self setSelectionIndexes:indexes]; + [self scrollRectToVisible:[self gridRectForIndex:[indexes lastIndex]]]; + } +} + +@end + + +#pragma mark - +// Delegate Default Implementations +#pragma mark Delegate Default Implementations + +@implementation NSObject (MUPhotoViewDelegate) + +// will only get called if photoArray has not been set, or has not been bound +- (unsigned)photoCountForPhotoView:(MUPhotoView *)view +{ + return 0; +} + +- (NSImage *)photoView:(MUPhotoView *)view photoAtIndex:(unsigned)photoIndex +{ + return nil; +} + +- (NSImage *)photoView:(MUPhotoView *)view fastPhotoAtIndex:(unsigned)photoIndex +{ + return [self photoView:view photoAtIndex:photoIndex]; +} + +- (NSString *)photoView:(MUPhotoView *)view titleForPhotoAtIndex:(unsigned)photoIndex +{ + return nil; +} + +// selection +- (NSIndexSet *)selectionIndexesForPhotoView:(MUPhotoView *)view +{ + return [NSIndexSet indexSet]; +} + +- (NSIndexSet *)photoView:(MUPhotoView *)view willSetSelectionIndexes:(NSIndexSet *)indexes +{ + return indexes; +} + +- (void)photoView:(MUPhotoView *)view didSetSelectionIndexes:(NSIndexSet *)indexes +{ +} + +// drag and drop +- (NSDragOperation)photoView:(MUPhotoView *)view draggingSourceOperationMaskForLocal:(BOOL)isLocal +{ + return NSDragOperationNone; +} + +- (NSArray *)pasteboardDragTypesForPhotoView:(MUPhotoView *)view +{ + return [[[NSArray alloc] init] autorelease]; +} + +- (NSData *)photoView:(MUPhotoView *)view pasteboardDataForPhotoAtIndex:(unsigned)photoIndex dataType:(NSString *)type +{ + return nil; +} + +// double-click +- (void)photoView:(MUPhotoView *)view doubleClickOnPhotoAtIndex:(unsigned)photoIndex withFrame:(NSRect)frame +{ + +} + +// photo removal support +- (NSIndexSet *)photoView:(MUPhotoView *)view willRemovePhotosAtIndexes:(NSIndexSet *)indexes +{ + return [NSIndexSet indexSet]; +} + +- (void)photoView:(MUPhotoView *)view didRemovePhotosAtIndexes:(NSIndexSet *)indexes +{ + +} + +- (NSString *)photoView:(MUPhotoView *)view tooltipForPhotoAtIndex:(unsigned)photoIndex +{ + return nil; +} + +- (NSDragOperation)photoView:(MUPhotoView *)view draggingEntered:(id )sender +{ + return NSDragOperationNone; +} + +- (void)photoView:(MUPhotoView *)view draggingExited:(id )sender +{ +} + +- (BOOL)photoView:(MUPhotoView *)view performDragOperation:(id )sender +{ + return NO; +} + +- (BOOL)photoView:(MUPhotoView *)view prepareForDragOperation:(id )sender +{ + return YES; +} + +- (void)photoView:(MUPhotoView *)view concludeDragOperation:(id )sender +{ + +} + +- (void)photoView:(MUPhotoView *)view fillPasteboardForDrag:(NSPasteboard *)pboard +{ + +} + +@end + +#pragma mark - +// Private +#pragma mark Private + +@implementation MUPhotoView (PrivateAPI) + +- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent +{ + NSPoint mouseEventLocation; + + mouseEventLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + unsigned clickedIndex = [self photoIndexForPoint:mouseEventLocation]; + NSRect photoRect = [self photoRectForIndex:clickedIndex]; + + return(NSPointInRect(mouseEventLocation, photoRect)); +} + +- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent +{ + // CEsfahani - If acceptsFirstMouse unconditionally returns YES, then it is possible to lose the selection if + // the user clicks in the content of the window without hitting one of the selected images. This is + // the Finder's behavior, and it bothers me. + // It seems I have two options: unconditionally return YES, or only return YES if we clicked in an image. + // But, does anyone rely on losing the selection if I bring a window forward? + + NSPoint mouseEventLocation; + + mouseEventLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + unsigned clickedIndex = [self photoIndexForPoint:mouseEventLocation]; + NSRect photoRect = [self photoRectForIndex:clickedIndex]; + + return NSPointInRect(mouseEventLocation, photoRect); +} + +// This stops the stuttering of the movie view when changing the photo sizes from the slider +- (void)viewWillStartLiveResize +{ + if (nil == liveResizeSubviews) + { + // remove all subviews + liveResizeSubviews = [[NSArray arrayWithArray:[self subviews]] retain]; + NSEnumerator *e = [liveResizeSubviews objectEnumerator]; + NSView *cur; + + while (cur = [e nextObject]) + { + [cur removeFromSuperview]; + } + } +} + +- (void)viewDidEndLiveResize +{ + if (nil != liveResizeSubviews) + { + + NSEnumerator *e = [liveResizeSubviews objectEnumerator]; + NSView *cur; + + while (cur = [e nextObject]) + { + [self addSubview:cur]; + } + [liveResizeSubviews release]; + liveResizeSubviews = nil; + } + [self setNeedsDisplayInRect:[self visibleRect]]; +} + +- (void)setFrame:(NSRect)frame +{ + float width = [self frame].size.width; + [super setFrame:frame]; + + if (width != frame.size.width) { + // update internal grid size, adjust height based on the new grid size + [self setNeedsDisplayInRect:[self visibleRect]]; + } +} + +- (void)updateGridAndFrame +{ + /**** BEGIN Dimension calculations and adjustments ****/ + + // get the number of photos + unsigned photoCount = [self photoCount]; + + // calculate the base grid size + gridSize.height = [self photoSize] + [self photoVerticalSpacing]; + gridSize.width = [self photoSize] + [self photoHorizontalSpacing]; + + if ([self showCaptions]) + { + gridSize.height += [self sizeOfTitleWithCurrentAttributes:@"Example"].height; + } + + // if there are no photos, return + if (0 == photoCount) { + columns = 0; + rows = 0; + float width = [self frame].size.width; + float height = [[[self enclosingScrollView] contentView] frame].size.height; + [self setFrameSize:NSMakeSize(width, height)]; + return; + } + + // calculate the number of columns (ivar) + float width = [self frame].size.width; + columns = width / gridSize.width; + + // minimum 1 column + if (1 > columns) + columns = 1; + + // if we have fewer photos than columns, adjust downward + // This behaviour is incorrect - a single row will be evenly + // spaced instead of left justified. Comment out the + // conditional below to get the arguably correct behav. + if (photoCount < columns) + columns = photoCount; + + // adjust the grid size width for extra space + gridSize.width += (width - (columns * gridSize.width)) / columns; + + // calculate the number of rows of photos based on the total count and the number of columns (ivar) + rows = photoCount / columns; + if (0 < (photoCount % columns)) + rows++; + // adjust my frame height to contain all the photos + float height = rows * gridSize.height; + NSScrollView *scroll = [self enclosingScrollView]; + if ((nil != scroll) && (height < [[scroll contentView] frame].size.height)) + height = [[scroll contentView] frame].size.height; + + // set my new frame size + [self setFrameSize:NSMakeSize(width, height)]; + + /**** END Dimension calculations and adjustments ****/ + +} + +// will fetch from the internal array if not nil, from delegate otherwise +- (unsigned)photoCount +{ + if (nil != [self photosArray]) + return [[self photosArray] count]; + else if (nil != delegate) + return [delegate photoCountForPhotoView:self]; + else + return 0; +} + +- (NSImage *)photoAtIndex:(unsigned)photoIndex +{ + NSImage *result = nil; + if ((nil != [self photosArray]) && (photoIndex < [self photoCount])) + result = [[self photosArray] objectAtIndex:photoIndex]; + else if ((nil != delegate) && (photoIndex < [self photoCount])) + result = [delegate photoView:self photoAtIndex:photoIndex]; + +// commenting out. This is really slow, and maybe not needed. +// if (![result isValid]) +// result = nil; + /* + If the receiver is initialized with an existing image file, but the corresponding image data is not yet loaded into memory, this method loads the data and expands it as needed. If the receiver contains no image representations and no associated image file, this method creates a valid cached image representation and initializes it to the default bit depth. This method returns NO in cases where the file or URL from which it was initialized is nonexistent or when the data in an existing file is invalid. + */ + + return result; +} + +- (NSString *)titleAtIndex:(unsigned)photoIndex +{ + NSString *title = nil; + + if ([self showCaptions]) + { + title = [delegate photoView:self titleForPhotoAtIndex:photoIndex]; + } + return title; +} + +- (void)updatePhotoResizing +{ + NSTimeInterval timeSinceResize = [[NSDate date] timeIntervalSinceReferenceDate] - [photoResizeTime timeIntervalSinceReferenceDate]; + if (timeSinceResize > 1) { + isDonePhotoResizing = YES; + [photoResizeTimer invalidate]; + photoResizeTimer = nil; + } + [self viewDidEndLiveResize]; +} + +- (BOOL)inLiveResize +{ + return ([super inLiveResize]) || (mouseDown) || (!isDonePhotoResizing); +} + +- (NSImage *)fastPhotoAtIndex:(unsigned)photoIndex +{ + NSImage *fastPhoto = nil; + if ((nil != [self photosArray]) && (photoIndex < [[self photosArray] count])) + { + fastPhoto = [photosFastArray objectAtIndex:photoIndex]; + if ((NSNull *)fastPhoto == [NSNull null]) + { + // Change this if you want higher/lower quality fast photos + float fastPhotoSize = 100.0; + + NSImageRep *fullSizePhotoRep = [[self scalePhoto:[self photoAtIndex:photoIndex]] bestRepresentationForDevice:nil]; + + // Figure out what the scaled size is + float longSide = [fullSizePhotoRep pixelsWide]; + if (longSide < [fullSizePhotoRep pixelsHigh]) + longSide = [fullSizePhotoRep pixelsHigh]; + + float scale = fastPhotoSize / longSide; + + NSSize scaledSize; + scaledSize.width = [fullSizePhotoRep pixelsWide] * scale; + scaledSize.height = [fullSizePhotoRep pixelsHigh] * scale; + + // Draw the full-size image into our fast, small image. + fastPhoto = [[NSImage alloc] initWithSize:scaledSize]; + [fastPhoto setFlipped:YES]; + [fastPhoto lockFocus]; + [fullSizePhotoRep drawInRect:NSMakeRect(0.0, 0.0, scaledSize.width, scaledSize.height)]; + [fastPhoto unlockFocus]; + + // Save it off + [photosFastArray replaceObjectAtIndex:photoIndex withObject:fastPhoto]; + + [fastPhoto autorelease]; + } + } else if ((nil != delegate) && ([delegate respondsToSelector:@selector(photoView:fastPhotoAtIndex:)])) { + fastPhoto = [delegate photoView:self fastPhotoAtIndex:photoIndex]; + } + + // if the above calls failed, try to just fetch the full size image + if (0 == fastPhoto || ![fastPhoto isValid]) { + fastPhoto = [self photoAtIndex:photoIndex]; + } + + return fastPhoto; +} + + +// placement and hit detection +- (NSSize)scaledPhotoSizeForSize:(NSSize)size +{ + float longSide = size.width; + if (longSide < size.height) + longSide = size.height; + + float scale = [self photoSize] / longSide; + + NSSize scaledSize = size; + if (scale < 1.0) // do not enlarge (POSSIBLY MAKE THIS A PREFERENCE?) + { + scaledSize.width = size.width * scale; + scaledSize.height = size.height * scale; + } + return scaledSize; +} + +- (NSImage *)scalePhoto:(NSImage *)image +{ + // calculate the new image size based on the scale + NSSize newSize; + NSImageRep *bestRep = [image bestRepresentationForDevice:nil]; + newSize.width = [bestRep pixelsWide]; + newSize.height = [bestRep pixelsHigh]; + + // resize the image + [image setScalesWhenResized:YES]; + [image setSize:newSize]; + + return image; +} + +- (unsigned)photoIndexForPoint:(NSPoint)point +{ + unsigned column = point.x / gridSize.width; + unsigned row = point.y / gridSize.height; + + return ((row * columns) + column); +} + +- (NSRange)photoIndexRangeForRect:(NSRect)rect +{ + unsigned photoCount = [self photoCount]; + if (!photoCount) + return NSMakeRange(NSNotFound, 0); + + unsigned start = [self photoIndexForPoint:rect.origin]; + if (start >= photoCount) + return NSMakeRange(NSNotFound, 0); + + unsigned finish = [self photoIndexForPoint:NSMakePoint(NSMaxX(rect)-1, NSMaxY(rect)-1)]; + if (finish >= photoCount) + finish = photoCount - 1; + + return NSMakeRange(start, (finish + 1) - start); +} + +- (NSRect)gridRectForIndex:(unsigned)photoIndex +{ + if (columns == 0) return NSZeroRect; + + unsigned row = photoIndex / columns; + unsigned column = photoIndex % columns; + float x = column * gridSize.width; + float y = row * gridSize.height; + + return NSMakeRect(x, y, gridSize.width, gridSize.height); +} + +- (NSRect)rectCenteredInRect:(NSRect)rect withSize:(NSSize)size +{ + float x = NSMidX(rect) - (size.width / 2); + float y = NSMidY(rect) - (size.height / 2); + + return NSMakeRect(x, y, size.width, size.height); +} + +- (NSSize)sizeOfTitleWithCurrentAttributes:(NSString*)title +{ + if (!sTitleAttributes) + { // This could be improved by setting the color to something that works well with a non white background color. + sTitleAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont labelFontOfSize:[NSFont labelFontSize]], NSFontAttributeName, [NSColor darkGrayColor], NSForegroundColorAttributeName, nil]; + [sTitleAttributes retain]; + } + return [title sizeWithAttributes:sTitleAttributes]; +} + +- (void)getDrawingRectsAtIndex:(unsigned)photoIndex withPhoto:(NSImage *)cellPhoto withTitle:(NSString*)title outGridRect:(NSRect *)outGridRect outPhotoRect:(NSRect *)outPhotoRect outTitleRect:(NSRect *)outTitleRect +{ + NSRect titleRect = NSZeroRect; + NSRect photoRect = NSZeroRect; + NSRect gridRect = NSZeroRect; + + // Only bother if the requested index is within our range + if ((photoIndex + 1) <= [self photoCount]) + { + NSSize titleSize = NSZeroSize; + + gridRect = [self centerScanRect:[self gridRectForIndex:photoIndex]]; + + if (title) + { + titleSize = [self sizeOfTitleWithCurrentAttributes:title]; + NSDivideRect(gridRect, &titleRect, &gridRect, titleSize.height + 6.0f, NSMaxYEdge); + } + + NSSize scaledSize = [self scaledPhotoSizeForSize:[cellPhoto size]]; + photoRect = [self rectCenteredInRect:gridRect withSize:scaledSize]; + +// DCJ - I don't think this is necessary because the title rect is already considered when determining the photoRect +// Furthermore, doing this caused a nasty bug when either dimension is less than 12: it causes the dimension to +// inset to a NEGATIVE dimension :) +// if (!NSEqualSizes(NSZeroSize,titleSize)) +// { +// photoRect = NSInsetRect(photoRect,6,6); +// } + photoRect = [self centerScanRect:photoRect]; + } + + if (outGridRect != nil) *outGridRect = gridRect; + if (outPhotoRect != nil) *outPhotoRect = photoRect; + if (outTitleRect != nil) *outTitleRect = titleRect; +} + +- (NSRect)photoRectForIndex:(unsigned)photoIndex +{ + // get the actual image + NSImage *photo = [self photoAtIndex:photoIndex]; + if (nil == photo) + { + return NSZeroRect; + } + else + { + NSRect photoRect; + [self getDrawingRectsAtIndex:photoIndex withPhoto:photo withTitle:[self titleAtIndex:photoIndex] outGridRect:nil outPhotoRect:&photoRect outTitleRect:nil]; + return photoRect; + } +} + +// selection +- (BOOL)isPhotoSelectedAtIndex:(unsigned)photoIndex; +{ + if (0 < [dragSelectedPhotoIndexes count]) { + if ([dragSelectedPhotoIndexes containsIndex:photoIndex]) + return YES; + } else if ((nil != [self selectedPhotoIndexes]) && [[self selectedPhotoIndexes] containsIndex:photoIndex]) + return YES; + else if (nil != delegate) + return [[delegate selectionIndexesForPhotoView:self] containsIndex:photoIndex]; + + + return NO; +} + +- (NSIndexSet *)selectionIndexes +{ + if (nil != [self selectedPhotoIndexes]) + return [self selectedPhotoIndexes]; + else if (nil != delegate) + return [delegate selectionIndexesForPhotoView:self]; + else + return nil; +} + +- (void)setSelectionIndexes:(NSIndexSet *)indexes +{ + NSMutableIndexSet *oldSelection = nil; + + // Set the new selection, but save the old selection so we know exactly what to redraw + if (nil != [self selectedPhotoIndexes]) + { + oldSelection = [[self selectedPhotoIndexes] retain]; + [self setSelectedPhotoIndexes:indexes]; + } + else if (nil != delegate) + { + // We have to iterate through the photos to figure out which ones the delegate thinks are selected - that's the only way to know the old selection when in delegate mode + oldSelection = [[NSMutableIndexSet alloc] init]; + int i, count = [self photoCount]; + for( i = 0; i < count; i += 1 ) + { + if ([self isPhotoSelectedAtIndex:i]) + { + [oldSelection addIndex:i]; + } + } + + // Now update the selection + indexes = [delegate photoView:self willSetSelectionIndexes:indexes]; + [delegate photoView:self didSetSelectionIndexes:indexes]; + } + + [self dirtyDisplayRectsForNewSelection:indexes oldSelection:oldSelection]; + [oldSelection release]; +} + +- (NSBezierPath *)shadowBoxPathForRect:(NSRect)rect +{ + NSRect inset = NSInsetRect(rect,5.0,5.0); + float radius = 15.0; + + float minX = NSMinX(inset); + float midX = NSMidX(inset); + float maxX = NSMaxX(inset); + float minY = NSMinY(inset); + float midY = NSMidY(inset); + float maxY = NSMaxY(inset); + + NSBezierPath *path = [[NSBezierPath alloc] init]; + [path moveToPoint:NSMakePoint(midX, minY)]; + [path appendBezierPathWithArcFromPoint:NSMakePoint(maxX,minY) toPoint:NSMakePoint(maxX,midY) radius:radius]; + [path appendBezierPathWithArcFromPoint:NSMakePoint(maxX,maxY) toPoint:NSMakePoint(midX,maxY) radius:radius]; + [path appendBezierPathWithArcFromPoint:NSMakePoint(minX,maxY) toPoint:NSMakePoint(minX,midY) radius:radius]; + [path appendBezierPathWithArcFromPoint:NSMakePoint(minX,minY) toPoint:NSMakePoint(midX,minY) radius:radius]; + + return [path autorelease]; + +} + +// photo removal +- (void)removePhotosAtIndexes:(NSIndexSet *)indexes +{ + // let the delegate know that we're about to delete, give it a chance to modify the indexes we'll delete + NSIndexSet *modifiedIndexes = [[indexes copy] autorelease]; + if ((nil != delegate) && ([delegate respondsToSelector:@selector(photoView:willRemovePhotosAtIndexes:)])) { + modifiedIndexes = [delegate photoView:self willRemovePhotosAtIndexes:modifiedIndexes]; + } + + // if using bindings, do the removal + if ((0 < [modifiedIndexes count]) && (nil != [self photosArray])) { + [self willChangeValueForKey:@"photosArray"]; + [photosArray removeObjectsAtIndexes:modifiedIndexes]; + [self didChangeValueForKey:@"photosArray"]; + } + + if ((nil != delegate) && ([delegate respondsToSelector:@selector(photoView:didRemovePhotosAtIndexes:)])) { + [delegate photoView:self didRemovePhotosAtIndexes:modifiedIndexes]; + } + + // update the selection + NSMutableIndexSet *remaining = [[self selectionIndexes] mutableCopy]; + [remaining removeIndexes:modifiedIndexes]; + [self setSelectionIndexes:remaining]; + [remaining release]; +} + +- (NSImage *)scaleImage:(NSImage *)image toSize:(float)size +{ + NSImageRep *fullSizePhotoRep = [[self scalePhoto:image] bestRepresentationForDevice:nil]; + + float longSide = [fullSizePhotoRep pixelsWide]; + if (longSide < [fullSizePhotoRep pixelsHigh]) + longSide = [fullSizePhotoRep pixelsHigh]; + + float scale = size / longSide; + + NSSize scaledSize; + scaledSize.width = [fullSizePhotoRep pixelsWide] * scale; + scaledSize.height = [fullSizePhotoRep pixelsHigh] * scale; + + NSImage *fastPhoto = [[NSImage alloc] initWithSize:scaledSize]; + [fastPhoto setFlipped:YES]; + [fastPhoto lockFocus]; + [fullSizePhotoRep drawInRect:NSMakeRect(0.0, 0.0, scaledSize.width, scaledSize.height)]; + [fastPhoto unlockFocus]; + + return [fastPhoto autorelease]; +} + +- (void)dirtyDisplayRectsForNewSelection:(NSIndexSet *)newSelection oldSelection:(NSIndexSet *)oldSelection +{ + NSRect visibleRect = [self visibleRect]; + + // Figure out how the selection changed and only update those areas of the grid + NSMutableIndexSet *changedIndexes = [NSMutableIndexSet indexSet]; + if (oldSelection && newSelection) + { + // First, see which of the old are different than the new + unsigned int thisIndex = [newSelection firstIndex]; + + while (thisIndex != NSNotFound) + { + if (![oldSelection containsIndex:thisIndex]) + { + [changedIndexes addIndex:thisIndex]; + } + thisIndex = [newSelection indexGreaterThanIndex:thisIndex]; + } + + // Next, see which of the new are different from the old + thisIndex = [oldSelection firstIndex]; + while (thisIndex != NSNotFound) + { + if (![newSelection containsIndex:thisIndex]) + { + [changedIndexes addIndex:thisIndex]; + } + thisIndex = [oldSelection indexGreaterThanIndex:thisIndex]; + } + + // Loop through the changes and dirty the rect for each + thisIndex = [changedIndexes firstIndex]; + while (thisIndex != NSNotFound) + { + NSRect photoRect = [self gridRectForIndex:thisIndex]; + if (NSIntersectsRect(visibleRect, photoRect)) + { + [self setNeedsDisplayInRect:photoRect]; + } + thisIndex = [changedIndexes indexGreaterThanIndex:thisIndex]; + } + + } + else + { + [self setNeedsDisplayInRect:visibleRect]; + } + +} + +- (NSImage*) currentDisplayImageAtIndex:(unsigned)thisPhotoIndex allowsShadows:(BOOL *)allowShadows; +{ + NSImage *photo = nil; + if ([self inLiveResize]) { + photo = [self fastPhotoAtIndex:thisPhotoIndex]; + } + + if (nil == photo) { + photo = [self photoAtIndex:thisPhotoIndex]; + } + BOOL placeholder = NO; + + if (nil == photo) { + placeholder = YES; + photo = [[[NSImage alloc] initWithSize:NSMakeSize(photoSize,photoSize)] autorelease]; + + // Note: it would be nice to have an NSBezierPath category method like bezierPathWithRoundedRect:radius: + const float curve = MIN(photoSize * 0.3, 50); + const int width = 4; + const int margin = width / 2; + const int boxSize = photoSize - margin; + NSBezierPath *p = [NSBezierPath bezierPath]; + [p moveToPoint:NSMakePoint(curve, margin)]; + [p lineToPoint:NSMakePoint(boxSize - curve, margin)]; + [p curveToPoint:NSMakePoint(boxSize, curve) controlPoint1:NSMakePoint(boxSize, margin) controlPoint2:NSMakePoint(boxSize, margin)]; + [p lineToPoint:NSMakePoint(boxSize, boxSize - curve)]; + [p curveToPoint:NSMakePoint(boxSize - curve, boxSize) controlPoint1:NSMakePoint(boxSize,boxSize) controlPoint2:NSMakePoint(boxSize,boxSize)]; + [p lineToPoint:NSMakePoint(curve, boxSize)]; + [p curveToPoint:NSMakePoint(margin, boxSize - curve) controlPoint1:NSMakePoint(margin, boxSize) controlPoint2:NSMakePoint(margin, boxSize)]; + [p lineToPoint:NSMakePoint(margin, curve)]; + [p curveToPoint:NSMakePoint(curve, margin) controlPoint1:NSMakePoint(margin, margin) controlPoint2:NSMakePoint(margin, margin)]; + [p closePath]; + + [photo lockFocus]; + [[NSColor colorWithCalibratedWhite:0.95 alpha:1.0] set]; + [p setLineWidth:width]; + [p stroke]; + + [photo unlockFocus]; + } + + // Disable shadows for placeholder image + if (allowShadows != nil) *allowShadows = (placeholder == NO); + + return photo; +} + +@end + diff --git a/MUPhotoView.zip b/MUPhotoView.zip new file mode 100644 index 0000000000000000000000000000000000000000..4a21e67fbe0436a3b4ac30adbc1a27b293cfb01d GIT binary patch literal 21145 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 G-u?xX%>&N> literal 0 HcmV?d00001 diff --git a/MediaContentController.h b/MediaContentController.h new file mode 100644 index 0000000..078e6b1 --- /dev/null +++ b/MediaContentController.h @@ -0,0 +1,107 @@ +// +// MediaContentController.h +// SproutedInterface +// +// Created by Philip Dow on 6/11/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +#define PDMediabarItemShowInFinder @"PDMediabarItemShowInFinder" +#define PDMediabarItemOpenWithFinder @"PDMediabarItemOpenWithFinder" +#define PDMediaBarItemGetInfo @"PDMediaBarItemGetInfo" + +@class PDMediaBar; +@class PDMediabarItem; +@class JournlerGradientView; + +@interface MediaContentController : NSObject { + + IBOutlet NSView *contentView; + IBOutlet PDMediaBar *bar; + + id delegate; + NSURL *URL; + + id representedObject; + NSString *searchString; + + NSDictionary *fileError; + NSManagedObjectContext *managedObjectContext; +} + +- (id) initWithOwner:(id)anObject managedObjectContext:(NSManagedObjectContext*)moc; + +- (NSView*) contentView; +- (NSUndoManager*) undoManager; + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (NSManagedObjectContext*) managedObjectContext; +- (void) setManagedObjectContext:(NSManagedObjectContext*)moc; + +- (id) representedObject; +- (void) setRepresentedObject:(id)anObject; + +- (NSURL*) URL; +- (void) setURL:(NSURL*)aURL; + +- (NSString*) searchString; +- (void) setSearchString:(NSString*)aString; + +- (BOOL) loadURL:(NSURL*)aURL; +- (BOOL) highlightString:(NSString*)aString; + +- (IBAction) printSelection:(id)sender; +- (IBAction) exportSelection:(id)sender; + +- (IBAction) getInfo:(id)sender; +- (IBAction) showInFinder:(id)sender; +- (IBAction) openInFinder:(id)sender; + +- (void) prepareTitleBar; +- (void) setWindowTitleFromURL:(NSURL*)aURL; + +- (NSResponder*) preferredResponder; +- (void) appropriateFirstResponder:(NSWindow*)window; +- (void) appropriateAlternateResponder:(NSWindow*)aWindow; +- (void) establishKeyViews:(NSView*)previous nextKeyView:(NSView*)next; + +- (BOOL) commitEditing; +- (void) ownerWillClose:(NSNotification*)aNotification; + +- (void) updateContent; +- (void) stopContent; + +- (BOOL) handlesFindCommand; +- (void) performCustomFindPanelAction:(id)sender; + +- (BOOL) handlesTextSizeCommand; +- (void) performCustomTextSizeAction:(id)sender; + +- (BOOL) canAnnotateDocumentSelection; +- (IBAction) annotateDocumentSelection:(id)sender; + +- (BOOL) canHighlightDocumentSelection; +- (IBAction) highlightDocumentSelection:(id)sender; + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem; + +@end + +@interface NSObject (MediaContentDelegate) + +- (void) contentController:(MediaContentController*)controller changedTitle:(NSString*)title; +- (void) contentController:(MediaContentController*)aController showLexiconSelection:(id)anObject term:(NSString*)aTerm; + +@end + +@interface NSView (MediaContentAdditions) + +- (void) setImage:(NSImage*)anImage; + +@end diff --git a/MediaContentController.m b/MediaContentController.m new file mode 100644 index 0000000..4501f77 --- /dev/null +++ b/MediaContentController.m @@ -0,0 +1,658 @@ +// +// MediaContentController.m +// SproutedInterface +// +// Created by Philip Dow on 6/11/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +#import +#import + +#import + +#import +#import + +@implementation MediaContentController + +- (id) init +{ + return [self initWithOwner:nil managedObjectContext:nil]; +} + +- (id) initWithOwner:(id)anObject managedObjectContext:(NSManagedObjectContext*)moc +{ + if ( self = [super init] ) + { + URL = [[NSURL alloc] initWithString:@"http://journler.com"]; + + [self setDelegate:anObject]; + [self setManagedObjectContext:moc]; + + #ifdef __DEBUG__ + NSLog(@"%@ %s", [self className], _cmd); + #endif + } + return self; +} + +- (void) awakeFromNib +{ + // sublcasses should call super's implementation + [self prepareTitleBar]; +} + +- (void) dealloc +{ + //#ifdef __DEBUG__ + NSLog(@"%@ %s", [self className], _cmd); + //#endif + + // top level nib objects + [contentView release]; + + // local variables + [URL release]; + [searchString release]; + [representedObject release]; + [managedObjectContext release]; + + [super dealloc]; +} + +#pragma mark - + +- (NSView*) contentView +{ + return contentView; +} + +- (NSUndoManager*) undoManager +{ + return [[[self contentView] window] undoManager]; +} + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (NSManagedObjectContext*) managedObjectContext +{ + return managedObjectContext; +} + +- (void) setManagedObjectContext:(NSManagedObjectContext*)moc +{ + if ( managedObjectContext != moc ) + { + [managedObjectContext release]; + managedObjectContext = [moc retain]; + } +} + +- (id) representedObject +{ + return representedObject; +} + +- (void) setRepresentedObject:(id)anObject +{ + if ( representedObject != anObject ) + { + [representedObject release]; + representedObject = [anObject retain]; + } +} + +- (NSURL*) URL +{ + return URL; +} + +- (void) setURL:(NSURL*)aURL +{ + if ( URL != aURL ) + { + [URL release]; + URL = [aURL copyWithZone:[self zone]]; + } +} + +- (NSString*) searchString +{ + return searchString; +} + +- (void) setSearchString:(NSString*)aString +{ + if ( searchString != aString ) + { + [searchString release]; + searchString = [aString retain]; + } +} + +#pragma mark - + +- (BOOL) loadURL:(NSURL*)aURL +{ + // overridden by subclasses to load the given url + // subclasses must set the url, or subclasses should call super's implementation + + [self setURL:aURL]; + [self setupMediabar:bar url:aURL]; + [self setWindowTitleFromURL:aURL]; + + return YES; +} + +- (BOOL) highlightString:(NSString*)aString +{ + if ( aString == nil || [aString length] == 0 ) + return NO; + + // overridden by subclasses to highlight a string in their view + NSPasteboard *findBoard = [NSPasteboard pasteboardWithName:NSFindPboard]; + [findBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; + [findBoard setString:aString forType:NSStringPboardType]; + + return NO; +} + +- (IBAction) printSelection:(id)sender +{ + // overridden by subclasses to handle document type specific printing + return; +} + +- (IBAction) exportSelection:(id)sender +{ + // subclasses should override if the url does not point to a file or if they want special behavior + if ( [[self URL] isFileURL] ) + { + NSSavePanel *savePanel = [NSSavePanel savePanel]; + [savePanel setRequiredFileType:nil]; + [savePanel setCanSelectHiddenExtension:YES]; + + //[openPanel setMessage:NSLocalizedString(@"export resources panel text",@"")]; + //[openPanel setTitle:NSLocalizedString(@"export resources panel title",@"")]; + //[openPanel setPrompt:NSLocalizedString(@"export resources panel prompt",@"")]; + + if ( [savePanel runModalForDirectory:nil file:[[[self URL] path] lastPathComponent]] == NSOKButton ) + { + NSString *filename = [savePanel filename]; + if ( ![[NSFileManager defaultManager] copyPath:[[self URL] path] toPath:filename handler:self] ) + { + NSString *errorTitle = NSLocalizedString(@"file manager error title",@""); + NSString *errorMessage = [NSString stringWithFormat:NSLocalizedString(@"file manager error msg",@""), + [fileError objectForKey:@"Error"], [fileError objectForKey:@"Path"]]; + + NSBeep(); + NSRunAlertPanel(errorTitle, errorMessage, nil, nil, nil); + + [fileError release]; + fileError = nil; + } + else + { + NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:[savePanel isExtensionHidden]] forKey:NSFileExtensionHidden]; + [[NSFileManager defaultManager] changeFileAttributes:fileAttributes atPath:[savePanel filename]]; + } + } + } + else + { + NSBeep(); + return; + } +} + +#pragma mark - + +- (IBAction) getInfo:(id)sender +{ + /* + if ( [[self representedObject] isKindOfClass:[JournlerResource class]] ) + [self showInfoForResource:[self representedObject]]; + else + NSBeep(); + */ +} + +- (IBAction) showInFinder:(id)sender +{ + // subclasses may override to provide more specific behavior + if ( [[self URL] isFileURL] ) + { + [[NSWorkspace sharedWorkspace] selectFile:[[self URL] path] + inFileViewerRootedAtPath:[[[self URL] path] stringByDeletingLastPathComponent]]; + } + else + [self openInFinder:sender]; +} + +- (IBAction) openInFinder:(id)sender +{ + // subclasses may override to provide more specific behavior + [[NSWorkspace sharedWorkspace] openURL:[self URL]]; +} + +#pragma mark - + +- (void) prepareTitleBar +{ + // subclasses may override to provide special behavior + int whichBorders[4] = {1,0,1,0}; + [bar setBordered:YES]; + [bar setBorderColor:[NSColor colorWithCalibratedRed:155.0/255.0 green:155.0/255.0 blue:155.0/255.0 alpha:1.0]]; + [bar setBorders:whichBorders]; +} + +- (void) setWindowTitleFromURL:(NSURL*)aURL +{ + // subclasses may override to provide custom behavior + if ( delegate && [delegate respondsToSelector:@selector(contentController:changedTitle:)] ) + { + if ( [aURL isFileURL] ) + [delegate contentController:self changedTitle:[[[aURL path] lastPathComponent] stringByDeletingPathExtension]]; + else + [delegate contentController:self changedTitle:[aURL absoluteString]]; + } +} + +- (NSResponder*) preferredResponder +{ + // meant to be overridden by subclasses + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return nil; +} + +- (void) appropriateFirstResponder:(NSWindow*)window +{ + // meant to be overridden by subclasses + return; +} + +- (void) appropriateAlternateResponder:(NSWindow*)aWindow +{ + // meant to be overridden by subclasses + return; +} + +- (void) establishKeyViews:(NSView*)previous nextKeyView:(NSView*)next +{ + // meant to be overridden by subclasses + // establish a connection between the two provided views if you don't need them + [previous setNextKeyView:next]; + NSLog(@"%@ %s - **** subclasses must override ****", [self className], _cmd); + return; +} + +#pragma mark - +#pragma mark Find Panel + +- (BOOL) handlesFindCommand +{ + // subclasses should override and return yes if they handle the find panel in their own way, including windowing + return NO; +} + +- (void) performCustomFindPanelAction:(id)sender +{ + // subclasses should override and return perform the handling in their own specific way + return; +} + +#pragma mark Text Sizing + +- (BOOL) handlesTextSizeCommand +{ + // subclasses should override and return yes if the handle the cmd +/- menu items (bigger/smaller) + return NO; +} + +- (void) performCustomTextSizeAction:(id)sender +{ + // subclasses should override and return perform the handling in their own specific way + return; +} + +#pragma mark Annotation + +- (BOOL) canAnnotateDocumentSelection +{ + //NSLog(@"%@ %s - **** subclasses must override ****",[self className],_cmd); + return NO; +} + +- (IBAction) annotateDocumentSelection:(id)sender +{ + NSLog(@"%@ %s - **** subclasses must override ****",[self className],_cmd); + return; +} + +#pragma mark Highlight + +- (BOOL) canHighlightDocumentSelection +{ + return NO; +} + +- (IBAction) highlightDocumentSelection:(id)sender +{ + NSLog(@"%@ %s - **** subclasses must override ****",[self className],_cmd); + return; +} + +#pragma mark - + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + // subclasses should override and validate/invalidate their own way (specifically for the custom find panel action and +/- actions) + return YES; +} + +#pragma mark - + +- (BOOL) commitEditing +{ + NSLog(@"%@ %s - **** Subclasses should override ****",[self className],_cmd); + return YES; + // subclsses should override and commit editing on the document in their own particular way +} + +- (void) ownerWillClose:(NSNotification*)aNotification +{ + // subclasses should override to unhook bindings, etc. aNotification is currently nil + [self stopContent]; + [contentView removeFromSuperview]; +} + +- (void) updateContent +{ + //meant to be overriddden by subclasses + return; +} + +- (void) stopContent +{ + //meant to be overridden by subclasses + return; +} + +#pragma mark - + +- (BOOL)fileManager:(NSFileManager *)manager shouldProceedAfterError:(NSDictionary *)errorInfo +{ + NSLog(@"%@ %s - file error: %@", [self className], _cmd, errorInfo); + fileError = [errorInfo retain]; + return NO; +} + +- (void)fileManager:(NSFileManager *)manager willProcessPath:(NSString *)path +{ + return; +} + +#pragma mark - +#pragma mark MediaBar Implementation + +- (void) setupMediabar:(PDMediaBar*)aMediabar url:(NSURL*)aURL +{ + if ( ![self canCustomizeMediabar:aMediabar] ) + return; + else + { + [aMediabar setDelegate:self]; + [aMediabar loadItems]; + [aMediabar displayItems]; + } +} + +- (NSImage*) defaultOpenWithFinderImage:(PDMediaBar*)aMediabar +{ + // subclasses should override to provide a default "open with finder" icon + return nil; +} + +- (float) mediabarMinimumWidthForUnmanagedControls:(PDMediaBar*)aMediabar +{ + // subclasses should override to provide the minimum width needed for default controls that aren't managed by the media bar + return 0; +} + +#pragma mark - +#pragma mark Medibar + +- (BOOL) canCustomizeMediabar:(PDMediaBar*)aMediabar +{ + // subclasses should override and return YES if they allow media bar customization + return NO; +} + +- (NSString*) mediabarIdentifier:(PDMediaBar*)aMediabar +{ + // subclasses may override to provide a different classname + return [self className]; +} + + +#pragma mark - + + +- (IBAction) perfomCustomMediabarItemAction:(PDMediabarItem*)anItem +{ + BOOL success = NO; + static NSString *perform_action_handler = @"perform_action"; + + // subclasses may override although it isn't necessary + + if ( [[anItem typeIdentifier] intValue] == kMenubarItemURI ) + { + // throw the uri at the workspace + NSURL *applicationURI = [anItem targetURI]; + NSURL *fileURI = [self URL]; + + if ( [applicationURI isFileURL] && [fileURI isFileURL] ) + { + success = [[NSWorkspace sharedWorkspace] openFile:[fileURI path] withApplication:[applicationURI path]]; + } + else + { + NSLog(@"%@ %s - curretly, only file based urls are supported %@", [self className], _cmd, [applicationURI absoluteString]); + success = NO; + } + } + + else if ( [[anItem typeIdentifier] intValue] == kMenubarItemAppleScript ) + { + NSDictionary *errorDictionary; + NSString *scriptSource = [[anItem targetScript] string]; + + NSString *resourceURI = [[self URL] absoluteString]; + id theRepresentedObject = (id)[NSNull null]; + //id theRepresentedObject = ( [self representedObject] != nil ? [[self representedObject] aeDescriptorValue] : (id)[NSNull null] ); + //id theRepresentedObject = ( [self representedObject] != nil && [[self representedObject] respondsToSelector:@selector(objectSpecifier)] + //? [[self representedObject] objectSpecifier] : (id)[NSNull null] ); + + NSAppleScript *script = [[[NSAppleScript alloc] initWithSource:scriptSource] autorelease]; + if ( script == nil ) + { + success = NO; + NSLog(@"%@ %s - unable to initalize script with source %@", [self className], _cmd, scriptSource); + + NSBeep(); + AppleScriptAlert *scriptAlert = [[[AppleScriptAlert alloc] initWithSource:[anItem targetScript] error:[NSString string]] autorelease]; + + NSBeep(); + [scriptAlert showWindow:self]; + goto bail; + } + + if ( [script compileAndReturnError:&errorDictionary] == NO ) + { + success = NO; + NSLog(@"%@ %s - unable to compile the script %@, error: %@", [self className], _cmd, scriptSource, errorDictionary); + AppleScriptAlert *scriptAlert = [[[AppleScriptAlert alloc] initWithSource:[anItem targetScript] error:errorDictionary] autorelease]; + + NSBeep(); + [scriptAlert showWindow:self]; + goto bail; + } + + if ( ![script executeHandler:perform_action_handler error:&errorDictionary withParameters: resourceURI, theRepresentedObject, nil] ) + { + success = NO; + NSLog(@"%@ %s - unable to execute handler of script %@, error: %@", [self className], _cmd, scriptSource, errorDictionary); + + id theSource = [script richTextSource]; + if ( theSource == nil ) theSource = [script source]; + AppleScriptAlert *scriptAlert = [[[AppleScriptAlert alloc] initWithSource:theSource error:errorDictionary] autorelease]; + + NSBeep(); + [scriptAlert showWindow:self]; + goto bail; + } + + // we made it through! + success = YES; + } + +bail: + + return; +} + +#pragma mark - + +- (PDMediabarItem*) mediabar:(PDMediaBar *)mediabar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoMediabar:(BOOL)flag +{ + // subclasses should override to build the media bar + // call super to get some default support for the get info, show in finder and open with finder items + + NSURL *aURL = [self URL]; + PDMediabarItem *anItem = [[[PDMediabarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease]; + + NSBundle *myBundle = [NSBundle bundleWithIdentifier:@"com.sprouted.interface"]; + + if ( [itemIdentifier isEqualToString:PDMediaBarItemGetInfo] ) + { + [anItem setTitle:NSLocalizedStringFromTableInBundle(@"get info title", @"Mediabar", myBundle, @"")]; + [anItem setTag:kMediaBarGetInfo]; + [anItem setTypeIdentifier:[NSNumber numberWithInt:kMenubarItemDefault]]; + [anItem setToolTip:NSLocalizedStringFromTableInBundle(@"get info tip",@"Mediabar",myBundle,@"")]; + + NSImage *theImage = [[[NSImage alloc] initWithContentsOfFile:[myBundle pathForImageResource:@"InfoBarSmall.png"]] autorelease]; + [anItem setImage:theImage]; + + [anItem setTarget:self]; + [anItem setAction:@selector(getInfo:)]; + } + + else if ( [itemIdentifier isEqualToString:PDMediabarItemShowInFinder] ) + { + [anItem setTitle:NSLocalizedStringFromTableInBundle(@"reveal in finder title", @"Mediabar", myBundle, @"")]; + [anItem setTag:kMediaBarShowInFinder]; + [anItem setTypeIdentifier:[NSNumber numberWithInt:kMenubarItemDefault]]; + [anItem setToolTip:NSLocalizedStringFromTableInBundle(@"reveal in finder tip",@"Mediabar",myBundle,@"")]; + + NSImage *theImage = [[[NSImage alloc] initWithContentsOfFile:[myBundle pathForImageResource:@"RevealInFinderBarSmall.png"]] autorelease]; + [anItem setImage:theImage]; + + [anItem setTarget:self]; + [anItem setAction:@selector(showInFinder:)]; + } + + else if ( [itemIdentifier isEqualToString:PDMediabarItemOpenWithFinder] ) + { + [anItem setTitle:NSLocalizedStringFromTableInBundle(@"open in finder title", @"Mediabar", myBundle, @"")]; + [anItem setTag:kMediaBarOpenWithFinder]; + [anItem setTypeIdentifier:[NSNumber numberWithInt:kMenubarItemDefault]]; + [anItem setToolTip:NSLocalizedStringFromTableInBundle(@"open in finder tip",@"Mediabar",myBundle,@"")]; + + [anItem setTarget:self]; + [anItem setAction:@selector(openInFinder:)]; + + if ( [aURL isFileURL] ) + { + NSImage *imageIcon; + NSString *appName, *fileType, *appPath; + NSString *filename = [aURL path]; + + if ( ![[NSWorkspace sharedWorkspace] getInfoForFile:filename application:&appName type:&fileType] || appName == nil ) + { + NSLog(@"%@ %s - unable to get workspace information for file at path %@", [self className], _cmd, filename); + // use the default image + [anItem setImage:[self defaultOpenWithFinderImage:mediabar]]; + } + else + { + appPath = [[NSWorkspace sharedWorkspace] fullPathForApplication:appName]; + + if ( appPath == nil ) + { + NSLog(@"%@ %s - unable to get application path for file at path %@", [self className], _cmd, filename); + // use the default image + [anItem setImage:[self defaultOpenWithFinderImage:mediabar]]; + } + else + { + #ifdef __DEBUG__ + NSLog(appPath); + #endif + + imageIcon = [[NSWorkspace sharedWorkspace] iconForFile:appPath]; + + // use a more indicative tooltip + NSString *appDisplayName = [[NSFileManager defaultManager] displayNameAtPath:appName]; + [anItem setToolTip:[NSString stringWithFormat:NSLocalizedStringFromTableInBundle(@"open with tip", @"Mediabar", myBundle, @""), appDisplayName]]; + + if ( imageIcon == nil ) + { + NSLog(@"%@ %s - unable to get icon path for application at path %@", [self className], _cmd, appPath); + // use the default image + [anItem setImage:[self defaultOpenWithFinderImage:mediabar]]; + } + else + { + [anItem setImage:[imageIcon imageWithWidth:24 height:24]]; + } + } + } + } + else + { + // use the default image + [anItem setImage:[self defaultOpenWithFinderImage:mediabar]]; + } + } + + else + { + // return nil - the setup method will handle custom attributes + anItem = nil; + } + + return anItem; +} + +- (NSArray*) mediabarDefaultItemIdentifiers:(PDMediaBar *)mediabar +{ + // subclasses should override to provide an array of default items + return nil; +} + +@end \ No newline at end of file diff --git a/MediaViewer.h b/MediaViewer.h new file mode 100644 index 0000000..f4a69f4 --- /dev/null +++ b/MediaViewer.h @@ -0,0 +1,52 @@ +// +// MediaViewer.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class MediaContentController; + +/* +@class AudioViewController; +@class MovieViewController; +@class WebViewController; +@class PDFViewController; +@class ImageViewController; +@class AddressRecordController; +*/ + +@interface MediaViewer : NSWindowController +{ + NSURL *homeURL; + MediaContentController *_contentController; + IBOutlet NSView *contentPlaceholder; +} + ++ (BOOL) canDisplayMediaOfType:(NSString*)uti url:(NSURL*)aURL; +- (id) initWithURL:(NSURL*)url uti:(NSString*)uti; + +- (id) representedObject; +- (void) setRepresentedObject:(id)anObject; + +- (MediaContentController*) contentController; + +- (BOOL) highlightString:(NSString*)aString; + +- (IBAction) printDocument:(id)sender; + +- (IBAction) save:(id)sender; +- (IBAction) exportSelection:(id)sender; + +@end + +@interface MediaViewer (CustomMenuSupport) + +- (void) performCustomFindPanelAction:(id)sender; +- (void) performCustomTextSizeAction:(id)sender; + +@end diff --git a/MediaViewer.m b/MediaViewer.m new file mode 100644 index 0000000..e6ab41a --- /dev/null +++ b/MediaViewer.m @@ -0,0 +1,305 @@ +// +// MediaViewer.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import MediaViewer.h> + +/* +#import "NSWorkspace_PDCategories.h" +#import "MediaContentController.h" + +#import "AudioViewController.h" +#import "MovieViewController.h" +#import "WebViewController.h" +#import "PDFViewController.h" +#import "ImageViewController.h" +#import "AddressRecordController.h" +#import "MailMessageController.h" +#import "WordDocumentController.h" +#import "TextDocumentController.h" +*/ + +//#import "JournlerResource.h" + +@implementation MediaViewer + ++ (BOOL) canDisplayMediaOfType:(NSString*)uti url:(NSURL*)aURL +{ + BOOL can_display = NO; + /* + if ( uti == nil ) + return NO; + + NSString *path = nil; + if ( [aURL isFileURL] ) + path = [aURL path]; + + NSString *mime_type = (NSString*)UTTypeCopyPreferredTagWithClass((CFStringRef)uti,kUTTagClassMIMEType); + + if ( UTTypeConformsTo((CFStringRef)uti,kUTTypeWebArchive) || UTTypeConformsTo( (CFStringRef)uti, kUTTypeHTML) ) + can_display = YES; + else if ( UTTypeConformsTo((CFStringRef)uti,kUTTypePDF) ) + can_display = YES; + else if ( UTTypeConformsTo((CFStringRef)uti,kUTTypeImage) ) + can_display = YES; + else if ( [[NSWorkspace sharedWorkspace] canPlayFile:path] ) + can_display = YES; + else if ( [[NSWorkspace sharedWorkspace] canWatchFile:path] ) + can_display = YES; + + else if ( UTTypeConformsTo((CFStringRef)uti,kUTTypeURL) || UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeURL) ) + can_display = YES; + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeABPerson) ) + can_display = YES; + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeMailEmail) ) + can_display = YES; + + else if ( UTTypeConformsTo( (CFStringRef)uti, (CFStringRef)@"com.microsoft.word.doc") ) + can_display = YES; + else if ( mime_type != nil && [WebView canShowMIMEType:mime_type] ) + can_display = YES; + else if ( UTTypeConformsTo( (CFStringRef)uti, kUTTypeRTF ) || UTTypeConformsTo( (CFStringRef)uti, kUTTypeRTFD ) || UTTypeConformsTo( (CFStringRef)uti, kUTTypePlainText ) ) + can_display = YES; + else + can_display = NO; + + if ( mime_type != nil ) + [mime_type release]; + */ + return can_display; +} + +#pragma mark - + +- (id) initWithURL:(NSURL*)url uti:(NSString*)uti +{ + _contentController = nil; + Class controllerClass = nil; + + /* + // first determine if we can display the media + if ( [url isFileURL] ) + { + if ( UTTypeConformsTo((CFStringRef)uti,kUTTypeWebArchive) || UTTypeConformsTo( (CFStringRef)uti, kUTTypeHTML) ) + controllerClass = [WebViewController class]; + + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)kUTTypePDF) ) + controllerClass = [PDFViewController class]; + + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)kUTTypeImage) ) + controllerClass = [ImageViewController class]; + + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)kUTTypeAudio) ) + controllerClass = [AudioViewController class]; + + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)@"public.movie") ) + controllerClass = [MovieViewController class]; + + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeMailEmail) ) + controllerClass = [MailMessageController class]; + + else if ( UTTypeConformsTo( (CFStringRef)uti, (CFStringRef)@"com.microsoft.word.doc") ) + controllerClass = [WordDocumentController class]; + + else if ( UTTypeConformsTo( (CFStringRef)uti, kUTTypeRTF ) || UTTypeConformsTo( (CFStringRef)uti, kUTTypeRTFD ) || UTTypeConformsTo( (CFStringRef)uti, kUTTypePlainText ) ) + controllerClass = [TextDocumentController class]; + + else if ( uti != nil ) + { + // check the mime type + NSString *mime_type = (NSString*)UTTypeCopyPreferredTagWithClass((CFStringRef)uti,kUTTagClassMIMEType); + if ( mime_type != nil && [WebView canShowMIMEType:mime_type] ) + controllerClass = [WebViewController class]; + } + } + + + else + { + if ( UTTypeConformsTo((CFStringRef)uti,kUTTypeURL) || UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeURL) ) + controllerClass = [WebViewController class]; + else if ( UTTypeConformsTo((CFStringRef)uti,(CFStringRef)LexUTTypeABPerson) ) + controllerClass = [AddressRecordController class]; + } + */ + + if ( controllerClass == nil ) + { + [self release]; + return nil; + } + + else if ( self = [self initWithWindowNibName:@"MediaViewer"] ) + { + // take control of ourselves + //[self setShouldCascadeWindows:NO]; + + homeURL = [url retain]; + _contentController = [[controllerClass alloc] init]; + [self retain]; + } + + return self; +} + + +- (void) windowDidLoad +{ + [[self window] setFrameUsingName:@"Media Viewer Window" force:YES]; + [[self window] setBackgroundColor:[NSColor whiteColor]]; + + [[_contentController contentView] setFrame:[contentPlaceholder frame]]; + [[[self window] contentView] replaceSubview:contentPlaceholder with:[_contentController contentView]]; + + //[[self window] setContentView:[_contentController contentView]]; + + [_contentController setDelegate:self]; + [_contentController loadURL:homeURL]; + +} + +- (void) dealloc +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s", [self className], _cmd); + #endif + + [_contentController ownerWillClose:nil]; + [_contentController release]; + [homeURL release]; + + [super dealloc]; +} + +- (void)windowWillClose:(NSNotification *)aNotification +{ + [self autorelease]; +} + +#pragma mark - + +- (id) representedObject +{ + return [_contentController representedObject]; +} + +- (void) setRepresentedObject:(id)anObject +{ + [_contentController setRepresentedObject:anObject]; +} + +#pragma mark - + +- (MediaContentController*) contentController +{ + return _contentController; +} + +#pragma mark - + +- (void) contentController:(MediaContentController*)controller changedTitle:(NSString*)title +{ + if ( controller != _contentController ) + return; + + if ( title != nil ) + [[self window] setTitle:title]; +} + +#pragma mark - + +- (BOOL) highlightString:(NSString*)aString +{ + // pass it on to the controller + return [_contentController highlightString:aString]; +} + +- (IBAction) printDocument:(id)sender +{ + // pass it on to the controller + [_contentController printDocument:sender]; +} + +- (IBAction) save:(id)sender +{ + NSBeep(); + return; +} + +- (IBAction) exportSelection:(id)sender +{ + // pass it on to the controller + [_contentController exportSelection:sender]; +} + +- (IBAction) doPageSetup:(id) sender +{ + NSPageLayout *pageLayout = [NSPageLayout pageLayout]; + //[pageLayout setAccessoryView:[[PageSetupController sharedPageSetup] contentView]]; + + if ( [[self window] isMainWindow] ) + [pageLayout beginSheetWithPrintInfo:[NSPrintInfo sharedPrintInfo] modalForWindow:[self window] + delegate:nil didEndSelector:nil contextInfo:nil]; + else + [pageLayout runModalWithPrintInfo:[NSPrintInfo sharedPrintInfo]]; + +} + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + BOOL enabled = YES; + SEL action = [menuItem action]; + + if ( action == @selector(printDocument:) ) + enabled = YES; + + else if ( action == @selector(doPageSetup:) ) + enabled = YES; + + else if ( action == @selector(exportSelection:) ) + enabled = YES; + + else if ( action == @selector(save:) ) + enabled = NO; + + else if ( action == @selector(performCustomFindPanelAction:) ) + enabled = [_contentController handlesFindCommand]; + + else if ( action == @selector(performCustomTextSizeAction:) ) + enabled = [_contentController handlesTextSizeCommand]; + + return enabled; +} + +@end + +@implementation MediaViewer (CustomMenuSupport) + +- (void)performCustomFindPanelAction:(id)sender +{ + // the first responder should only make it this far under special circumstances + if ( [_contentController handlesFindCommand] && [_contentController respondsToSelector:@selector(performCustomFindPanelAction:)] ) + [_contentController performSelector:@selector(performCustomFindPanelAction:) withObject:sender]; + else + { + NSBeep(); + } +} + +- (void) performCustomTextSizeAction:(id)sender +{ + // the first responder should only make it this far under special circumstances + if ( [_contentController handlesTextSizeCommand] && [_contentController respondsToSelector:@selector(performCustomTextSizeAction:)] ) + [_contentController performSelector:@selector(performCustomTextSizeAction:) withObject:sender]; + else + { + NSBeep(); + } +} + +@end \ No newline at end of file diff --git a/MediabarItemApplicationPicker.h b/MediabarItemApplicationPicker.h new file mode 100644 index 0000000..d37fe57 --- /dev/null +++ b/MediabarItemApplicationPicker.h @@ -0,0 +1,32 @@ +// +// MediabarItemApplicationPicker.h +// SproutedInterface +// +// Created by Philip Dow on 2/22/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@interface MediabarItemApplicationPicker : JournlerGradientView { + + id delegate; + NSString *filename; +} + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (NSString*) filename; +- (void) setFilename:(NSString*)aString; + +@end + +@interface NSObject (MediabarItemApplicationPickerDelegate) + +// return yes if the drop is accepted - do something with it! +- (BOOL) mediabarItemApplicationPicker:(MediabarItemApplicationPicker*)appPicker shouldAcceptDrop:(NSString*)aFilename; + +@end \ No newline at end of file diff --git a/MediabarItemApplicationPicker.m b/MediabarItemApplicationPicker.m new file mode 100644 index 0000000..2e0a7cc --- /dev/null +++ b/MediabarItemApplicationPicker.m @@ -0,0 +1,132 @@ +// +// MediabarItemApplicationPicker.m +// SproutedInterface +// +// Created by Philip Dow on 2/22/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation MediabarItemApplicationPicker + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; + } + return self; +} + +- (void) dealloc +{ + [filename release]; + [self unregisterDraggedTypes]; + + [super dealloc]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect { + // Drawing code here.f + [super drawRect:rect]; +} + +#pragma mark - + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (NSString*) filename +{ + return filename; +} + +- (void) setFilename:(NSString*)aString +{ + if ( filename != aString ) + { + [filename release]; + filename = [aString copyWithZone:[self zone]]; + [self setNeedsDisplay:YES]; + } +} + +#pragma mark - + +- (BOOL)performDragOperation:(id )sender +{ + NSPasteboard *pboard = [sender draggingPasteboard]; + NSArray *types = [pboard types]; + + if ( ![types containsObject:NSFilenamesPboardType] ) + { + NSBeep(); return NO; + } + + NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; + if ( [filenames count] == 0 ) return NO; + + if ( [[self delegate] respondsToSelector:@selector(mediabarItemApplicationPicker:shouldAcceptDrop:)] ) + return [[self delegate] mediabarItemApplicationPicker:self shouldAcceptDrop:[filenames objectAtIndex:0]]; + else + return NO; +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + NSPasteboard *pboard = [sender draggingPasteboard]; + NSArray *types = [pboard types]; + + if ( ![types containsObject:NSFilenamesPboardType] ) + return NSDragOperationNone; + + NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; + return ( [filenames count] == 1 ? NSDragOperationCopy : NSDragOperationNone ); +} + +- (NSDragOperation)draggingUpdated:(id )sender +{ + NSPasteboard *pboard = [sender draggingPasteboard]; + NSArray *types = [pboard types]; + + if ( ![types containsObject:NSFilenamesPboardType] ) + return NSDragOperationNone; + + NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; + return ( [filenames count] == 1 ? NSDragOperationCopy : NSDragOperationNone ); +} + +- (void)draggingExited:(id )sender +{ + return; +} + +- (BOOL)prepareForDragOperation:(id )sender +{ + return YES; +} + +- (void)concludeDragOperation:(id )sender +{ + return; +} + +- (BOOL)ignoreModifierKeysWhileDragging +{ + return YES; +} + + +@end diff --git a/NewMediabarItemController.h b/NewMediabarItemController.h new file mode 100644 index 0000000..a1a0d74 --- /dev/null +++ b/NewMediabarItemController.h @@ -0,0 +1,92 @@ + +// +// NewMediabarItemController.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + + +#import + +@class JournlerGradientView; +@class MediabarItemApplicationPicker; + +@interface NewMediabarItemController : NSWindowController +{ + IBOutlet MediabarItemApplicationPicker *applicationField; + IBOutlet NSTextView *scriptText; + IBOutlet NSTextField *titleField; + + IBOutlet NSTextField *appnameField; + IBOutlet NSImageView *appImageView; + + IBOutlet NSObjectController *objectController; + + BOOL isSheet; + NSRect sheetFrame; + + id delegate; + NSWindow *targetWindow; + + NSImage *icon; + NSString *title; + NSString *helptip; + NSString *filepath; + NSAttributedString *scriptSource; + + id representedObject; + + BOOL wantsScript; + BOOL wantsFile; +} + +- (id) initWithDictionaryRepresentation:(NSDictionary*)aDictionary; +- (NSDictionary*) dictionaryRepresentation; + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (NSImage *)icon; +- (void) setIcon:(NSImage*)anImage; + +- (NSString *)title; +- (void) setTitle:(NSString*)aString; + +- (NSString *)helptip; +- (void) setHelptip:(NSString*)aString; + +- (NSString *)filepath; +- (void) setFilepath:(NSString*)aString; + +- (NSAttributedString *)scriptSource; +- (void) setScriptSource:(NSAttributedString*)anAttributedString; + +- (id) representedObject; +- (void) setRepresentedObject:(id)anObject; + +- (BOOL) wantsScript; +- (void) setWantsScript:(BOOL)aBool; + +- (BOOL) wantsFile; +- (void) setWantsFile:(BOOL)aBool; + +- (IBAction)cancel:(id)sender; +- (IBAction)chooseApplication:(id)sender; +- (IBAction)help:(id)sender; +- (IBAction)save:(id)sender; +- (IBAction) verifyDraggedImage:(id)sender; + +- (void) runAsSheetForWindow:(NSWindow*)window attached:(BOOL)sheet location:(NSRect)frame; +- (void) sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; + +@end + +@interface NSObject (MediaBarItemCreatorDelegate) + +- (void) mediabarItemCreateDidCancelAction:(NewMediabarItemController*)mediabarItemCreator; +- (void) mediabarItemCreateDidSaveAction:(NewMediabarItemController*)mediabarItemCreator; + +@end \ No newline at end of file diff --git a/NewMediabarItemController.m b/NewMediabarItemController.m new file mode 100644 index 0000000..94487ca --- /dev/null +++ b/NewMediabarItemController.m @@ -0,0 +1,423 @@ + +// +// NewMediabarItemController.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +#import +#import +#import + +@implementation NewMediabarItemController + +- (id) init +{ + if ( self = [super initWithWindowNibName:@"NewMediabarItem"] ) + { + wantsScript = YES; + + [self window]; + [self retain]; + } + return self; +} + +- (id) initWithDictionaryRepresentation:(NSDictionary*)aDictionary +{ + if ( self = [self init] ) + { + [self setTitle:[aDictionary objectForKey:@"title"]]; + [self setFilepath:[aDictionary objectForKey:@"targetURI"]]; + [self setHelptip:[aDictionary objectForKey:@"tooltip"]]; + + NSData *imageData = [aDictionary objectForKey:@"image"]; + if ( imageData != nil ) [self setIcon:[NSKeyedUnarchiver unarchiveObjectWithData:imageData]]; + + NSData *scriptData = [aDictionary objectForKey:@"targetScript"]; + if ( scriptData != nil ) [self setScriptSource:[NSKeyedUnarchiver unarchiveObjectWithData:scriptData]]; + + int myTypeIdentifier = [[aDictionary objectForKey:@"typeIdentifier"] intValue]; + if ( myTypeIdentifier == kMenubarItemAppleScript ) + [self setWantsScript:YES]; + else if ( myTypeIdentifier == kMenubarItemURI ) + [self setWantsFile:YES]; + else + [self setWantsScript:YES]; + + } + + return self; +} + +- (void) windowDidLoad +{ + // the filepath gradient + int borders[4] = {1,1,1,1}; + [applicationField setBordered:YES]; + [applicationField setBorders:borders]; + + [applicationField setDrawsGradient:NO]; + [applicationField setBackgroundColor:[NSColor whiteColor]]; + + // the default icon + NSImage *scriptIcon = BundledImageWithName(@"AppleScriptActionBarSmall.png", @"com.sprouted.interface"); + [self setIcon:scriptIcon]; + + // the example script + // place DefaultMediabarAction.rtf in your application's main bundle + NSString *examplePath = [[NSBundle mainBundle] pathForResource:@"DefaultMediabarAction" ofType:@"rtf"]; + if ( examplePath == nil ) + { + NSLog(@"%@ %s - unable to locate resource \"DefaultMediabarAction\" of type \"rtf\"", [self className], _cmd); + } + else + { + NSAttributedString *attributedExample = [[[NSAttributedString alloc] initWithPath:examplePath documentAttributes:nil] autorelease]; + if ( attributedExample == nil ) + { + NSLog(@"%@ %s - unable to initialize example from path %@", [self className], _cmd, examplePath); + } + else + { + [self setScriptSource:attributedExample]; + } + } + + //targetWindow = [self window]; +} + +- (void) dealloc +{ + [icon release]; + [title release]; + [helptip release]; + [filepath release]; + [scriptSource release]; + + [super dealloc]; +} + +- (void)windowWillClose:(NSNotification *)aNotification +{ + [objectController unbind:@"contentObject"]; + [objectController setContent:nil]; + + [self autorelease]; +} + +#pragma mark - + +- (NSDictionary*) dictionaryRepresentation +{ + NSNumber *typeIdentifier = nil; + NSMutableString *identifier = [[[self title] mutableCopyWithZone:[self zone]] autorelease]; + NSMutableDictionary *representation = [NSMutableDictionary dictionaryWithCapacity:4]; + + // preapre the type identifier + if ( [self wantsScript] ) + typeIdentifier = [NSNumber numberWithInt:kMenubarItemAppleScript]; + else + typeIdentifier = [NSNumber numberWithInt:kMenubarItemURI]; + + // prepare the identifier + [identifier replaceOccurrencesOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] + withString:@"" options:0 range:NSMakeRange(0,[identifier length])]; + + + if ( icon != nil ) [representation setObject:[NSKeyedArchiver archivedDataWithRootObject:icon] forKey:@"image"]; + if ( title != nil ) [representation setObject:title forKey:@"title"]; + if ( helptip != nil ) [representation setObject:helptip forKey:@"tooltip"]; + + if ( filepath != nil && [self wantsFile] ) [representation setObject:[[NSURL fileURLWithPath:filepath] absoluteString] forKey:@"targetURI"]; + if ( scriptSource != nil && [self wantsScript] ) [representation setObject:[NSKeyedArchiver archivedDataWithRootObject:[self scriptSource]] forKey:@"targetScript"]; + + if ( identifier != nil ) [representation setObject:identifier forKey:@"identifier"]; + if ( typeIdentifier != nil ) [representation setObject:typeIdentifier forKey:@"typeIdentifier"]; + + return representation; + +} + +#pragma mark - + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (NSImage *)icon +{ + return icon; +} + +- (void) setIcon:(NSImage*)anImage +{ + if ( icon != anImage ) + { + [icon release]; + icon = [anImage copyWithZone:[self zone]]; + } +} + +- (NSString *)title +{ + return title; +} + +- (void) setTitle:(NSString*)aString +{ + if ( title != aString ) + { + [title release]; + title = [aString copyWithZone:[self zone]]; + } +} + +- (NSString *)helptip +{ + return helptip; +} + +- (void) setHelptip:(NSString*)aString +{ + if ( helptip != aString ) + { + [helptip release]; + helptip = [aString copyWithZone:[self zone]]; + } +} + +- (NSString *)filepath +{ + return filepath; +} + +- (void) setFilepath:(NSString*)aString +{ + if ( filepath != aString ) + { + [filepath release]; + filepath = [aString copyWithZone:[self zone]]; + } +} + +- (NSAttributedString *)scriptSource +{ + return scriptSource; +} + +- (void) setScriptSource:(NSAttributedString*)anAttributedString +{ + if ( scriptSource != anAttributedString ) + { + [scriptSource release]; + scriptSource = [anAttributedString copyWithZone:[self zone]]; + } +} + +- (id) representedObject +{ + return representedObject; +} + +- (void) setRepresentedObject:(id)anObject +{ + if ( representedObject != anObject ) + { + [representedObject release]; + representedObject = [anObject retain]; + } +} + +#pragma mark - + +- (BOOL) wantsScript +{ + return wantsScript; +} + +- (void) setWantsScript:(BOOL)aBool +{ + wantsScript = aBool; + if ( wantsScript == YES ) [self setWantsFile:NO]; +} + +- (BOOL) wantsFile +{ + return wantsFile; +} + +- (void) setWantsFile:(BOOL)aBool +{ + wantsFile = aBool; + if ( wantsFile == YES ) [self setWantsScript:NO]; +} + +#pragma mark - + +- (IBAction) save:(id)sender +{ + [objectController commitEditing]; + + if ( [self title] == nil || [[self title] length] == 0 ) + { + NSBeep(); + [[self window] makeFirstResponder:titleField]; + } + else + { + if ( isSheet ) + [NSApp endSheet:targetWindow returnCode:NSRunStoppedResponse]; + else + [NSApp stopModal]; + } +} + +- (IBAction) cancel:(id)sender +{ + [objectController commitEditing]; + + if ( isSheet ) + [NSApp endSheet:targetWindow returnCode:NSRunAbortedResponse]; + else + [NSApp abortModal]; +} + +- (IBAction)chooseApplication:(id)sender +{ + int result; + NSArray *fileTypes = /*[NSArray arrayWithObjects:@"app", @"application", @"scpt", nil]*/ nil; + NSOpenPanel *oPanel = [NSOpenPanel openPanel]; + + result = [oPanel runModalForDirectory:@"/Applications" file:nil types:fileTypes]; + if (result == NSOKButton) + { + NSString *theFilename = [oPanel filename]; + NSString *theAppname = [[NSFileManager defaultManager] displayNameAtPath:theFilename]; + NSImage *theIcon = [[[NSWorkspace sharedWorkspace] iconForFile:theFilename] imageWithWidth:22 height:22]; + + [applicationField setFilename:theFilename]; + [appnameField setStringValue:theAppname]; + [appImageView setImage:theIcon]; + [appImageView setHidden:NO]; + + [self setIcon:theIcon]; + [self setFilepath:theFilename]; + [self setWantsFile:YES]; + } +} + +- (BOOL) mediabarItemApplicationPicker:(MediabarItemApplicationPicker*)appPicker shouldAcceptDrop:(NSString*)aFilename +{ + NSString *theFilename = aFilename; + NSString *theAppname = [[NSFileManager defaultManager] displayNameAtPath:theFilename]; + NSImage *theIcon = [[[NSWorkspace sharedWorkspace] iconForFile:theFilename] imageWithWidth:22 height:22]; + + [applicationField setFilename:theFilename]; + [appnameField setStringValue:theAppname]; + [appImageView setImage:theIcon]; + [appImageView setHidden:NO]; + + [self setIcon:theIcon]; + [self setFilepath:theFilename]; + [self setWantsFile:YES]; + + return YES; +} + +- (IBAction) verifyDraggedImage:(id)sender +{ + NSImage *anImage = [sender image]; + NSImage *resizedImage = [anImage imageWithWidth:22 height:22 inset:0]; + [self setIcon:resizedImage]; +} + + +- (IBAction)help:(id)sender +{ + [[NSHelpManager sharedHelpManager] openHelpAnchor:@"CustomizableMediabar" inBook:@"JournlerHelp"]; +} + +#pragma mark - + +- (void) runAsSheetForWindow:(NSWindow*)window attached:(BOOL)sheet location:(NSRect)frame +{ + int result = NSRunAbortedResponse; + isSheet = sheet; + + id originalDelegate = [window delegate]; + [window setDelegate:self]; + + if ( sheet ) + { + sheetFrame = frame; + sheetFrame.size.height = 0; + + //[NSApp beginSheet: [self window] modalForWindow: window modalDelegate: self + // didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: nil]; + [NSApp beginSheet: [self window] modalForWindow: window modalDelegate: self + didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: nil]; + } + else + { + //result = [NSApp runModalForWindow: [self window]]; + result = [NSApp runModalForWindow: [self window]]; + } + + if ( !isSheet && result == NSRunAbortedResponse ) + { + // only possible if ran as modal and the date was canceled + if ( [delegate respondsToSelector:@selector(mediabarItemCreateDidCancelAction:)] ) + [delegate mediabarItemCreateDidCancelAction:self]; + + //[[self window] close]; + [[self window] close]; + } + else if ( !isSheet && result == NSRunStoppedResponse ) + { + // only possible if ran as modal and the date was saved + if ( [delegate respondsToSelector:@selector(mediabarItemCreateDidSaveAction:)] ) + [delegate mediabarItemCreateDidSaveAction:self]; + + //[[self window] close]; + [[self window] close]; + } + + [window setDelegate:originalDelegate]; +} + +- (void) sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + if ( returnCode == NSRunAbortedResponse && [delegate respondsToSelector:@selector(mediabarItemCreateDidCancelAction:)] ) + [delegate mediabarItemCreateDidCancelAction:self]; + + else if ( returnCode == NSRunStoppedResponse && [delegate respondsToSelector:@selector(mediabarItemCreateDidSaveAction:)] ) + [delegate mediabarItemCreateDidSaveAction:self]; + + //[[self window] close]; + [[self window] close]; +} + +#pragma mark - + +- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect +{ + return sheetFrame; +} + + +@end diff --git a/PDAnnotatedRulerView.h b/PDAnnotatedRulerView.h new file mode 100644 index 0000000..0a683b9 --- /dev/null +++ b/PDAnnotatedRulerView.h @@ -0,0 +1,17 @@ +// +// PDAnnotatedRulerView.h +// SproutedInterface +// +// Created by Philip Dow on 5/23/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@interface PDAnnotatedRulerView : MNLineNumberingRulerView { + +} + +@end diff --git a/PDAnnotatedRulerView.m b/PDAnnotatedRulerView.m new file mode 100644 index 0000000..b8ddd2f --- /dev/null +++ b/PDAnnotatedRulerView.m @@ -0,0 +1,230 @@ +// +// PDAnnotatedRulerView.m +// SproutedInterface +// +// Created by Philip Dow on 5/23/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +// Ruler thickness value +#define RULER_THICKNESS 25 + +// Margin of displaying bookmarked line in a context menu. +#define STRIP_PREVIEW_MARGIN 15 + +// Default +#define DEFAULT_OPTION MNParagraphNumber | MNDrawBookmarks + +@implementation PDAnnotatedRulerView + +- (id)initWithScrollView:(NSScrollView *)aScrollView orientation:(NSRulerOrientation)orientation +{ + + if ( self = [super initWithScrollView:(NSScrollView *)aScrollView orientation:(NSRulerOrientation)orientation]) + { + [self setScrollView:aScrollView]; + [self setOrientation:orientation]; + + //load nib + //[NSBundle loadNibNamed:@"PDAnnotatedRuler" owner:self]; + + + + // Set default width + [self setRuleThickness:RULER_THICKNESS]; + + // Marker config + [self setReservedThicknessForMarkers:0]; + [self setClientView:self]; // Markers ask me if I can add a marker. + + // Add a dummy marker to draw properly + + markerImage = [[NSImage alloc] initByReferencingFile: + [[NSBundle bundleForClass:[self class]] pathForResource:@"prioritymedium" ofType:@"tiff"]]; + + NSRulerMarker* aMarker = [self newMarker]; + [self addMarker:aMarker]; + [self removeMarker:aMarker]; + + + // Set letter attributes + marginAttributes = [[NSMutableDictionary alloc] init]; + [marginAttributes setObject:[NSFont labelFontOfSize:9] forKey: NSFontAttributeName]; + [marginAttributes setObject:[NSColor darkGrayColor] forKey: NSForegroundColorAttributeName]; + + rulerOption = DEFAULT_OPTION; + + markerDeleteReservationFlag = NO; + + // + textView = [aScrollView documentView]; + layoutManager = [textView layoutManager]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowDidUpdate:) + name:NSWindowDidUpdateNotification + object:[aScrollView window]]; + + [self setOption:MNDrawBookmarks]; + + } + + return self; +} + +#pragma mark - + +- (void)drawMarkersInRect:(NSRect)aRect +{ + //NSLog(@"drawMarkersInRect %@",NSStringFromRect(aRect)); + + if( (rulerOption & 0x10) == 0 ) + return; + + + + + // *** (0) remove existing markers *** + // Delete markers unless while dragging. + + NSArray* existingMarkers = [self markers]; + + unsigned hoge = 0; + for( hoge = 0; hoge < [existingMarkers count]; hoge++) + { + if( ! [[existingMarkers objectAtIndex:hoge] isDragging] ) + [self removeMarker:[existingMarkers objectAtIndex:hoge]]; + + } + + + + + // Only get the visible part of the scroller view + NSRect documentVisibleRect = [[[layoutManager firstTextView] enclosingScrollView] documentVisibleRect]; + + // Find the glyph range for the visible glyphs + NSRange glyphRange = [layoutManager glyphRangeForBoundingRect: documentVisibleRect inTextContainer: [textView textContainer]]; + + NSRange charRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + + NSRange limitRange; + NSRange effectiveRange; + + limitRange = charRange; + + while (limitRange.length > 0) { + + //for( hoge= charRange.location; hoge < NSMaxRange(charRange) ; hoge ++ ) + //{ + + hoge = limitRange.location; + + id attribute = [[textView textStorage] attribute:NSToolTipAttributeName + atIndex:limitRange.location longestEffectiveRange:&effectiveRange + inRange:limitRange]; + + if ( attribute != nil ) + { + //if ( [[textView textStorage] hasBookmarkAtIndex:hoge inTextView:textView effectiveRange:effectiveRange] ) + //{ + + //NSRange paragraphRange = + //[textView selectionRangeForProposedRange:NSMakeRange(hoge, 1) granularity:NSSelectByParagraph]; + + + + //unsigned glyphIndex = [layoutManager glyphRangeForCharacterRange:NSMakeRange(paragraphRange.location,1) + // actualCharacterRange:NULL].location; + + + unsigned glyphIndex = [layoutManager glyphRangeForCharacterRange:NSMakeRange(hoge,1) + actualCharacterRange:NULL].location; + + NSRect drawingRect = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange: NULL]; + drawingRect.size.height = [markerImage size].height; + + [self drawMarkerInRect:drawingRect ]; + + + + } + + limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange)); + } + + + +} + +-(void)drawMarkerInRect:(NSRect)lineRect + // check if a marker should be drawn and draw it if necessary +{ + + lineRect = [textView convertRect:lineRect toView:self]; + + + NSArray* markerObjects = [self markers]; + unsigned hoge; + BOOL exist = NO; + for(hoge = 0; hoge < [markerObjects count]; hoge++) + { + //get represented object + NSRulerMarker* marker = [markerObjects objectAtIndex:hoge]; + + + if( [[marker representedObject] isEqualToString:NSStringFromRect(lineRect) ] ) + { + //if( ! [marker isDragging] ) + // [marker setMarkerLocation: lineRect.origin.y + (lineRect.size.height / 2) ]; + [[[self scrollView] backgroundColor] set]; + NSRectFillUsingOperation(lineRect, NSCompositeSourceOver); + + [marker drawRect:lineRect]; + + exist = YES; + } + + + } + + if( exist == NO ) + { + + NSRulerMarker* aMarker = [self newMarker]; + [aMarker setMarkerLocation: lineRect.origin.y + (lineRect.size.height / 2) ]; + + [[[self scrollView] backgroundColor] set]; + NSRectFillUsingOperation(lineRect, NSCompositeSourceOver); + [aMarker drawRect:lineRect]; + + [aMarker setMovable:YES]; + [aMarker setRemovable:YES]; + [aMarker setRepresentedObject: NSStringFromRect(lineRect) ]; + [self addMarker:aMarker]; + + } +} + + +#pragma mark - + +- (void)mouseDown:(NSEvent *)theEvent +{ + return; +} + +- (void)mouseUp:(NSEvent *)theEvent +{ + return; +} + +- (void)mouseDragged:(NSEvent *)theEvent +{ + return; +} + +@end diff --git a/PDAnnotatedTextStorage.h b/PDAnnotatedTextStorage.h new file mode 100644 index 0000000..b79de16 --- /dev/null +++ b/PDAnnotatedTextStorage.h @@ -0,0 +1,19 @@ +// +// PDAnnotatedTextStorage.h +// SproutedInterface +// +// Created by Philip Dow on 5/24/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@interface PDAnnotatedTextStorage : MNLineNumberingTextStorage { + +} + +-(BOOL)hasBookmarkAtIndex:(unsigned)index inTextView:(NSTextView*)textView effectiveRange:(NSRangePointer)aRange; + +@end diff --git a/PDAnnotatedTextStorage.m b/PDAnnotatedTextStorage.m new file mode 100644 index 0000000..1d70b3b --- /dev/null +++ b/PDAnnotatedTextStorage.m @@ -0,0 +1,53 @@ +// +// PDAnnotatedTextStorage.m +// SproutedInterface +// +// Created by Philip Dow on 5/24/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define MarkerAttributeName NSToolTipAttributeName + +@implementation PDAnnotatedTextStorage + +-(BOOL)hasBookmarkAtIndex:(unsigned)index inTextView:(NSTextView*)textView +{ + //NSRange paragraphRange = + //[textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + //NSLog(@"%@ %s - %i, %i", [self className], _cmd, NSMaxRange(paragraphRange) -1); + + //id attribute = [self attribute:MarkerAttributeName atIndex:NSMaxRange(paragraphRange) -1 effectiveRange:NULL]; + id attribute = [self attribute:MarkerAttributeName atIndex:index effectiveRange:NULL]; + if( attribute != NULL ) + return YES; + else + return NO; +} + +-(BOOL)hasBookmarkAtIndex:(unsigned)index inTextView:(NSTextView*)textView effectiveRange:(NSRangePointer)aRange +{ + //NSRange paragraphRange = + //[textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + //NSLog(@"%@ %s - %i, %i", [self className], _cmd, NSMaxRange(paragraphRange) -1); + + id attribute = [self attribute:MarkerAttributeName atIndex:index effectiveRange:aRange]; + if( attribute != NULL ) + return YES; + else + return NO; +} + +-(void)setBookmarkAtIndex:(unsigned)index flag:(BOOL)flag inTextView:(NSTextView*)textView +{ + NSRange paragraphRange = + [textView selectionRangeForProposedRange:NSMakeRange(index, 1) granularity:NSSelectByParagraph]; + + [self addAttribute:MarkerAttributeName value:@"My Comment" range:NSMakeRange(NSMaxRange(paragraphRange)-1,1)]; +} + +@end diff --git a/PDAnnotatedTextView.h b/PDAnnotatedTextView.h new file mode 100644 index 0000000..fe5190c --- /dev/null +++ b/PDAnnotatedTextView.h @@ -0,0 +1,18 @@ +// +// PDAnnotatedTextView.h +// SproutedInterface +// +// Created by Philip Dow on 5/23/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import + +@interface PDAnnotatedTextView : MNLineNumberingTextView { + +} + +@end diff --git a/PDAnnotatedTextView.m b/PDAnnotatedTextView.m new file mode 100644 index 0000000..59ca1e7 --- /dev/null +++ b/PDAnnotatedTextView.m @@ -0,0 +1,47 @@ +// +// PDAnnotatedTextView.m +// SproutedInterface +// +// Created by Philip Dow on 5/23/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import + +@implementation PDAnnotatedTextView + +- (void) awakeFromNib +{ + PDAnnotatedTextStorage* ts = [[PDAnnotatedTextStorage alloc] init]; + + [[self layoutManager] replaceTextStorage:ts]; + + [[self textStorage] setDelegate:self]; + + + NSScrollView* scrollView = [self enclosingScrollView]; + + + + // *** set up main text View *** // + //textView setting -- add ruler to textView + PDAnnotatedRulerView* aNumberingRulerView = + [[PDAnnotatedRulerView alloc] initWithScrollView:scrollView + orientation:NSVerticalRuler]; + + [scrollView setVerticalRulerView:aNumberingRulerView ]; + + //configuration + [scrollView setHasVerticalRuler:YES]; + [scrollView setHasHorizontalRuler:NO]; + + [scrollView setRulersVisible:YES]; + + [aNumberingRulerView release]; + +} + +@end diff --git a/PDAutoCompleteTextField.h b/PDAutoCompleteTextField.h new file mode 100644 index 0000000..43c5c21 --- /dev/null +++ b/PDAutoCompleteTextField.h @@ -0,0 +1,19 @@ +// +// PDAutoCompleteTextField.h +// SproutedInterface +// +// Created by Philip Dow on 7/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDAutoCompleteTextField : NSTextField { + NSArray *autoCompleteOptions; +} + +- (NSArray*) autoCompleteOptions; +- (void) setAutoCompleteOptions:(NSArray*)options; + +@end diff --git a/PDAutoCompleteTextField.m b/PDAutoCompleteTextField.m new file mode 100644 index 0000000..19b88f0 --- /dev/null +++ b/PDAutoCompleteTextField.m @@ -0,0 +1,67 @@ +// +// PDAutoCompleteTextField.m +// SproutedInterface +// +// Created by Philip Dow on 7/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDAutoCompleteTextField + +- (void) awakeFromNib +{ + autoCompleteOptions = [[NSArray alloc] init]; +} + +- (NSArray*) autoCompleteOptions +{ + return autoCompleteOptions; +} + +- (void) setAutoCompleteOptions:(NSArray*)options +{ + if ( autoCompleteOptions != options ) + { + [autoCompleteOptions release]; + autoCompleteOptions = [options copyWithZone:[self zone]]; + } +} + +#pragma mark - + +- (void)textDidChange:(NSNotification *)aNotification +{ + [[[aNotification userInfo] objectForKey:@"NSFieldEditor"] complete:self]; + [super textDidChange:aNotification]; +} + +- (NSArray *)textView:(NSTextView *)textView completions:(NSArray *)words + forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int *)index +{ + + // + // Textview delegate method that responds to the field editor + // When this text view is being edited + // + + // dunno if this is the correct way to do this at all + + NSMutableArray *hits = [[NSMutableArray alloc] init]; + + // grab the view's string + NSString *text = [textView string]; + + int i; + for ( i = 0; i < [autoCompleteOptions count]; i++ ) + { + if ( [[autoCompleteOptions objectAtIndex:i] rangeOfString:text options:NSLiteralSearch].location != NSNotFound ) + [hits addObject:[autoCompleteOptions objectAtIndex:i]]; + } + + return [hits autorelease]; +} + +@end diff --git a/PDBlueHighlightTextCell.h b/PDBlueHighlightTextCell.h new file mode 100644 index 0000000..fa38486 --- /dev/null +++ b/PDBlueHighlightTextCell.h @@ -0,0 +1,16 @@ +// +// PDBlueHighlightTextCell.h +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDBlueHighlightTextCell : NSTextFieldCell { + BOOL _beingEdited; +} + +@end diff --git a/PDBlueHighlightTextCell.m b/PDBlueHighlightTextCell.m new file mode 100644 index 0000000..75f186a --- /dev/null +++ b/PDBlueHighlightTextCell.m @@ -0,0 +1,45 @@ +// +// PDBlueHighlightTextCell.m +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDBlueHighlightTextCell + + +- (id)initWithCoder:(NSCoder *)decoder { + self = [super initWithCoder:decoder]; + [self setFocusRingType:NSFocusRingTypeNone]; + [self setShowsFirstResponder:NO]; + return self; +} + + +- (NSColor*) textColor { + + if ( [self isHighlighted] && ([[[self controlView] window] firstResponder] == [self controlView]) && + [[[self controlView] window] isMainWindow] && [[[self controlView] window] isKeyWindow] ) + return [NSColor whiteColor]; + else if ( [self isHighlighted] && + [(NSTableView*)[self controlView] editedRow] != -1 && [(NSTableView*)[self controlView] editedColumn] != -1 ) + return [NSColor whiteColor]; + else + return [super textColor]; + +} + +/* +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + //[super drawWithFrame:cellFrame inView:<#(NSView *)controlView#> + +} +*/ + +@end diff --git a/PDBorderedView.h b/PDBorderedView.h new file mode 100644 index 0000000..c309f01 --- /dev/null +++ b/PDBorderedView.h @@ -0,0 +1,34 @@ +// +// PDBorderedFill.h +// SproutedInterface +// +// Created by Philip Dow on 12/15/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDBorderedView : NSView { + + int borders[4]; + BOOL bordered; + + NSColor *fillColor; + NSColor *borderColor; + +} + +- (int*) borders; +- (void) setBorders:(int*)sides; + +- (BOOL) bordered; +- (void) setBordered:(BOOL)flag; + +- (NSColor*) fillColor; +- (void) setFillColor:(NSColor*)aColor; + +- (NSColor*) borderColor; +- (void) setBorderColor:(NSColor*)aColor; + +@end diff --git a/PDBorderedView.m b/PDBorderedView.m new file mode 100644 index 0000000..7dc2cad --- /dev/null +++ b/PDBorderedView.m @@ -0,0 +1,196 @@ +// +// PDBorderedFill.m +// SproutedInterface +// +// Created by Philip Dow on 12/15/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDBorderedView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + fillColor = [[NSColor whiteColor] retain]; + borderColor = [[NSColor + colorWithCalibratedRed:157.0/255.0 green:157.0/255.0 blue:157.0/255.0 alpha:1.0] retain]; + + bordered = YES; + + borders[0] = 1; // top + borders[1] = 1; // right + borders[2] = 1; // bottom + borders[3] = 1; // left + + } + return self; +} + +- (void) dealloc { + + [fillColor release]; + fillColor = nil; + + [borderColor release]; + borderColor = nil; + + [super dealloc]; + +} + +#pragma mark - + +- (int*) borders { + return borders; +} + +- (void) setBorders:(int*)sides { + + borders[0] = sides[0]; + borders[1] = sides[1]; + borders[2] = sides[2]; + borders[3] = sides[3]; +} + +- (BOOL) bordered { + return bordered; +} + +- (void) setBordered:(BOOL)flag { + bordered = flag; +} + +- (NSColor*) fillColor { + return fillColor; +} + +- (void) setFillColor:(NSColor*)aColor { + + if ( fillColor != aColor ) { + [fillColor release]; + fillColor = [aColor copyWithZone:[self zone]]; + } +} + +- (NSColor*) borderColor { + return borderColor; +} + +- (void) setBorderColor:(NSColor*)aColor { + + if ( borderColor != aColor ) { + [borderColor release]; + borderColor = [aColor copyWithZone:[self zone]]; + } +} + +- (void)drawRect:(NSRect)rect { + + // Draw a frame and fill in white + NSRect bds = [self bounds]; + + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + + //then fills it the requested color + if ( fillColor != nil ) + { + [[self fillColor] set]; + NSRectFillUsingOperation(bds, NSCompositeSourceOver); + } + + if ( [self bordered] ) + { + + NSPoint topLeft, topRight, bottomRight, bottomLeft; + + topLeft = NSMakePoint(0.5, bds.size.height-0.5); + topRight = NSMakePoint(bds.size.width, bds.size.height-0.5); + + bottomRight = NSMakePoint(bds.size.width-0.5, 0.5); + bottomLeft = NSMakePoint(0.5, 0.5); + + + float scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; + if ( scaleFactor != 1.0 ) { + + // apply the scale factor + topLeft.x *= scaleFactor; + topLeft.y *= scaleFactor; + + topRight.x *= scaleFactor; + topRight.y *= scaleFactor; + + bottomRight.x *= scaleFactor; + bottomRight.y *= scaleFactor; + + bottomLeft.x *= scaleFactor; + bottomLeft.y *= scaleFactor; + + // adjust the points to integral boundaries + topLeft.x = ceil(topLeft.x); + topLeft.y = ceil(topLeft.y); + + topRight.x = ceil(topRight.x); + topRight.y = ceil(topRight.y); + + bottomRight.x = ceil(bottomRight.x); + bottomRight.y = ceil(bottomRight.y); + + bottomLeft.x = ceil(bottomLeft.x); + bottomLeft.y = ceil(bottomLeft.y); + + // convert back to user space + topLeft.x /= scaleFactor; + topLeft.y /= scaleFactor; + + topRight.x /= scaleFactor; + topRight.y /= scaleFactor; + + bottomRight.x /= scaleFactor; + bottomRight.y /= scaleFactor; + + bottomLeft.x /= scaleFactor; + bottomLeft.y /= scaleFactor; + + + } + + // + //draws an outline around the guy, just like with other views + if ( [self bordered] ) { + NSBezierPath *borderPath = [NSBezierPath bezierPath]; + if ( borders[0] ) { + [borderPath moveToPoint:topLeft]; + [borderPath lineToPoint:topRight]; + } + if ( borders[1] ) { + [borderPath moveToPoint:topRight]; + [borderPath lineToPoint:bottomRight]; + } + if ( borders[2] ) { + [borderPath moveToPoint:bottomRight]; + [borderPath lineToPoint:bottomLeft]; + } + if ( borders[3] ) { + [borderPath moveToPoint:bottomLeft]; + [borderPath lineToPoint:topLeft]; + } + + [[self borderColor] set ]; + + [currentContext saveGraphicsState]; + [currentContext setShouldAntialias:NO]; + + [borderPath setLineWidth:1.0]; + [borderPath stroke]; + + [currentContext restoreGraphicsState]; + } + } +} + +@end diff --git a/PDButton.h b/PDButton.h new file mode 100644 index 0000000..1232f8f --- /dev/null +++ b/PDButton.h @@ -0,0 +1,18 @@ +// +// PDButton.h +// SproutedInterface +// +// Created by Philip Dow on 12/4/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDButtonCell; + +@interface PDButton : NSButton { + +} + +@end diff --git a/PDButton.m b/PDButton.m new file mode 100644 index 0000000..6e1e25f --- /dev/null +++ b/PDButton.m @@ -0,0 +1,37 @@ +// +// PDButton.m +// SproutedInterface +// +// Created by Philip Dow on 12/4/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDButton + + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDButtonCell class]; +} + +@end diff --git a/PDButtonCell.h b/PDButtonCell.h new file mode 100644 index 0000000..735e0b5 --- /dev/null +++ b/PDButtonCell.h @@ -0,0 +1,16 @@ +// +// PDButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 12/4/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDButtonCell : NSButtonCell { + +} + +@end diff --git a/PDButtonCell.m b/PDButtonCell.m new file mode 100644 index 0000000..14ea5d9 --- /dev/null +++ b/PDButtonCell.m @@ -0,0 +1,131 @@ +// +// PDButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 12/4/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +#define PDButtonCellFillLeft 0 +#define PDButtonCellFillCenter 1 +#define PDButtonCellFillRight 2 + +#define PDButtonCellDarkLeft 3 +#define PDButtonCellDarkCenter 4 +#define PDButtonCellDarkRight 5 + +@implementation PDButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + + + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + if ( [self isHighlighted] ) { + + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else { + + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + int height = cellFrame.size.height; + int width = cellFrame.size.width; + + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11.0], NSFontAttributeName, + ( [self isEnabled] ? [NSColor blackColor] : [NSColor lightGrayColor] ), NSForegroundColorAttributeName, nil]; + + NSSize stringSize = [[self title] sizeWithAttributes:attributes]; + + NSRect stringRect = NSMakeRect(width/2.0-stringSize.width/2.0, height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + NSRect targetRect = NSMakeRect( stringRect.origin.x-16.0, stringRect.origin.y-2.0, + stringRect.size.width+32.0, stringRect.size.height+4.0 ); + + targetRect = NSInsetRect(targetRect,0.5,0.5); + + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] stroke]; + + [[self title] drawInRect:stringRect withAttributes:attributes]; + + +} + +@end diff --git a/PDButtonColorWell.h b/PDButtonColorWell.h new file mode 100644 index 0000000..748d02d --- /dev/null +++ b/PDButtonColorWell.h @@ -0,0 +1,22 @@ +// +// PDButtonColorWell.h +// SproutedInterface +// +// Created by Philip Dow on 1/7/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDButtonColorWell : NSButton { + NSString *defaultsKey; +} + +- (NSColor*) color; +- (void) setColor:(NSColor*)color; + +- (NSString*) defaultsKey; +- (void) setDefaultsKey:(NSString*)aKey; + +@end diff --git a/PDButtonColorWell.m b/PDButtonColorWell.m new file mode 100644 index 0000000..0b6c0bf --- /dev/null +++ b/PDButtonColorWell.m @@ -0,0 +1,84 @@ +// +// PDButtonColorWell.m +// SproutedInterface +// +// Created by Philip Dow on 1/7/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + + +@implementation PDButtonColorWell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDButtonColorWellCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + } + + return self; +} + +- (void) dealloc +{ + [defaultsKey release]; + [super dealloc]; +} + + ++ (Class) cellClass +{ + return [PDButtonColorWellCell class]; +} + +- (BOOL) isFlipped +{ + return YES; +} + +- (NSColor*) color +{ + return [[self cell] color]; +} + +- (void) setColor:(NSColor*)color +{ + [self willChangeValueForKey:@"color"]; + [[self cell] setColor:color]; + [self didChangeValueForKey:@"color"]; + + [self setNeedsDisplay:YES]; +} + +- (NSString*) defaultsKey +{ + return defaultsKey; +} + +- (void) setDefaultsKey:(NSString*)aKey +{ + if ( defaultsKey != aKey ) + { + [self willChangeValueForKey:@"defaultsKey"]; + [defaultsKey release]; + defaultsKey = [aKey copyWithZone:[self zone]]; + [self didChangeValueForKey:@"defaultsKey"]; + + [self unbind:@"color"]; + [self bind:@"color" + toObject:[NSUserDefaultsController sharedUserDefaultsController] + withKeyPath:[NSString stringWithFormat:@"values.%@",defaultsKey] + options:[NSDictionary dictionaryWithObjectsAndKeys: + NSUnarchiveFromDataTransformerName, NSValueTransformerNameBindingOption, nil]]; + } +} + + +@end diff --git a/PDButtonColorWellCell.h b/PDButtonColorWellCell.h new file mode 100644 index 0000000..b424815 --- /dev/null +++ b/PDButtonColorWellCell.h @@ -0,0 +1,21 @@ +// +// PDButtonColorWellCell.h +// SproutedInterface +// +// Created by Philip Dow on 1/7/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDButtonColorWellCell : NSButtonCell { + + NSColor *_color; + +} + +- (NSColor*) color; +- (void) setColor:(NSColor*)color; + +@end diff --git a/PDButtonColorWellCell.m b/PDButtonColorWellCell.m new file mode 100644 index 0000000..9027f19 --- /dev/null +++ b/PDButtonColorWellCell.m @@ -0,0 +1,196 @@ +// +// PDButtonColorWellCell.m +// SproutedInterface +// +// Created by Philip Dow on 1/7/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +#define kLabelOffset 20 + +@implementation PDButtonColorWellCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + [self setBordered:NO]; + } + + return self; +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + [self setBordered:NO]; + } + + return self; +} + +- (void) dealloc { + + [_color release]; + [super dealloc]; +} + +#pragma mark - + + +- (NSColor*) color +{ + return _color; +} + +- (void) setColor:(NSColor*)color +{ + if ( _color != color ) + { + [self willChangeValueForKey:@"color"]; + [_color release]; + _color = [color copyWithZone:[self zone]]; + [self didChangeValueForKey:@"color"]; + } +} + +#pragma mark - + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + if ( [self isHighlighted] /*|| [self state] == NSOnState*/ ) { + + borderColor = [NSColor colorWithCalibratedRed:119.0/255.0 green:119.0/255.0 blue:119.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + } + else { + + borderColor = [NSColor colorWithCalibratedRed:143.0/255.0 green:143.0/255.0 blue:143.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + } + + NSRect targetRect = cellFrame; + targetRect = NSInsetRect(targetRect,0.5,0.5); + //targetRect.origin.x += 0.5; targetRect.origin.y += 0.5; targetRect.size.width = 21; targetRect.size.height -= 1; + + NSBezierPath *thePath = [NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:2.0]; + [thePath linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [thePath stroke]; + + // + // draw the color inside the cell image + NSColor *cellColor = [self color]; + if ( !cellColor ) cellColor = [NSColor blackColor]; + + [cellColor set]; + //NSRect colorRect = NSInsetRect(targetRect, 5.0, 4.0); + NSRect colorRect = targetRect; + colorRect.origin.x += 5; colorRect.origin.y += 4; colorRect.size.width = 10; colorRect.size.height -= 8; + NSBezierPath *insetPath = [NSBezierPath bezierPathWithRoundedRect:colorRect cornerRadius:2.0]; + + [insetPath fill]; + + [[borderColor colorWithAlphaComponent:0.7] set]; + + //[borderColor set]; + [insetPath stroke]; + + if ( [[self title] length] != 0 ) + { + cellFrame.origin.x += kLabelOffset; + cellFrame.size.width -= kLabelOffset; + + [super drawInteriorWithFrame:cellFrame inView:controlView]; + } + +} + +/* +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + if ( [self isHighlighted] ) { + + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else { + + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + NSRect targetRect = cellFrame; + + targetRect = NSInsetRect(targetRect,0.5,0.5); + + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:2.0] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:2.0] stroke]; + + // draw the color inside the cell image + NSColor *cellColor = [self color]; + if ( !cellColor ) cellColor = [NSColor blackColor]; + + [cellColor set]; + NSRect colorRect = NSInsetRect(targetRect, 6.0, 4.0); + [[NSBezierPath bezierPathWithRoundedRect:colorRect cornerRadius:2.0] fill]; + + // draw the label if there is one + NSString *title = [self title]; + if ( title != nil && [title length] > 0 ) + { + // really basic stuff happening here - no alignment, no elision, etc + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [self font], NSFontAttributeName, nil]; + + NSSize stringSize = [title sizeWithAttributes:attributes]; + NSRect titleRect = NSMakeRect( cellFrame.origin.x + cellFrame.size.width - stringSize.width, + cellFrame.origin.y + cellFrame.size.height - stringSize.height, + stringSize.width, stringSize.height ); + + [title drawInRect:titleRect withAttributes:attributes]; + } +} +*/ + +@end diff --git a/PDButtonTextOnImage.h b/PDButtonTextOnImage.h new file mode 100644 index 0000000..2920d20 --- /dev/null +++ b/PDButtonTextOnImage.h @@ -0,0 +1,18 @@ +// +// PDButtonTextOnImage.h +// SproutedInterface +// +// Created by Philip Dow on 1/3/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDButtonTextOnImageCell; + +@interface PDButtonTextOnImage : NSButton { + +} + +@end diff --git a/PDButtonTextOnImage.m b/PDButtonTextOnImage.m new file mode 100644 index 0000000..cb0b67e --- /dev/null +++ b/PDButtonTextOnImage.m @@ -0,0 +1,44 @@ +// +// PDButtonTextOnImage.m +// SproutedInterface +// +// Created by Philip Dow on 1/3/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDButtonTextOnImage + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + + NSFont *font = [[self cell] font]; + NSString *title = [self title]; + + [self setCell:[[[PDButtonTextOnImageCell alloc] initImageCell:[self image]] autorelease]]; + + [(PDButtonTextOnImageCell*)[self cell] setTitle:title]; + [(PDButtonTextOnImageCell*)[self cell] setFont:font]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDButtonTextOnImageCell class]; +} + +- (BOOL) isFlipped { return YES; } + +- (BOOL)isOpaque { return NO; } + + +@end diff --git a/PDButtonTextOnImageCell.h b/PDButtonTextOnImageCell.h new file mode 100644 index 0000000..78e03a9 --- /dev/null +++ b/PDButtonTextOnImageCell.h @@ -0,0 +1,16 @@ +// +// PDButtonTextOnImageCell.h +// SproutedInterface +// +// Created by Philip Dow on 1/3/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDButtonTextOnImageCell : NSButtonCell { + +} + +@end diff --git a/PDButtonTextOnImageCell.m b/PDButtonTextOnImageCell.m new file mode 100644 index 0000000..6f22d40 --- /dev/null +++ b/PDButtonTextOnImageCell.m @@ -0,0 +1,127 @@ +// +// PDButtonTextOnImageCell.m +// SproutedInterface +// +// Created by Philip Dow on 1/3/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDButtonTextOnImageCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + [self setBordered:NO]; + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + [self setBordered:NO]; + } + + return self; + +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + + + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + + float height = cellFrame.size.height; + float width = cellFrame.size.width; + + float alpha = 1.0; + + NSSize centerSize; + NSSize textSize; + NSRect targetRect; + NSRect textRect; + + NSImage *cellImage = [self image]; + + NSMutableAttributedString *attrValue = [[[NSMutableAttributedString alloc] initWithString:[self title]attributes: + [NSDictionary dictionaryWithObjectsAndKeys:[self font], NSFontAttributeName, nil]] autorelease]; + + centerSize = [cellImage size]; + targetRect = NSMakeRect(width/2-centerSize.width/2, height/2-centerSize.height/2, centerSize.width, centerSize.height); + + if ( [self isHighlighted] ) { + [[NSColor blackColor] set]; + NSRectFillUsingOperation(cellFrame, NSCompositeSourceOver); + alpha = 0.6; + } + + [cellImage setFlipped:YES]; + [cellImage drawInRect:targetRect + fromRect:NSMakeRect(0,0,centerSize.width,centerSize.height) + operation:NSCompositeSourceOver fraction:alpha]; + + textSize = [attrValue size]; + + // a maximum rectangle for the text + NSRect maxTextRect = NSMakeRect(4,height/2-textSize.height/2 + 1, width-8, textSize.height); + + // the required size + textRect = NSMakeRect(width/2-textSize.width/2, height/2-textSize.height/2 + 1, textSize.width, textSize.height); + + if ( textRect.size.width > maxTextRect.size.width ) { + + NSMutableParagraphStyle *parStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]]; + [parStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + [attrValue addAttribute:NSParagraphStyleAttributeName value:parStyle range:NSMakeRange(0,[attrValue length])]; + [attrValue drawInRect:maxTextRect]; + + [parStyle release]; + + } + else { + + [attrValue drawInRect:textRect]; + + } + +} + + +@end diff --git a/PDCaseInsensitiveComboBoxCell.h b/PDCaseInsensitiveComboBoxCell.h new file mode 100644 index 0000000..add7b15 --- /dev/null +++ b/PDCaseInsensitiveComboBoxCell.h @@ -0,0 +1,17 @@ +// +// PDCaseInsensitiveComboBox.h +// SproutedInterface +// +// Created by Philip Dow on 3/17/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDCaseInsensitiveComboBoxCell : NSComboBoxCell { + +} + +@end diff --git a/PDCaseInsensitiveComboBoxCell.m b/PDCaseInsensitiveComboBoxCell.m new file mode 100644 index 0000000..f8ce25e --- /dev/null +++ b/PDCaseInsensitiveComboBoxCell.m @@ -0,0 +1,45 @@ +// +// PDCaseInsensitiveComboBox.m +// SproutedInterface +// +// Created by Philip Dow on 3/17/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDCaseInsensitiveComboBoxCell + +-(NSString*)completedString:(NSString*)substring +{ + if([self usesDataSource]) + { + return[super completedString:substring]; + } + else //basicallydowhatcompleteshoulddo--becaseinsensitive. + { + NSArray* currentList=[self objectValues]; + NSEnumerator* theEnum=[currentList objectEnumerator]; + id eachString; + int maxLength=0; + NSString* bestMatch=@""; + + while(nil!=(eachString=[theEnum nextObject])) + { + NSString* commonPrefix= [eachString commonPrefixWithString:substring options:NSCaseInsensitiveSearch]; + if([commonPrefix length]>=[substring length]&&[commonPrefix length]>maxLength) + { + maxLength=[commonPrefix length]; + bestMatch=eachString; + break; + + //Build match string based on what user has typed so far, to show changes in capitalization. + //bestMatch=[NSString stringWithFormat:@"%@%@",substring, [eachString substringFromIndex:[substringlength]]]; + } + } + return bestMatch; + } +} + +@end \ No newline at end of file diff --git a/PDCircleButton.h b/PDCircleButton.h new file mode 100644 index 0000000..2778a49 --- /dev/null +++ b/PDCircleButton.h @@ -0,0 +1,18 @@ +// +// PDCircleButton.h +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDCircleButtonCell; + +@interface PDCircleButton : NSButton { + +} + +@end diff --git a/PDCircleButton.m b/PDCircleButton.m new file mode 100644 index 0000000..5cd2b85 --- /dev/null +++ b/PDCircleButton.m @@ -0,0 +1,37 @@ +// +// PDCircleButton.m +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDCircleButton + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDCircleButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDCircleButtonCell class]; +} + + +@end diff --git a/PDCircleButtonCell.h b/PDCircleButtonCell.h new file mode 100644 index 0000000..9d8688d --- /dev/null +++ b/PDCircleButtonCell.h @@ -0,0 +1,16 @@ +// +// PDCircleButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDCircleButtonCell : NSButtonCell { + +} + +@end diff --git a/PDCircleButtonCell.m b/PDCircleButtonCell.m new file mode 100644 index 0000000..b9c87ff --- /dev/null +++ b/PDCircleButtonCell.m @@ -0,0 +1,129 @@ +// +// PDCircleButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +#define PDButtonCellFillLeft 0 +#define PDButtonCellFillCenter 1 +#define PDButtonCellFillRight 2 + +#define PDButtonCellDarkLeft 3 +#define PDButtonCellDarkCenter 4 +#define PDButtonCellDarkRight 5 + +@implementation PDCircleButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + + [self setBordered:NO]; + } + + return self; + +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + + + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + if ( [self isHighlighted] ) { + + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else { + + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + static float fontSize = 12.0; + int height = cellFrame.size.height; + int width = cellFrame.size.width; + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:fontSize], NSFontAttributeName, + ( [self isEnabled] ? [NSColor blackColor] : [NSColor lightGrayColor] ), NSForegroundColorAttributeName, nil]; + + NSSize stringSize = [[self title] sizeWithAttributes:attributes]; + + NSRect stringRect = NSMakeRect(width/2.0-stringSize.width/2.0, height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + float offset = fontSize * 1.5; + + NSRect targetRect = NSMakeRect( width/2.0 - offset/2, height/2.0 - offset/2, offset, offset ); + targetRect = NSInsetRect(targetRect,0.5,0.5); + + [[NSBezierPath bezierPathWithOvalInRect:targetRect] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithOvalInRect:targetRect] stroke]; + + [[self title] drawInRect:stringRect withAttributes:attributes]; + + +} + +@end \ No newline at end of file diff --git a/PDColorWell.h b/PDColorWell.h new file mode 100644 index 0000000..d54a971 --- /dev/null +++ b/PDColorWell.h @@ -0,0 +1,17 @@ +// +// PDColorWell.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDColorWell : NSColorWell { + +} + +@end diff --git a/PDColorWell.m b/PDColorWell.m new file mode 100644 index 0000000..677f910 --- /dev/null +++ b/PDColorWell.m @@ -0,0 +1,19 @@ +// +// PDColorWell.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDColorWell + +- (void)activate:(BOOL)exclusive { + [[self window] makeFirstResponder:self]; + [super activate:YES]; +} + +@end diff --git a/PDDateDisplayCell.h b/PDDateDisplayCell.h new file mode 100644 index 0000000..e9afc70 --- /dev/null +++ b/PDDateDisplayCell.h @@ -0,0 +1,30 @@ +// +// PDDateDisplayCell.h +// SproutedInterface +// +// Created by Philip Dow on 5/31/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDDateDisplayCell : NSTextFieldCell { + NSDateFormatter *_dayFormatter; + NSDateFormatter *_timeFormatter; + + float widthWas; + BOOL alreadyJumpedOnNoTime; + + BOOL selected; + BOOL boldsWhenSelected; +} + +- (BOOL) isSelected; +- (void) setSelected:(BOOL)isSelected; + +- (BOOL) boldsWhenSelected; +- (void) setBoldsWhenSelected:(BOOL)doesBold; + +@end diff --git a/PDDateDisplayCell.m b/PDDateDisplayCell.m new file mode 100644 index 0000000..11edc12 --- /dev/null +++ b/PDDateDisplayCell.m @@ -0,0 +1,266 @@ +// +// PDDateDisplayCell.m +// SproutedInterface +// +// Created by Philip Dow on 5/31/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define kEdgeInset 2 +static NSString *shorter_time = @"HH:mm"; + +@implementation PDDateDisplayCell + +// +// cells are copied, which means a formatter can be shared across the cells +// as the cells are resized, the smallest cell can determine the formatter's behavior across the board + +- (BOOL) isSelected +{ + return selected; +} + +- (void) setSelected:(BOOL)isSelected +{ + selected = isSelected; +} + +- (BOOL) boldsWhenSelected +{ + return boldsWhenSelected; +} + +- (void) setBoldsWhenSelected:(BOOL)doesBold +{ + boldsWhenSelected = doesBold; +} + +#pragma mark - + +- copyWithZone:(NSZone *)zone { + PDDateDisplayCell *cell = (PDDateDisplayCell *)[super copyWithZone:zone]; + //cell->_formatter = [_formatter retain]; + cell->_dayFormatter = [_dayFormatter retain]; + cell->_timeFormatter = [_timeFormatter retain]; + + cell->widthWas = widthWas; + cell->alreadyJumpedOnNoTime = alreadyJumpedOnNoTime; + + cell->selected = selected; + cell->boldsWhenSelected = boldsWhenSelected; + + return cell; +} + +- (void ) dealoc { + if ( _dayFormatter ) [_dayFormatter release]; + if ( _timeFormatter ) [_timeFormatter release]; +} + +- (NSColor*) textColor { + + //if ( [self isHighlighted] && ([[[self controlView] window] firstResponder] == [self controlView]) && + // [[[self controlView] window] isMainWindow] && [[[self controlView] window] isKeyWindow] ) + // return [NSColor whiteColor]; + if ( [self isHighlighted] && [[[self controlView] window] firstResponder] == [self controlView] ) + { + if ( [[[self controlView] window] isKindOfClass:[NSPanel class]] && [[[self controlView] window] isKeyWindow] ) + return [NSColor whiteColor]; + + else if ( [[[self controlView] window] isMainWindow] && [[[self controlView] window] isKeyWindow] ) + return [NSColor whiteColor]; + + else + return [super textColor]; + } + + else if ( [self isHighlighted] && [(NSTableView*)[self controlView] editedRow] != -1 && [(NSTableView*)[self controlView] editedColumn] != -1 ) + return [NSColor whiteColor]; + else + return [super textColor]; + +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + + NSString *time_string = nil, *day_string = nil; + NSSize time_size, day_size; + NSPoint time_origin, day_origin; + + NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [self font], NSFontAttributeName, [self textColor], NSForegroundColorAttributeName, nil]; + + if ([self isSelected]) + { + // prepare the text in white. + [attrs setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + + // bold the text if that option has been requested + if ( [self boldsWhenSelected] ) + { + NSFont *originalFont = [attrs objectForKey:NSFontAttributeName]; + if ( originalFont ) { + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:originalFont toHaveTrait:NSBoldFontMask]; + if ( boldedFont ) + [attrs setObject:boldedFont forKey:NSFontAttributeName]; + } + } + } + + NSDate *date = [self objectValue]; + if ( _dayFormatter == nil ) { + + //_formatter = [[NSDateFormatter alloc] init]; + _dayFormatter = [[NSDateFormatter alloc] init]; + _timeFormatter = [[NSDateFormatter alloc] init]; + + [_dayFormatter setDateStyle:NSDateFormatterLongStyle]; + [_dayFormatter setTimeStyle:NSDateFormatterNoStyle]; + + [_timeFormatter setDateStyle:NSDateFormatterNoStyle]; + [_timeFormatter setTimeStyle:NSDateFormatterShortStyle]; + } + + if ( cellFrame.size.width > widthWas && [_dayFormatter dateStyle] != NSDateFormatterLongStyle ) { + #ifdef __DEBUG__ + NSLog(@"%@ %s - growing", [self className], _cmd); + #endif + + // we're growing, give the original date and time format another chance + //[_timeFormatter setDateFormat:nil]; + [_dayFormatter setDateStyle:NSDateFormatterLongStyle]; + [_timeFormatter setTimeStyle:NSDateFormatterShortStyle]; + } + + widthWas = cellFrame.size.width; + + // + // draw the day on the far left in medium style + //[_formatter setDateStyle:NSDateFormatterMediumStyle]; + //[_formatter setTimeStyle:NSDateFormatterNoStyle]; + +CalculateDateSize: + + + //day_string = [_formatter stringFromDate:date]; + day_string = [_dayFormatter stringFromDate:date]; + day_size = [day_string sizeWithAttributes:attrs]; + + day_origin.x = cellFrame.origin.x + kEdgeInset; + day_origin.y = cellFrame.origin.y + cellFrame.size.height/2 - day_size.height/2; + + + +CalculateTimeSize: + + // + // draw the time on the far right in short style + //[_formatter setDateStyle:NSDateFormatterNoStyle]; + //[_formatter setTimeStyle:NSDateFormatterShortStyle]; + + //time_string = [_formatter stringFromDate:date]; + time_string = [_timeFormatter stringFromDate:date]; + time_size = [time_string sizeWithAttributes:attrs]; + + time_origin.x = cellFrame.origin.x + cellFrame.size.width - time_size.width - kEdgeInset; + time_origin.y = cellFrame.origin.y + cellFrame.size.height/2 - time_size.height/2; + + + if ( time_origin.x < day_origin.x + day_size.width + kEdgeInset*3 ) { + + // + // the time doesn't fit - first try making the date smaller + if ( /* alreadyJumpedOnNoTime == NO && */ [_dayFormatter dateStyle] == NSDateFormatterLongStyle ) { + #ifdef __DEBUG__ + NSLog(@"%@ %s - recalculating date style to NSDateFormatterMediumStyle", [self className], _cmd); + #endif + + [_dayFormatter setDateStyle:NSDateFormatterMediumStyle]; + goto CalculateDateSize; + } + else if ( alreadyJumpedOnNoTime == NO && [_dayFormatter dateStyle] == NSDateFormatterMediumStyle ) { + #ifdef __DEBUG__ + NSLog(@"%@ %s - recalculating date style to NSDateFormatterShortStyle", [self className], _cmd); + #endif + + [_dayFormatter setDateStyle:NSDateFormatterShortStyle]; + goto CalculateDateSize; + } + + // + // the time doesn't fit, make it even shorter + //[_formatter setDateFormat:@"h:mm"]; + if ( ![shorter_time isEqualToString:[_timeFormatter dateFormat]] ) + [_timeFormatter setDateFormat:shorter_time]; + + //time_string = [_formatter stringFromDate:date]; + time_string = [_timeFormatter stringFromDate:date]; + time_size = [time_string sizeWithAttributes:attrs]; + + time_origin.x = cellFrame.origin.x + cellFrame.size.width - time_size.width - kEdgeInset; + time_origin.y = cellFrame.origin.y + cellFrame.size.height/2 - time_size.height/2; + + // + // if it still doesn't fit! + if ( time_origin.x < day_origin.x + day_size.width + kEdgeInset*3 ) { + + // + // time won't fit, reset date back to medium and recalculate the size + if ( alreadyJumpedOnNoTime == NO && [_dayFormatter dateStyle] == NSDateFormatterShortStyle ) + { + [_dayFormatter setDateStyle:NSDateFormatterMediumStyle]; + alreadyJumpedOnNoTime = YES; + goto CalculateDateSize; + } + else if ( alreadyJumpedOnNoTime == NO && [_dayFormatter dateStyle] == NSDateFormatterMediumStyle ) + { + [_dayFormatter setDateStyle:NSDateFormatterLongStyle]; + alreadyJumpedOnNoTime = YES; + goto CalculateDateSize; + } + else + { + day_string = [_dayFormatter stringFromDate:date]; + day_size = [day_string sizeWithAttributes:attrs]; + + day_origin.x = cellFrame.origin.x + kEdgeInset; + day_origin.y = cellFrame.origin.y + cellFrame.size.height/2 - day_size.height/2; + + // + // zero time string + [_timeFormatter setDateFormat:[NSString string]]; + time_string = [_timeFormatter stringFromDate:date]; + + alreadyJumpedOnNoTime = NO; + } + + } + + //[_formatter setDateFormat:nil]; + + } + + // + // only draw the time string if it fits at all, even after being shortened + if ( time_string != nil && [time_string length] != 0 ) + //if ( time_origin.x >= day_origin.x + day_size.width + kEdgeInset*3 ) + [time_string drawAtPoint:time_origin withAttributes:attrs]; + + // + // actually draw the day + if ( day_string != nil ) + [day_string drawAtPoint:day_origin withAttributes:attrs]; + + alreadyJumpedOnNoTime = NO; +} + +- (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + return nil; +} + +@end diff --git a/PDFavorite.h b/PDFavorite.h new file mode 100644 index 0000000..e7e5168 --- /dev/null +++ b/PDFavorite.h @@ -0,0 +1,57 @@ +// +// PDFavorite.h +// SproutedInterface +// +// Created by Philip Dow on 3/17/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define PDFavoriteNoHover 0 +#define PDFavoriteHover 1 +#define PDFavoriteMouseDown 2 + +@interface PDFavorite : NSView { + + NSString *_title; + //NSAttributedString *_attributedTitle; + id _identifier; + //NSArray *_subElements; + + NSSize _idealSize; + int _state; + + int label; + BOOL drawsLabel; +} + +- (id) initWithFrame:(NSRect)frame title:(NSString*)title identifier:(id)identifier; + +- (NSString*) title; +- (void) setTitle:(NSString*)title; + +//- (NSAttributedString*) attributedTitle; +//- (void) setAttributedTitle:(NSAttributedString*)title; + +- (id) identifier; +- (void) setIdentifier:(id)identifier; + +- (int) state; +- (void) setState:(int)state; + +- (int) label; +- (void) setLabel:(int)aLabel; + +- (BOOL) drawsLabel; +- (void) setDrawsLabel:(BOOL)draws; + +- (NSAttributedString*) generateAttributedTitle:(NSString*)title; +- (NSAttributedString*) generateHoverAttributedTitle:(NSString*)title; +- (NSSize) idealSize; +- (NSImage*) image; + +- (void) _drawLabel:(NSRect)rect; + +@end diff --git a/PDFavorite.m b/PDFavorite.m new file mode 100644 index 0000000..6ed709d --- /dev/null +++ b/PDFavorite.m @@ -0,0 +1,304 @@ +// +// PDFavorite.m +// SproutedInterface +// +// Created by Philip Dow on 3/17/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import +#import + +static NSDictionary* TitleAttributes() +{ + static NSDictionary *textAttributes = nil; + if ( textAttributes == nil ) + { + NSMutableParagraphStyle *paragraphStyle; + + paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; + [paragraphStyle setAlignment:NSLeftTextAlignment]; + [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + textAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:11], NSFontAttributeName, + [NSColor colorWithCalibratedRed:0.20 green:0.20 blue:0.20 alpha:1.0], NSForegroundColorAttributeName, + paragraphStyle, NSParagraphStyleAttributeName, nil]; + } + return textAttributes; +} + +static NSDictionary* HoverTitleAttributes() +{ + static NSDictionary *textAttributes = nil; + if ( textAttributes == nil ) + { + NSMutableParagraphStyle *paragraphStyle; + + paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; + [paragraphStyle setAlignment:NSLeftTextAlignment]; + [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + textAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:11], NSFontAttributeName, + [NSColor colorWithCalibratedRed:0.98 green:0.98 blue:0.98 alpha:1.0], NSForegroundColorAttributeName, + paragraphStyle, NSParagraphStyleAttributeName, nil]; + } + return textAttributes; +} + +@implementation PDFavorite + +- (id) initWithFrame:(NSRect)frame title:(NSString*)title identifier:(id)identifier { + + if ( self = [self initWithFrame:frame] ) { + + _state = PDFavoriteNoHover; + _idealSize.width = -1; + + label = 0; + + if ( title ) + _title = [title copyWithZone:[self zone]]; + else + _title = [[NSString alloc] initWithString:@""]; + + if ( identifier ) + _identifier = [identifier copyWithZone:[self zone]]; + else + _identifier = [[NSString alloc] initWithString:@""]; + + } + + return self; + +} + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + } + return self; +} + +- (void) dealloc { + + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + [_title release]; + [_identifier release]; + + [super dealloc]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect +{ + // Drawing code here. + + NSRect bds = [self bounds]; + NSAttributedString *textStr; + + NSRect stateRect = bds; + NSBezierPath *roundedRect; + + switch ( _state ) { + + case PDFavoriteHover: + + stateRect.origin.x+=1; stateRect.origin.y+=2; stateRect.size.width-=1; stateRect.size.height-=5; + + roundedRect = [NSBezierPath bezierPathWithRoundedRect:stateRect cornerRadius:8.0]; + [[NSColor colorWithCalibratedRed:0.6 green:0.6 blue:0.6 alpha:1.0] set]; + [roundedRect fill]; + + textStr = [self generateHoverAttributedTitle:[self title]]; + break; + + case PDFavoriteMouseDown: + + stateRect.origin.x+=1; stateRect.origin.y+=2; stateRect.size.width-=1; stateRect.size.height-=5; + + roundedRect = [NSBezierPath bezierPathWithRoundedRect:stateRect cornerRadius:8.0]; + [[NSColor colorWithCalibratedRed:0.45 green:0.45 blue:0.45 alpha:1.0] set]; + [roundedRect fill]; + + textStr = [self generateHoverAttributedTitle:[self title]]; + break; + + default: + + if ( [self drawsLabel] && [self label] != 0 ) + { + stateRect.origin.x+=1; stateRect.origin.y+=2; stateRect.size.width-=1; stateRect.size.height-=5; + [self _drawLabel:stateRect]; + } + + textStr = [self generateAttributedTitle:[self title]]; + break; + + } + + NSSize strSize = [textStr size]; + NSRect strBds = NSMakeRect( bds.size.width/2-strSize.width/2, + bds.size.height/2-strSize.height/2, + strSize.width, strSize.height ); + + + [textStr drawInRect:strBds]; + +} + +- (void) _drawLabel:(NSRect)rect +{ + NSRect inset = rect; + NSColor *gradientStart = [NSColor colorForLabel:[self label] gradientEnd:YES]; + NSColor *gradientEnd = [NSColor colorForLabel:[self label] gradientEnd:NO]; + NSBezierPath *aPath = [NSBezierPath bezierPathWithRoundedRect:inset cornerRadius:8.0]; // 7.3 + + [[NSColor colorWithCalibratedWhite:0.6 alpha:1.0] set]; + [aPath linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; +} + +#pragma mark - + +- (NSString*) title { return _title; } + +- (void) setTitle:(NSString*)title { + if ( _title != title ) { + [_title release]; + _title = [title copyWithZone:[self zone]]; + } +} + + +- (id) identifier { return _identifier; } + +- (void) setIdentifier:(id)identifier { + if ( _identifier != identifier ) { + [_identifier release]; + _identifier = [identifier copyWithZone:[self zone]]; + } +} + +- (int) state { return _state; } + +- (void) setState:(int)state { + + _state = state; + +} + +- (int) label +{ + return label; +} + +- (void) setLabel:(int)aLabel +{ + label = aLabel; + [self setNeedsDisplay:YES]; +} + +- (BOOL) drawsLabel +{ + return drawsLabel; +} + +- (void) setDrawsLabel:(BOOL)draws +{ + drawsLabel = draws; + [self setNeedsDisplay:YES]; +} + +#pragma mark - + +- (NSAttributedString*) generateAttributedTitle:(NSString*)title +{ + NSAttributedString *attrString = [[NSAttributedString alloc] + initWithString:( title != nil ? title : @"" ) attributes:TitleAttributes()]; + + return [attrString autorelease]; +} + +- (NSAttributedString*) generateHoverAttributedTitle:(NSString*)title +{ + NSAttributedString *attrString = [[NSAttributedString alloc] + initWithString:( title != nil ? title : @"" ) attributes:HoverTitleAttributes()]; + + return [attrString autorelease]; +} + +- (NSSize) idealSize { + + if ( _idealSize.width != -1 ) + + return _idealSize; + + else { + + NSAttributedString *theAttributedTitle = [self generateAttributedTitle:[self title]]; + + _idealSize = [theAttributedTitle size]; + _idealSize.width+=16; + + // for extra label color + _idealSize.width+=4; + + return _idealSize; + + } +} + +- (NSImage*) image { + + NSRect bds = [self bounds]; + NSAttributedString *textStr; + + NSRect stateRect = bds; + NSBezierPath *roundedRect; + + NSSize idealSize = [self idealSize]; + idealSize.height = 22; + + NSImage *returnImage = [[NSImage alloc] initWithSize:idealSize]; + + [returnImage lockFocus]; + + stateRect.origin.x+=1; stateRect.origin.y+=2; stateRect.size.width-=1; stateRect.size.height-=5; + + roundedRect = [NSBezierPath bezierPathWithRoundedRect:stateRect cornerRadius:10.0]; + [[NSColor colorWithCalibratedRed:0.45 green:0.45 blue:0.45 alpha:1.0] set]; + [roundedRect fill]; + + textStr = [self generateHoverAttributedTitle:[self title]]; + + NSSize strSize = [textStr size]; + NSRect strBds = NSMakeRect( bds.size.width/2-strSize.width/2, + bds.size.height/2-strSize.height/2, + strSize.width, strSize.height ); + + [textStr drawInRect:strBds]; + + [returnImage unlockFocus]; + + return [returnImage autorelease]; + +} + +#pragma mark - + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +@end diff --git a/PDFavoritesBar.h b/PDFavoritesBar.h new file mode 100644 index 0000000..a7d9555 --- /dev/null +++ b/PDFavoritesBar.h @@ -0,0 +1,92 @@ +// +// PDFavoritesBar.h +// SproutedInterface +// +// Created by Philip Dow on 3/17/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#define PDFavoritePboardType @"PDFavoritePboardType" +#define PDFavoritesDidChangeNotification @"PDFavoritesDidChangeNotification" + +#define PDFavoriteName @"name" +#define PDFavoriteID @"id" + +#import + +@class PDFavorite; + +@interface PDFavoritesBar : NSView { + + NSColor *_backgroundColor; + NSMutableArray *_favorites; + NSMutableArray *_vFavorites; + NSMutableArray *_trackingRects; + + NSPopUpButton *_morePop; + NSMenuItem *_popTitle; + + unsigned _eventFavorite; + BOOL _titleSheet; + + id delegate; + id _target; + SEL _action; + + NSMenu *contextMenu; + + BOOL drawsLabels; +} + +- (NSColor*) backgroundColor; +- (void) setBackgroundColor:(NSColor*)color; + +- (NSMutableArray*) favorites; +- (void) setFavorites:(NSArray*)favorites; + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (id) target; +- (void) setTarget:(id)target; + +- (SEL) action; +- (void) setAction:(SEL)action; + +- (BOOL) drawsLabels; +- (void) setDrawsLabels:(BOOL)draws; + +- (IBAction) toggleDrawsLabels:(id)sender; + +- (void) sendEvent:(unsigned)sender; +- (NSDictionary*) eventFavorite; + +- (BOOL) addFavorite:(NSDictionary*)aFavorite atIndex:(unsigned)loc requestTitle:(BOOL)showSheet; +- (void) removeFavoriteAtIndex:(unsigned)loc; + +- (void) _generateFavoriteViews:(id)object; +- (void) _positionFavoriteViews:(id)object; + +- (void) _initiateDragOperation:(unsigned)favoriteIndex location:(NSPoint)dragStart event:(NSEvent*)theEvent; + +- (void) favoritesDidChange:(NSNotification*)aNotification; +- (void) _toolbarDidChangeVisible:(NSNotification*)aNotification; + +- (NSString*) _titleFromTitleSheet:(NSString*)defaultTitle; +- (void) _okaySheet:(id)sender; +- (void) _cancelSheet:(id)sender; + +- (PDFavorite*) favoriteWithIdentifier:(id)anIdentifier; +- (void) setLabel:(int)label forFavorite:(PDFavorite*)aFavorite; +- (void) rescanLabels; + +- (NSRect) frameOfFavoriteAtIndex:(int)theIndex; + +@end + +@interface NSObject (FavoritesBarDelegate) + +- (int) favoritesBar:(PDFavoritesBar*)aFavoritesBar labelOfItemWithIdentifier:(NSString*)anIdentifier; + +@end diff --git a/PDFavoritesBar.m b/PDFavoritesBar.m new file mode 100644 index 0000000..98f4a98 --- /dev/null +++ b/PDFavoritesBar.m @@ -0,0 +1,963 @@ +// +// PDFavoritesBar.m +// SproutedInterface +// +// Created by Philip Dow on 3/17/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +#import + +#import +#import + +@implementation PDFavoritesBar + +- (id)initWithFrame:(NSRect)frame { + if ( self = [super initWithFrame:frame] ) + { + // Initialization code here. + + _titleSheet = YES; + + _backgroundColor = [[NSColor windowBackgroundColor] retain]; + _favorites = [[NSMutableArray alloc] init]; + _trackingRects = [[NSMutableArray alloc] init]; + + // CHANGES + _vFavorites = [[NSMutableArray alloc] init]; + + NSImage *moreImage = [NSImage imageNamed:@"more.tif"]; + _popTitle = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + + [_popTitle setImage:moreImage]; + + _morePop = [[NSPopUpButton alloc] initWithFrame:NSMakeRect( frame.size.width - 28, 6, 28, 10 ) pullsDown:YES]; + + [_morePop setBordered:NO]; + [_morePop setTarget:self]; + [_morePop setAction:@selector(_favoriteFromPop:)]; + [_morePop setAutoresizingMask:NSViewMinXMargin]; + [_morePop setHidden:YES]; + [[_morePop menu] addItem:_popTitle]; + [[_morePop cell] setArrowPosition:NSPopUpNoArrow]; + + [self addSubview:_morePop]; + + [self setAutoresizingMask:NSViewWidthSizable|NSViewMinYMargin]; + [self registerForDraggedTypes:[NSArray arrayWithObjects:PDFavoritePboardType, nil]]; + + [self setPostsBoundsChangedNotifications:YES]; + [self setPostsFrameChangedNotifications:YES]; + + //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_generateFavoriteViews:) + //name:NSViewBoundsDidChangeNotification object:self]; + //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_generateFavoriteViews:) + //name:NSViewFrameDidChangeNotification object:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_positionFavoriteViews:) + name:NSViewBoundsDidChangeNotification object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_positionFavoriteViews:) + name:NSViewFrameDidChangeNotification object:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(favoritesDidChange:) + name:PDFavoritesDidChangeNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_toolbarDidChangeVisible:) + name:PDToolbarDidHideNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_toolbarDidChangeVisible:) + name:PDToolbarDidShowNotification object:nil]; + + // label bindings + [self bind:@"drawsLabels" toObject:[NSUserDefaultsController sharedUserDefaultsController] + withKeyPath:@"values.FavoritesBarDrawsLabels" options:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], NSNullPlaceholderBindingOption, nil]]; + + // set the initial favorites + //NSArray *theFavorites = [[NSUserDefaults standardUserDefaults] arrayForKey:@"PDFavoritesBar"]; + //if ( theFavorites == nil ) theFavorites = [NSArray array]; + //[self setFavorites:theFavorites]; + + // build the contextual menu + contextMenu = [[NSMenu alloc] initWithTitle:@"Context"]; + + NSString *aTitle = NSLocalizedStringFromTableInBundle(@"draw labels", @"PDFavoritesBar", [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], @""); + NSMenuItem *labelsToggle = [[[NSMenuItem alloc] initWithTitle:aTitle action:@selector(toggleDrawsLabels:) keyEquivalent:@""] autorelease]; + + [labelsToggle setTarget:self]; + [contextMenu addItem:labelsToggle]; + [self setMenu:contextMenu]; + + } + return self; +} + +- (void) dealloc { + + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning",[self className],_cmd); + #endif + + int i; + for ( i = 0; i < [_trackingRects count]; i++ ) + [self removeTrackingRect:[[_trackingRects objectAtIndex:i] intValue]]; + + [_trackingRects release]; + [_vFavorites release]; + + [_backgroundColor release]; + [_favorites release]; + [_morePop release]; + [_popTitle release]; + + [contextMenu release]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + //[self unbind:@"favorites"]; + [self unregisterDraggedTypes]; + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending",[self className],_cmd); + #endif + + [super dealloc]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect { + // Drawing code here. + + NSRect bds = [self bounds]; + + // fill with the label bar color + [_backgroundColor set]; + NSRectFillUsingOperation(bds, NSCompositeSourceOver); + + // draw a gradient over that + NSColor *gradientStart = [NSColor colorWithCalibratedWhite:0.86 alpha:0.8]; // 0.6 // 0.82 + NSColor *gradientEnd = [NSColor colorWithCalibratedWhite:0.88 alpha:0.8]; // 0.92 + [[NSBezierPath bezierPathWithRect:bds] linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + NSGraphicsContext *context = [NSGraphicsContext currentContext]; + [context saveGraphicsState]; + [context setShouldAntialias:NO]; + + [[NSColor darkGrayColor] set]; + [[NSBezierPath bezierPathWithLineFrom:NSMakePoint(0,bds.size.height-1) to:NSMakePoint(bds.size.width,bds.size.height-1) lineWidth:1] stroke]; + + [[NSColor colorWithCalibratedWhite:1.0 alpha:0.82] set]; + [[NSBezierPath bezierPathWithLineFrom:NSMakePoint(0,bds.size.height-2) to:NSMakePoint(bds.size.width,bds.size.height-2) lineWidth:1] stroke]; + + [context restoreGraphicsState]; +} + +#pragma mark - + +- (NSColor*) backgroundColor +{ + return _backgroundColor; + } + +- (void) setBackgroundColor:(NSColor*)color +{ + if ( _backgroundColor != color ) + { + [_backgroundColor release]; + _backgroundColor = [color copyWithZone:[self zone]]; + } +} + +- (NSMutableArray*) favorites +{ + return _favorites; +} + +- (void) setFavorites:(NSArray*)favorites +{ + if ( _favorites != favorites ) + { + [_favorites release]; + _favorites = [favorites retain]; + + // regenerate the favorites view + [self _generateFavoriteViews:nil]; + + // and re-position + //[self _positionFavoriteViews:nil]; + } +} + +#pragma mark - + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (id) target +{ + return _target; +} + +- (void) setTarget:(id)target +{ + _target = target; +} + +- (SEL) action +{ + return _action; +} + +- (void) setAction:(SEL)action +{ + _action = action; +} + +- (BOOL) drawsLabels +{ + return drawsLabels; +} + +- (void) setDrawsLabels:(BOOL)draws +{ + drawsLabels = draws; + [_vFavorites setValue:[NSNumber numberWithBool:drawsLabels] forKey:@"drawsLabel"]; +} + +- (IBAction) toggleDrawsLabels:(id)sender +{ + [[NSUserDefaults standardUserDefaults] + setBool:![[NSUserDefaults standardUserDefaults] boolForKey:@"FavoritesBarDrawsLabels"] + forKey:@"FavoritesBarDrawsLabels"]; + + //[self setDrawsLabels:![self drawsLabels]]; + //[_vFavorites setValue:[NSNumber numberWithBool:[self drawsLabels]] forKey:@"drawsLabel"]; + //[_vFavorites setValue:[NSNumber numberWithBool:YES] forKey:@"needsDisplay"]; +} + +#pragma mark - + +- (void) sendEvent:(unsigned)sender { + + _eventFavorite = sender; + if ( [[self target] respondsToSelector:[self action]] ) + [[self target] performSelector:[self action] withObject:self]; + +} + +- (NSDictionary*) eventFavorite { + + return [[self favorites] objectAtIndex:_eventFavorite]; + +} + +#pragma mark - + +- (BOOL) addFavorite:(NSDictionary*)aFavorite atIndex:(unsigned)loc requestTitle:(BOOL)showSheet { + + NSMutableArray *tempFavs = [[[self favorites] mutableCopyWithZone:[self zone]] autorelease]; + if ( tempFavs == nil ) tempFavs = [NSMutableArray array]; + + if ( loc > [tempFavs count] ) + loc = [tempFavs count]; + else if ( loc < 0 ) + loc = 0; + + // + // show a sheet if requested + if ( showSheet ) { + + NSString *newTitle = [self _titleFromTitleSheet:[aFavorite objectForKey:PDFavoriteName]]; + if ( !newTitle ) return NO; + + NSMutableDictionary *modAddition = [aFavorite mutableCopyWithZone:[self zone]]; + [modAddition setObject:newTitle forKey:PDFavoriteName]; + + [tempFavs insertObject:modAddition atIndex:loc]; + + [modAddition release]; + + } + else { + + [tempFavs insertObject:aFavorite atIndex:loc]; + + } + + [self setFavorites:tempFavs]; + [[NSUserDefaults standardUserDefaults] setObject:tempFavs forKey:@"PDFavoritesBar"]; + [[NSNotificationCenter defaultCenter] postNotificationName:PDFavoritesDidChangeNotification + object:self userInfo:[NSDictionary dictionaryWithObject:tempFavs forKey:@"favorites"]]; + + return YES; + +} + +- (void) removeFavoriteAtIndex:(unsigned)loc +{ + NSMutableArray *tempFavs = [[[self favorites] mutableCopyWithZone:[self zone]] autorelease]; + if ( tempFavs == nil ) tempFavs = [NSMutableArray array]; + + if ( loc > [tempFavs count] ) + loc = [tempFavs count]; + else if ( loc < 0 ) + loc = 0; + + [tempFavs removeObjectAtIndex:loc]; + + [self setFavorites:tempFavs]; + [self _generateFavoriteViews:self]; + [self _positionFavoriteViews:self]; + + [[NSUserDefaults standardUserDefaults] setObject:tempFavs forKey:@"PDFavoritesBar"]; + [[NSNotificationCenter defaultCenter] postNotificationName:PDFavoritesDidChangeNotification + object:self userInfo:[NSDictionary dictionaryWithObject:tempFavs forKey:@"favorites"]]; +} + +#pragma mark - + +- (void) favoritesDidChange:(NSNotification*)aNotification +{ + if ( [aNotification object] != self ) + { + NSArray *theFavorites = [[aNotification userInfo] objectForKey:@"favorites"]; + [self setFavorites:theFavorites]; + } +} + +- (PDFavorite*) favoriteWithIdentifier:(id)anIdentifier +{ + int anIndex = [[_vFavorites valueForKey:@"identifier"] indexOfObject:anIdentifier]; + if ( anIndex == NSNotFound ) return nil; + else return [_vFavorites objectAtIndex:anIndex]; +} + +- (void) setLabel:(int)label forFavorite:(PDFavorite*)aFavorite +{ + [aFavorite setLabel:label]; + [aFavorite setNeedsDisplay:YES]; +} + +- (void) rescanLabels +{ + if ( ![[self delegate] respondsToSelector:@selector(favoritesBar:labelOfItemWithIdentifier:)] ) + return; + + PDFavorite *aFavorite; + NSEnumerator *enumerator = [_vFavorites objectEnumerator]; + + while ( aFavorite = [enumerator nextObject] ) + [aFavorite setLabel:[[self delegate] favoritesBar:self labelOfItemWithIdentifier:[aFavorite identifier]]]; +} + +#pragma mark - + + +- (void) _generateFavoriteViews:(id)object { + + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning",[self className],_cmd); + #endif + + int i; + + [_vFavorites makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [_vFavorites removeAllObjects]; + + for ( i = 0; i < [_favorites count]; i++ ) { + + NSDictionary *aFavDict = [_favorites objectAtIndex:i]; + PDFavorite *aFavorite = [[[PDFavorite alloc] initWithFrame:NSMakeRect(0,0,40,22) + title:[aFavDict objectForKey:PDFavoriteName] identifier:[aFavDict objectForKey:PDFavoriteID]] autorelease]; + + if ( [[self delegate] respondsToSelector:@selector(favoritesBar:labelOfItemWithIdentifier:)] ) + [aFavorite setLabel:[[self delegate] favoritesBar:self labelOfItemWithIdentifier:[aFavorite identifier]]]; + + [_vFavorites addObject:aFavorite]; + + } + + [_vFavorites setValue:[NSNumber numberWithBool:[self drawsLabels]] forKey:@"drawsLabel"]; + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending",[self className],_cmd); + #endif +} + +- (void) _positionFavoriteViews:(id)object +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning",[self className],_cmd); + #endif + + int i; + int totalWidth = 10; + NSRect bds = [self bounds]; + + for ( i = 0; i < [_trackingRects count]; i++ ) + [self removeTrackingRect:[[_trackingRects objectAtIndex:i] intValue]]; + + [_trackingRects removeAllObjects]; + //[_vFavorites makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + [_morePop removeAllItems]; + [_morePop setHidden:YES]; + + for ( i = 0; i < [_vFavorites count]; i++ ) { + + PDFavorite *aFavorite = [_vFavorites objectAtIndex:i]; + + NSSize idealSize = [aFavorite idealSize]; + + if ( totalWidth + idealSize.width < bds.size.width - 10 ) { + + NSRect thisRect = NSMakeRect(totalWidth, 0, idealSize.width, 22); + NSTrackingRectTag thisTrack = [self addTrackingRect:thisRect owner:self userData:nil assumeInside:NO]; + + [aFavorite setFrame:thisRect]; + [_trackingRects addObject:[NSNumber numberWithInt:thisTrack]]; + + if ( [aFavorite superview] == nil ) + [self addSubview:aFavorite]; + + } + else { + + if ( [aFavorite superview] != nil ) + [aFavorite removeFromSuperview]; + + if ( [_morePop isHidden] ) + [_morePop setHidden:NO]; + if ( [_morePop numberOfItems] == 0 ) + [[_morePop menu] addItem:_popTitle]; + + NSMenuItem *thisItem = [[NSMenuItem alloc] initWithTitle:[aFavorite title] action:@selector(_favoriteFromPop:) keyEquivalent:@""]; + [thisItem setTag:i]; + [thisItem setTarget:self]; + [thisItem setRepresentedObject:aFavorite]; + + [[_morePop menu] addItem:thisItem]; + [thisItem release]; + } + + totalWidth+=idealSize.width+=4; + } + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending",[self className],_cmd); + #endif + +} + +/* +- (void) _generateFavoriteViews:(id)object { + + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning",[self className],_cmd); + #endif + + int i; + int totalWidth = 10; + NSRect bds = [self bounds]; + + if ( _trackingRects != nil ) + { + for ( i = 0; i < [_trackingRects count]; i++ ) + [self removeTrackingRect:[[_trackingRects objectAtIndex:i] intValue]]; + + [_trackingRects release]; + _trackingRects = nil; + } + + _trackingRects = [[NSMutableArray alloc] initWithCapacity:[_favorites count]]; + + if ( _vFavorites != nil ) + { + [_vFavorites makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + [_vFavorites release]; + _vFavorites = nil; + } + + _vFavorites = [[NSMutableArray alloc] initWithCapacity:[_favorites count]]; + + for ( i = 0; i < [_favorites count]; i++ ) { + + NSDictionary *aFavDict = [_favorites objectAtIndex:i]; + PDFavorite *aFavorite = [[PDFavorite alloc] initWithFrame:NSMakeRect(0,0,40,22) + title:[aFavDict objectForKey:PDFavoriteName] identifier:[aFavDict objectForKey:PDFavoriteID]]; + + if ( [[self delegate] respondsToSelector:@selector(favoritesBar:labelOfItemWithIdentifier:)] ) + [aFavorite setLabel:[[self delegate] favoritesBar:self labelOfItemWithIdentifier:[aFavorite identifier]]]; + + [_vFavorites setValue:[NSNumber numberWithBool:[self drawsLabels]] forKey:@"drawsLabel"]; + [_vFavorites addObject:aFavorite]; + + } + + [_morePop removeAllItems]; + [_morePop setHidden:YES]; + + for ( i = 0; i < [_vFavorites count]; i++ ) { + + PDFavorite *aFavorite = [_vFavorites objectAtIndex:i]; + + NSSize idealSize = [aFavorite idealSize]; + + if ( totalWidth + idealSize.width < bds.size.width - 10 ) { + + NSRect thisRect = NSMakeRect(totalWidth, 0, idealSize.width, 22); + NSTrackingRectTag thisTrack = [self addTrackingRect:thisRect owner:self userData:nil assumeInside:NO]; + + [aFavorite setFrame:thisRect]; + [_trackingRects addObject:[NSNumber numberWithInt:thisTrack]]; + [self addSubview:aFavorite]; + + } + else { + + if ( [_morePop isHidden] ) + [_morePop setHidden:NO]; + if ( [_morePop numberOfItems] == 0 ) + [[_morePop menu] addItem:_popTitle]; + + NSMenuItem *thisItem = [[NSMenuItem alloc] initWithTitle:[aFavorite title] action:@selector(_favoriteFromPop:) keyEquivalent:@""]; + [thisItem setTag:i]; + [thisItem setTarget:self]; + [thisItem setRepresentedObject:aFavorite]; + + [[_morePop menu] addItem:thisItem]; + [thisItem release]; + } + + totalWidth+=idealSize.width+=4; + } + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending",[self className],_cmd); + #endif +} +*/ + +- (void) _favoriteFromPop:(id) sender { + + [self sendEvent:[sender tag]]; + +} + +#pragma mark - + +/* +- (void)viewDidMoveToSuperview { + + if ( [self superview] != nil ) + // [self _generateFavoriteViews:nil]; + [self _positionFavoriteViews:nil]; +} +*/ + +- (void)viewDidMoveToWindow { + + if ( [self window] != nil ) + // [self _generateFavoriteViews:nil]; + [self _positionFavoriteViews:nil]; +} + +#pragma mark - + +- (void)mouseEntered:(NSEvent *)theEvent { + + int i; + NSTrackingRectTag trackTag = [theEvent trackingNumber]; + + for ( i = 0; i < [_trackingRects count]; i++ ) { + if ( [[_trackingRects objectAtIndex:i] intValue] == trackTag ) { + [[_vFavorites objectAtIndex:i] setState:PDFavoriteHover]; + [[_vFavorites objectAtIndex:i] setNeedsDisplay:YES]; + break; + } + } +} + +- (void)mouseExited:(NSEvent *)theEvent { + + int i; + NSTrackingRectTag trackTag = [theEvent trackingNumber]; + + for ( i = 0; i < [_trackingRects count]; i++ ) { + if ( [[_trackingRects objectAtIndex:i] intValue] == trackTag ) { + [[_vFavorites objectAtIndex:i] setState:PDFavoriteNoHover]; + [[_vFavorites objectAtIndex:i] setNeedsDisplay:YES]; + break; + } + } +} + +#pragma mark - + + +- (void)mouseDown:(NSEvent *)theEvent { + + // + // converts the event into a tab selection or close and + // sends ourself the message + // + + // enter my own even loop until we have some kind of result + BOOL keepOn = YES; + BOOL isInside = YES; + NSPoint localPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + NSPoint originalPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + NSRect bds = [self bounds]; + NSRect innenRect; + + int i; + int totalWidth = 10; + + for ( i = 0; i < [_vFavorites count]; i++ ) { + + PDFavorite *aFavorite = [_vFavorites objectAtIndex:i]; + NSSize idealSize = [aFavorite idealSize]; + + if ( totalWidth + idealSize.width < bds.size.width - 10 ) { + + NSRect thisRect = NSMakeRect(totalWidth, 0, idealSize.width, 22); + if ( NSPointInRect(localPoint,thisRect) ) { + innenRect = thisRect; + break; + } + } + + totalWidth+=idealSize.width+=4; + + } + + if ( i < [_vFavorites count] ) { + + [[_vFavorites objectAtIndex:i] setState:PDFavoriteMouseDown]; + [(PDFavorite*)[_vFavorites objectAtIndex:i] display]; + + while (keepOn) { + + theEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask | + NSLeftMouseDraggedMask]; + + localPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + isInside = [self mouse:localPoint inRect:innenRect]; + + switch ([theEvent type]) { + case NSLeftMouseDragged: + + if ( originalPoint.x - localPoint.x <= -10 || originalPoint.x - localPoint.x >= 10 || + originalPoint.y - localPoint.y <= -6 || originalPoint.y - localPoint.y >= 6 ) { + + [self _initiateDragOperation:i location:localPoint event:theEvent]; + keepOn = NO; + + } + + break; + + case NSLeftMouseUp: + + if (isInside) { + [self sendEvent:i]; + [[_vFavorites objectAtIndex:i] setState:PDFavoriteHover]; + [(PDFavorite*)[_vFavorites objectAtIndex:i] display]; + } + else { + [[_vFavorites objectAtIndex:i] setState:PDFavoriteNoHover]; + [(PDFavorite*)[_vFavorites objectAtIndex:i] display]; + } + + keepOn = NO; + break; + + default: + /* Ignore any other kind of event. */ + break; + } + }; + + } +} + +#pragma mark - + +- (BOOL)performDragOperation:(id )sender { + + NSPasteboard *pboard = [sender draggingPasteboard]; + //gets the dragging-specific pasteboard from the sender + + NSArray *types = [NSArray arrayWithObjects:PDFavoritePboardType, nil]; + //a list of types that we can accept + + NSString *desiredType = [pboard availableTypeFromArray:types]; + // one desired type + + if ( [desiredType isEqualToString:PDFavoritePboardType] ) { + + // + // determine where the drop is to occur and make it + + NSPoint localPoint = [self convertPoint:[sender draggingLocation] fromView:nil]; + NSDictionary *favDict = [pboard propertyListForType:PDFavoritePboardType]; + + int i; + int totalWidth = 10; + BOOL requireTitle; + + for ( i = 0; i < [_vFavorites count]; i++ ) { + + PDFavorite *aFavorite = [_vFavorites objectAtIndex:i]; + NSSize idealSize = [aFavorite idealSize]; + + if ( localPoint.x < totalWidth + idealSize.width ) + break; + + totalWidth+=idealSize.width+=4; + + } + + requireTitle = ( [sender draggingSource] != self ); + + if ( [self addFavorite:favDict atIndex:i requestTitle:requireTitle] ) + { + // regenerate and reposition favorite views + [self _generateFavoriteViews:nil]; + [self _positionFavoriteViews:nil]; + return YES; + } + else { + return NO; + } + + } + else { + + return NO; + + } + +} + +- (NSDragOperation)draggingEntered:(id )sender { + + if ( [sender draggingSource] == self ) + return NSDragOperationMove; + else + return NSDragOperationCopy; + +} + +- (NSDragOperation)draggingUpdated:(id )sender { + + if ( [sender draggingSource] == self ) + return NSDragOperationMove; + else + return NSDragOperationCopy; + +} + +- (BOOL)prepareForDragOperation:(id )sender { + + return YES; + +} + +- (void) _initiateDragOperation:(unsigned)favoriteIndex location:(NSPoint)dragStart event:(NSEvent*)theEvent { + + NSSize dragOffset = NSMakeSize(0.0, 0.0); + NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSImage *dragImage = [(PDFavorite*)[_vFavorites objectAtIndex:favoriteIndex] image]; + + //NSPoint diff; + //dragOffset.width = [[_vFavorites objectAtIndex:favoriteIndex] idealSize].width/2; + + dragStart.x = dragStart.x - [dragImage size].width/2; + dragStart.y = dragStart.y - [dragImage size].height/2; + + [pboard declareTypes:[NSArray arrayWithObjects:PDFavoritePboardType, nil] owner:self]; + [pboard setPropertyList:[_favorites objectAtIndex:favoriteIndex] forType:PDFavoritePboardType]; + + [self removeFavoriteAtIndex:favoriteIndex]; + + [self dragImage:dragImage at:dragStart offset:dragOffset event:theEvent pasteboard:pboard source:self slideBack:NO]; + +} + +#pragma mark - + +- (NSString*) _titleFromTitleSheet:(NSString*)defaultTitle { + + int result; + NSString *returnValue; + NSBundle *interfaceBundle = [NSBundle bundleWithIdentifier:@"com.sprouted.interface"]; + + // + // build the window and components + NSRect contentRect = NSMakeRect(0,0,259,127); + NSWindow *sheetWin = [[NSWindow alloc] initWithContentRect:contentRect styleMask:(NSTitledWindowMask|NSResizableWindowMask) + backing:NSBackingStoreBuffered defer:YES]; + + NSRect frameRect = [sheetWin frameRectForContentRect:contentRect]; + [sheetWin setMaxSize:NSMakeSize(600, frameRect.size.height)]; + [sheetWin setMinSize:NSMakeSize(259, frameRect.size.height)]; + + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(17,90,225,17)]; + [label setStringValue:NSLocalizedStringFromTableInBundle(@"Favorites Name",@"PDFavoritesBar",interfaceBundle,@"")]; // localize + [label setSelectable:NO]; + [label setEditable:NO]; + [label setBezeled:NO]; + [label setBordered:NO]; + [label setDrawsBackground:NO]; + [[label cell] setControlSize:NSRegularControlSize]; + [label setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; + + NSTextField *title = [[NSTextField alloc] initWithFrame:NSMakeRect(20,60,219,22)]; + [title setStringValue:defaultTitle]; + [title setSelectable:YES]; + [title setEditable:YES]; + [title setBezeled:YES]; + [title setDrawsBackground:YES]; + [title setBezelStyle:NSTextFieldSquareBezel]; + [title setAutoresizingMask:NSViewWidthSizable]; + [[title cell] setScrollable:YES]; + [[title cell] setControlSize:NSRegularControlSize]; + [title setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; + + NSButton *cancel = [[NSButton alloc] initWithFrame:NSMakeRect(81,12,82,32)]; + [cancel setTarget:self]; + [cancel setAction:@selector(_cancelSheet:)]; + [cancel setTitle:NSLocalizedStringFromTableInBundle(@"Cancel",@"PDFavoritesBar",interfaceBundle,@"")]; // localize + [cancel setBezelStyle:NSRoundedBezelStyle]; + [cancel setButtonType:NSMomentaryPushInButton]; + [cancel setKeyEquivalent:@"\E"]; + [cancel setAutoresizingMask:NSViewMinXMargin]; + [[cancel cell] setControlSize:NSRegularControlSize]; + [cancel setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; + + NSButton *okay = [[NSButton alloc] initWithFrame:NSMakeRect(163,12,82,32)]; + [okay setTarget:self]; + [okay setAction:@selector(_okaySheet:)]; + [okay setTitle:NSLocalizedStringFromTableInBundle(@"OK",@"PDFavoritesBar",interfaceBundle,@"")]; // localize + [okay setBezelStyle:NSRoundedBezelStyle]; + [okay setButtonType:NSMomentaryPushInButton]; + [okay setAutoresizingMask:NSViewMinXMargin]; + [[okay cell] setControlSize:NSRegularControlSize]; + [okay setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; + + [[sheetWin contentView] addSubview:label]; + [[sheetWin contentView] addSubview:title]; + [[sheetWin contentView] addSubview:cancel]; + [[sheetWin contentView] addSubview:okay]; + + [sheetWin setDefaultButtonCell:[okay cell]]; + + // + // set the frame + NSString *winFrameStr = [[NSUserDefaults standardUserDefaults] stringForKey:@"PDFavoritesBarWindowFrame"]; + if ( winFrameStr ) [sheetWin setFrameFromString:winFrameStr]; + + // + // run the sheet + [NSApp beginSheet:sheetWin modalForWindow:[self window] modalDelegate: nil didEndSelector: nil contextInfo: nil]; + result = [NSApp runModalForWindow:sheetWin]; + + [title validateEditing]; + + [NSApp endSheet:sheetWin]; + [sheetWin close]; + + // + // grab the value + if ( result != NSRunStoppedResponse ) + returnValue = nil; + else + returnValue = [title stringValue]; + + // + // save the frame + winFrameStr = [sheetWin stringWithSavedFrame]; + [[NSUserDefaults standardUserDefaults] setObject:winFrameStr forKey:@"PDFavoritesBarWindowFrame"]; + + // + // clean up + [cancel release]; + [okay release]; + [label release]; + [title release]; + //[sheetWin release]; + + // + // return the value + return returnValue; + +} + +- (void) _okaySheet:(id)sender +{ + [NSApp stopModal]; +} + +- (void) _cancelSheet:(id)sender +{ + [NSApp abortModal]; +} + +#pragma mark - + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +- (NSRect) frameOfFavoriteAtIndex:(int)theIndex +{ + if ( theIndex >= [_vFavorites count] ) + { + //NSLog(@"%@ %s - index %i is greater than avaible count %i", [self className], _cmd, theIndex, [_vFavorites count] - 1 ); + return NSZeroRect; + } + else + { + return [[_vFavorites objectAtIndex:theIndex] bounds]; + } +} + +#pragma mark - + +- (void) _toolbarDidChangeVisible:(NSNotification*)aNotification +{ + if ( [[self window] toolbar] == [aNotification object] ) + //[self _generateFavoriteViews:nil]; + [self _positionFavoriteViews:nil]; +} + +#pragma mark - + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + BOOL enabled = YES; + SEL action = [menuItem action]; + + if ( action == @selector(toggleDrawsLabels:) ) + [menuItem setState:( [self drawsLabels] ? NSOnState : NSOffState) ]; + + return enabled; +} + +@end diff --git a/PDFileInfoView.h b/PDFileInfoView.h new file mode 100644 index 0000000..dfcf528 --- /dev/null +++ b/PDFileInfoView.h @@ -0,0 +1,30 @@ +// +// PDFileInfoView.h +// SproutedInterface +// +// Created by Philip Dow on 6/17/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +typedef UInt32 PDFileInfoAlignment; +enum PDInfoAlignment { + PDFileInfoAlignLeft = 0, + PDFileInfoAlignRight = 1 +}; + + +@interface PDFileInfoView : NSView { + NSURL *url; + NSImageCell *cell; + PDFileInfoAlignment viewAlignment; +} + +- (NSURL*) url; +- (void) setURL:(NSURL*)aURL; + +- (void) _drawInfoForFile; + +@end diff --git a/PDFileInfoView.m b/PDFileInfoView.m new file mode 100644 index 0000000..0fdcc13 --- /dev/null +++ b/PDFileInfoView.m @@ -0,0 +1,842 @@ +// +// PDFileInfoView.m +// SproutedInterface +// +// Created by Philip Dow on 6/17/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import + +#import + +#define kFilterOffset 14 + +@implementation PDFileInfoView + +static NSString* NoNullString( NSString *aString ) +{ + return ( aString == nil ? [NSString string] : aString ); +} + +- (id)initWithFrame:(NSRect)frameRect +{ + if ( self = [super initWithFrame:frameRect] ) + { + cell = [[NSImageCell alloc] initImageCell:nil]; + [cell setImageFrameStyle:NSImageFrameNone]; + + viewAlignment = PDFileInfoAlignLeft; + } + return self; +} + +- (void) dealloc +{ + [url release]; + [cell release]; + [super dealloc]; +} + +#pragma mark - + +- (BOOL) isFlipped +{ + return YES; +} + +- (void)drawRect:(NSRect)rect { + // Drawing code here. + + [super drawRect:rect]; + + if ( [self url] == nil ) + return; + + NSRect bds = [self bounds]; + NSSize cellSize = NSMakeSize(128,128); + + NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[[self url] path]]; + [icon setSize:NSMakeSize(128,128)]; + + /* + CIFilter *perspectiveTransform = [CIFilter filterWithName:@"CIPerspectiveTransform"]; + [perspectiveTransform setDefaults]; + + CIVector *trVector = [CIVector vectorWithX:128-kFilterOffset Y:128-kFilterOffset]; + CIVector *brVector = [CIVector vectorWithX:128-kFilterOffset Y:kFilterOffset]; + CIVector *tlVector = [CIVector vectorWithX:0 Y:128]; + CIVector *blVector = [CIVector vectorWithX:0 Y:0]; + + [perspectiveTransform setValue:[NSImage CIImageFromImage:icon] forKey:@"inputImage"]; + [perspectiveTransform setValue:trVector forKey:@"inputTopRight"]; + [perspectiveTransform setValue:brVector forKey:@"inputBottomRight"]; + [perspectiveTransform setValue:tlVector forKey:@"inputTopLeft"]; + [perspectiveTransform setValue:blVector forKey:@"inputBottomLeft"]; + + icon = [NSImage imageFromCIImage: [perspectiveTransform valueForKey:@"outputImage"] ]; + + NSImage *reflectedIcon = [icon reflectedImage:0.33]; + */ + + [[NSColor colorWithCalibratedWhite:1.0 alpha:1.0] set]; + NSRectFillUsingOperation(rect, NSCompositeSourceOver); + + /* + NSRect iconBoundary; + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconBoundary = NSMakeRect( 5, bds.size.height - 5, cellSize.width+10, cellSize.height+10 ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconBoundary = NSMakeRect( bds.size.width - cellSize.width - 15, bds.size.height - 5, cellSize.width+10, cellSize.height+10 ); + */ + + NSRect iconRect; + //NSRect reflectedRect; + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconRect = NSMakeRect( 10, /*bds.size.height - cellSize.height - 30*/ 30, cellSize.width, cellSize.height ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconRect = NSMakeRect( bds.size.width - cellSize.width - 10, /*bds.size.height - cellSize.height - 30*/ 30, cellSize.width, cellSize.height ); + + //reflectedRect = iconRect; + //reflectedRect.origin.y -= 128; + + [cell setObjectValue:icon]; + [cell setImageAlignment:NSImageAlignBottom]; + [cell drawWithFrame:iconRect inView:self]; + + //[cell setObjectValue:reflectedIcon]; + //[cell setImageAlignment:NSImageAlignTop]; + //[cell drawWithFrame:reflectedRect inView:self]; + + // draw the information for the resource + [self _drawInfoForFile]; + + // set up a cursor rect +} + +- (void) _drawInfoForFile +{ + unsigned long long kBytesInKilobyte = 1024; + unsigned long long kBytesInMegabyte = 1048576; + unsigned long long kBytesInGigabyte = 1073741824; + + NSString *path = [[self url] path]; + NSFileManager *fm = [NSFileManager defaultManager]; + + FSRef fsRef; + FSCatalogInfo catInfo; + // #warning returns 0 when the file is a package/directory + + if ( ![fm fileExistsAtPath:path] ) + { + return; + } + + NSSize cellSize = NSMakeSize(128,128); + NSSize stringSize; + NSRect stringRect; + unsigned int originaXOffset= ( viewAlignment == PDFileInfoAlignLeft ? 5*2 + cellSize.width + 10 : 5*2 ); + + NSBundle *myBundle = [NSBundle bundleWithIdentifier:@"com.sprouted.interface"]; + + NSMutableParagraphStyle *titleParagraph = [[[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]] autorelease]; + [titleParagraph setLineBreakMode:NSLineBreakByTruncatingMiddle]; + + NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; + + [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0.96 alpha:0.96]]; + [textShadow setShadowOffset:NSMakeSize(0,-1)]; + + NSDictionary *titleAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + textShadow, NSShadowAttributeName, + titleParagraph, NSParagraphStyleAttributeName, nil]; + + NSDictionary *labelAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:11], NSFontAttributeName, + [NSColor colorWithCalibratedWhite:0.4 alpha:1.0], NSForegroundColorAttributeName, + textShadow, NSShadowAttributeName, nil]; + + NSDictionary *propertyAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + titleParagraph, NSParagraphStyleAttributeName, + textShadow, NSShadowAttributeName, nil]; + + MDItemRef mdItem = MDItemCreate(NULL,(CFStringRef)path); + + // derive an icon for the file based on the unique file system file number + NSDictionary *fileAttributes = [fm fileAttributesAtPath:path traverseLink:NO]; + + + NSRect bds = [self bounds]; + NSRect iconRect; + NSRect infoRect; + NSRect infoReflectionRect; + + NSSize lwTitle, lwKind, lwSize, lwCreated, lwModified, lwLastOpened, lwMax; + + lwTitle = NSMakeSize(0, 0); + lwKind = NSMakeSize(0, 0); + lwSize = NSMakeSize(0, 0); + lwCreated = NSMakeSize(0, 0); + lwModified = NSMakeSize(0, 0); + lwLastOpened = NSMakeSize(0, 0); + lwMax = NSMakeSize(0, 0); + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconRect = NSMakeRect( 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height + 20 ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconRect = NSMakeRect( bds.size.width - cellSize.width - 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height + 20 ); + + infoRect = iconRect; + infoRect.origin.x = originaXOffset; + infoRect.size.width = bds.size.width - originaXOffset; + + infoReflectionRect = infoRect; + infoReflectionRect.origin.y -= 152; + + //unsigned int xOffset = 0, yOffset = infoRect.size.height - 20; + unsigned int xOffset = originaXOffset, yOffset = 50; // 30 for the image cell, 50 is a bit arbitrary + + NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; + [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; + [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; + + // only draw if there is room for the information + if ( infoRect.size.width > 1 ) + { + + // first calculate all the label widths + + // labels + NSString *titleLabel = NSLocalizedStringFromTableInBundle(@"mditem title name", @"FileInfo", myBundle, @""); + NSString *typeLabel = NSLocalizedStringFromTableInBundle(@"mditem kind name", @"FileInfo", myBundle, @""); + NSString *sizeLabel = NSLocalizedStringFromTableInBundle(@"mditem size name", @"FileInfo", myBundle, @""); + NSString *dateLabel = NSLocalizedStringFromTableInBundle(@"mditem created name", @"FileInfo", myBundle, @""); + NSString *dateModifiedLabel = NSLocalizedStringFromTableInBundle(@"mditem modified name", @"FileInfo", myBundle, @""); + NSString *lastOpenedLabel = NSLocalizedStringFromTableInBundle(@"mditem lastopened name", @"FileInfo", myBundle, @""); + + // values + NSString *displayName = /*[fm displayNameAtPath:path];*/ [[path lastPathComponent] stringByDeletingPathExtension]; + + NSDate *dateCreated = [fileAttributes valueForKey:NSFileCreationDate]; + NSString *dateCreatedAsString = nil; + if ( dateCreated != nil ) dateCreatedAsString = NoNullString([dateFormatter stringFromDate:dateCreated]); + + NSDate *dateModified = [fileAttributes valueForKey:NSFileModificationDate]; + NSString *dateModifiedAsString = nil; + if ( dateModified != nil )dateModifiedAsString = NoNullString([dateFormatter stringFromDate:dateModified]); + + NSString *typeDescription = nil; + NSString *lastOpenedAsString = nil; + + if ( mdItem != NULL ) + { + typeDescription = [(NSString*)MDItemCopyAttribute(mdItem,(CFStringRef)kMDItemKind) autorelease]; + + NSDate *lastOpened = (NSDate*)[(NSString*)MDItemCopyAttribute(mdItem,(CFStringRef)kMDItemLastUsedDate) autorelease]; + if ( lastOpened != nil ) lastOpenedAsString = NoNullString([dateFormatter stringFromDate:lastOpened]); + + CFRelease(mdItem); + mdItem = NULL; + } + + // actually calculate the sizes + + if ( titleLabel != nil ) lwTitle = [titleLabel sizeWithAttributes:labelAttrs]; + if ( lwTitle.width > lwMax.width ) lwMax.width = lwTitle.width; + + if ( typeLabel != nil ) lwKind = [typeLabel sizeWithAttributes:labelAttrs]; + if ( lwKind.width > lwMax.width ) lwMax.width = lwKind.width; + + if ( sizeLabel != nil ) lwSize = [sizeLabel sizeWithAttributes:labelAttrs]; + if ( lwSize.width > lwMax.width ) lwMax.width = lwSize.width; + + if ( dateLabel != nil ) lwCreated = [dateLabel sizeWithAttributes:labelAttrs]; + if ( lwCreated.width > lwMax.width ) lwMax.width = lwCreated.width; + + if ( dateModifiedLabel != nil ) lwModified = [dateModifiedLabel sizeWithAttributes:labelAttrs]; + if ( lwModified.width > lwMax.width ) lwMax.width = lwModified.width; + + if ( lastOpenedLabel != nil ) lwLastOpened = [lastOpenedLabel sizeWithAttributes:labelAttrs]; + if ( lwLastOpened.width > lwMax.width ) lwMax.width = lwLastOpened.width; + + // max widths + unsigned int maxWidth = [self bounds].size.width - ( xOffset + lwMax.width + 8 + 20 ); + float greatestWidth = 0; + + // do the drawing + + // display name + if ( displayName != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwTitle.width), yOffset, lwTitle.width, lwTitle.height ); + [titleLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwTitle.width > greatestWidth ) + greatestWidth = xOffset + lwTitle.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [displayName sizeWithAttributes:titleAttrs]; + [displayName drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:titleAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } + + // file type + if ( typeLabel != nil && typeDescription != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwKind.width), yOffset, lwKind.width, lwKind.height ); + [typeLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwKind.width > greatestWidth ) + greatestWidth = xOffset + lwKind.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [typeDescription sizeWithAttributes:propertyAttrs]; + stringRect = NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ); + [typeDescription drawInRect:stringRect withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } // file type + + // file size + if ( FSPathMakeRef((const UInt8 *)[path UTF8String] ,&fsRef,NULL) == noErr && + FSGetCatalogInfo(&fsRef,kFSCatInfoGettableInfo,&catInfo,NULL,NULL,NULL) == noErr ) + { + // is it necessary to add the resource size? + UInt64 file_size = catInfo.dataPhysicalSize + catInfo.rsrcPhysicalSize; + NSString *fileSizeAsString; + + if ( file_size != 0 ) + { + if ( file_size / kBytesInGigabyte > 1 ) + { + NSNumber *gigabytes = [NSNumber numberWithInt:(file_size / kBytesInGigabyte)]; + fileSizeAsString = NoNullString( [[gigabytes stringValue] stringByAppendingString: + NSLocalizedStringFromTableInBundle(@"mditem size gb", @"FileInfo", myBundle, @"")] ); + } + else + { + if ( file_size / kBytesInMegabyte > 1 ) + { + NSNumber *megabytes = [NSNumber numberWithInt:(file_size / kBytesInMegabyte)]; + fileSizeAsString = NoNullString( [[megabytes stringValue] stringByAppendingString: + NSLocalizedStringFromTableInBundle(@"mditem size mb", @"FileInfo", myBundle, @"")] ); + } + else + { + NSNumber *kilobytes = [NSNumber numberWithInt:(file_size / kBytesInKilobyte)]; + fileSizeAsString = NoNullString( [[kilobytes stringValue] stringByAppendingString: + NSLocalizedStringFromTableInBundle(@"mditem size kb", @"FileInfo", myBundle, @"")] ); + } + } + + + + if ( sizeLabel != nil && fileSizeAsString != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwSize.width), yOffset, lwSize.width, lwSize.height ); + [sizeLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwSize.width > greatestWidth ) + greatestWidth = xOffset + lwSize.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [fileSizeAsString sizeWithAttributes:propertyAttrs]; + stringRect = NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ); + [fileSizeAsString drawInRect:stringRect withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } + } + } // file size + + + // date created + if ( dateLabel != nil && dateCreatedAsString != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwCreated.width), yOffset, lwCreated.width, lwCreated.height ); + [dateLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwCreated.width > greatestWidth ) + greatestWidth = xOffset + lwCreated.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [dateCreatedAsString sizeWithAttributes:propertyAttrs]; + stringRect = NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ); + [dateCreatedAsString drawInRect:stringRect withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } // date created + + + // date modified + if ( dateModifiedLabel != nil && dateModifiedAsString != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwModified.width), yOffset, lwModified.width, lwModified.height ); + [dateModifiedLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwModified.width > greatestWidth ) + greatestWidth = xOffset + lwModified.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [dateModifiedAsString sizeWithAttributes:propertyAttrs]; + stringRect = NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ); + [dateModifiedAsString drawInRect:stringRect withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } // date modified + + + // last opened + if ( lastOpenedLabel != nil && lastOpenedAsString != nil ) + { + // label + stringRect = NSMakeRect( xOffset + ( lwMax.width - lwLastOpened.width), yOffset, lwLastOpened.width, lwLastOpened.height ); + [lastOpenedLabel drawInRect:stringRect withAttributes:labelAttrs]; + + if ( xOffset + lwLastOpened.width > greatestWidth ) + greatestWidth = xOffset + lwLastOpened.width; + + xOffset += lwMax.width; + xOffset += 8; + + // value + stringSize = [lastOpenedAsString sizeWithAttributes:propertyAttrs]; + stringRect = NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ); + [lastOpenedAsString drawInRect:stringRect withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + yOffset += stringSize.height; + xOffset = originaXOffset; + } // last opened + } +} + + +/* + +- (void) _drawInfoForFile +{ + unsigned long long kBytesInKilobyte = 1024; + unsigned long long kBytesInMegabyte = 1048576; + unsigned long long kBytesInGigabyte = 1073741824; + + NSString *path = [[self url] path]; + NSFileManager *fm = [NSFileManager defaultManager]; + + FSRef fsRef; + FSCatalogInfo catInfo; + // #warning returns 0 when the file is a package/directory + + if ( ![fm fileExistsAtPath:path] ) + { + return; + } + + NSSize cellSize = NSMakeSize(128,128); + NSSize stringSize; + //NSRect stringRect; + unsigned int originaXOffset= ( viewAlignment == PDFileInfoAlignLeft ? 5*2 + cellSize.width + 10 : 5*2 ); + + //unsigned int xOffset = originaXOffset, yOffset = 20; + //unsigned int xOffset = 0, yOffset = [self bounds].size.height - 20; + unsigned int maxWidth = [self bounds].size.width - ( 5*2 + cellSize.width + 10*2 ); + float greatestWidth = 0; + + NSMutableParagraphStyle *titleParagraph = [[[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]] autorelease]; + [titleParagraph setLineBreakMode:NSLineBreakByTruncatingTail]; + + NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; + + [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0.96 alpha:0.96]]; + [textShadow setShadowOffset:NSMakeSize(0,-1)]; + + NSDictionary *titleAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:13], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + textShadow, NSShadowAttributeName, + titleParagraph, NSParagraphStyleAttributeName, nil]; + + NSDictionary *labelAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:13], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + textShadow, NSShadowAttributeName, nil]; + + NSDictionary *propertyAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:13], NSFontAttributeName, + [NSColor blackColor], NSForegroundColorAttributeName, + titleParagraph, NSParagraphStyleAttributeName, + textShadow, NSShadowAttributeName, nil]; + + MDItemRef mdItem = MDItemCreate(NULL,(CFStringRef)path); + + // derive an icon for the file based on the unique file system file number + NSDictionary *fileAttributes = [fm fileAttributesAtPath:path traverseLink:NO]; + + + NSRect bds = [self bounds]; + NSRect iconRect; + NSRect infoRect; + NSRect infoReflectionRect; + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconRect = NSMakeRect( 10, bds.size.height - cellSize.height -10, cellSize.width, cellSize.height ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconRect = NSMakeRect( bds.size.width - cellSize.width - 10, bds.size.height - cellSize.height -10, cellSize.width, cellSize.height ); + + infoRect = iconRect; + infoRect.origin.x = originaXOffset; + infoRect.size.width = bds.size.width - originaXOffset; + + infoReflectionRect = infoRect; + infoReflectionRect.origin.y -= 132; + + unsigned int xOffset = 0, yOffset = infoRect.size.height - 20; + + // only draw if there is room for the information + if ( infoRect.size.width > 1 ) + { + + NSImage *textImage = [[[NSImage alloc] initWithSize:infoRect.size] autorelease]; + + [textImage lockFocus]; + + // draw the header + NSString *displayName = [fm displayNameAtPath:path]; + if ( displayName != nil ) + { + stringSize = [displayName sizeWithAttributes:titleAttrs]; + [displayName drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:titleAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //yOffset += 14; + yOffset -= stringSize.height; + yOffset -= 14; + } + + // file type + if ( mdItem != NULL ) + { + NSString *typeLabel = NSLocalizedString(@"mditem kind name",@""); + NSString *typeDescription = [(NSString*)MDItemCopyAttribute(mdItem,(CFStringRef)kMDItemKind) autorelease]; + + if ( typeLabel != nil && typeDescription != nil ) + { + stringSize = [typeLabel sizeWithAttributes:labelAttrs]; + [typeLabel drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:labelAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + xOffset += ( stringSize.width < maxWidth ? stringSize.width : maxWidth ); + xOffset += 8; + + stringSize = [typeDescription sizeWithAttributes:propertyAttrs]; + [typeDescription drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //xOffset = originaXOffset; + yOffset -= stringSize.height; + xOffset = 0; + } + } + + // file size + if ( FSPathMakeRef((const UInt8 *)[path UTF8String] ,&fsRef,NULL) == noErr && + FSGetCatalogInfo(&fsRef,kFSCatInfoGettableInfo,&catInfo,NULL,NULL,NULL) == noErr ) + { + + // is it necessary to add the resource size? + UInt64 file_size = catInfo.dataPhysicalSize + catInfo.rsrcPhysicalSize; + NSString *fileSizeAsString; + + if ( file_size != 0 ) + { + if ( file_size / kBytesInGigabyte > 1 ) + { + NSNumber *gigabytes = [NSNumber numberWithInt:(file_size / kBytesInGigabyte)]; + fileSizeAsString = NoNullString([[gigabytes stringValue] stringByAppendingString:NSLocalizedString(@"mditem size gb",@"")]); + } + else + { + if ( file_size / kBytesInMegabyte > 1 ) + { + NSNumber *megabytes = [NSNumber numberWithInt:(file_size / kBytesInMegabyte)]; + fileSizeAsString = NoNullString([[megabytes stringValue] stringByAppendingString:NSLocalizedString(@"mditem size mb",@"")]); + } + else + { + NSNumber *kilobytes = [NSNumber numberWithInt:(file_size / kBytesInKilobyte)]; + fileSizeAsString = NoNullString([[kilobytes stringValue] stringByAppendingString:NSLocalizedString(@"mditem size kb",@"")]); + } + } + + NSString *sizeLabel = NSLocalizedString(@"mditem size name",@""); + + if ( sizeLabel != nil && fileSizeAsString != nil ) + { + stringSize = [sizeLabel sizeWithAttributes:labelAttrs]; + [sizeLabel drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:labelAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + xOffset += ( stringSize.width < maxWidth ? stringSize.width : maxWidth ); + xOffset += 8; + + stringSize = [fileSizeAsString sizeWithAttributes:propertyAttrs]; + [fileSizeAsString drawInRect:NSMakeRect( xOffset, yOffset, ( stringSize.width < maxWidth ? stringSize.width : maxWidth ), stringSize.height ) withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //xOffset = originaXOffset; + yOffset -= stringSize.height; + xOffset = 0; + } + } + } + + // date created and modified; + NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease]; + [dateFormatter setDateStyle:NSDateFormatterLongStyle]; + [dateFormatter setTimeStyle:NSDateFormatterShortStyle]; + + // date created + NSDate *dateCreated = [fileAttributes valueForKey:NSFileCreationDate]; + if ( dateCreated != nil ) + { + NSString *dateLabel = NSLocalizedString(@"mditem created name",@""); + NSString *dateCreatedAsString = NoNullString([dateFormatter stringFromDate:dateCreated]); + + if ( dateLabel != nil && dateCreatedAsString != nil ) + { + stringSize = [dateLabel sizeWithAttributes:labelAttrs]; + [dateLabel drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:labelAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + xOffset += stringSize.width; + xOffset += 8; + + stringSize = [dateCreatedAsString sizeWithAttributes:propertyAttrs]; + [dateCreatedAsString drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //xOffset = originaXOffset; + yOffset -= stringSize.height; + xOffset = 0; + } + } + + // date modified + NSDate *dateModified = [fileAttributes valueForKey:NSFileModificationDate]; + if ( dateModified != nil ) + { + NSString *dateModifiedLabel = NSLocalizedString(@"mditem modified name",@""); + NSString *dateModifiedAsString = NoNullString([dateFormatter stringFromDate:dateModified]); + + if ( dateModifiedLabel != nil && dateModifiedAsString != nil ) + { + stringSize = [dateModifiedLabel sizeWithAttributes:labelAttrs]; + [dateModifiedLabel drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:labelAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + xOffset += stringSize.width; + xOffset += 8; + + stringSize = [dateModifiedAsString sizeWithAttributes:propertyAttrs]; + [dateModifiedAsString drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //xOffset = originaXOffset; + yOffset -= stringSize.height; + xOffset = 0; + } + } + + // last opened + if ( mdItem != NULL ) + { + NSDate *lastOpened = (NSDate*)[(NSString*)MDItemCopyAttribute(mdItem,(CFStringRef)kMDItemLastUsedDate) autorelease]; + if ( lastOpened != nil ) + { + NSString *lastOpenedLabel = NSLocalizedString(@"mditem lastopened name",@""); + NSString *lastOpenedAsString = NoNullString([dateFormatter stringFromDate:lastOpened]); + + if ( lastOpenedLabel != nil && lastOpenedAsString != nil ) + { + stringSize = [lastOpenedLabel sizeWithAttributes:labelAttrs]; + [lastOpenedLabel drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:labelAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + xOffset += stringSize.width; + xOffset += 8; + + stringSize = [lastOpenedAsString sizeWithAttributes:propertyAttrs]; + [lastOpenedAsString drawInRect:NSMakeRect( xOffset, yOffset, stringSize.width, stringSize.height ) withAttributes:propertyAttrs]; + + if ( xOffset + stringSize.width > greatestWidth ) + greatestWidth = xOffset + stringSize.width; + + //yOffset += stringSize.height; + //xOffset = originaXOffset; + yOffset -= stringSize.height; + xOffset = 0; + } + } + + // clean up + CFRelease(mdItem); + + } + + [textImage unlockFocus]; + [textImage drawInRect:infoRect fromRect:NSMakeRect(0,0,infoRect.size.width,infoRect.size.height) + operation:NSCompositeSourceOver fraction:1.0]; + + // draw the reflection + + NSImage *reflectedText = [NSImage reflectedImage:textImage amountReflected:0.33]; + + [cell setImageAlignment:NSImageAlignTop]; + [cell setObjectValue:reflectedText]; + [cell drawInteriorWithFrame:infoReflectionRect inView:self]; + } +} + +*/ + +#pragma mark - + +- (void)resetCursorRects +{ + NSRect iconRect; + + NSRect bds = [self bounds]; + NSSize cellSize = NSMakeSize(128,128); + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconRect = NSMakeRect( 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconRect = NSMakeRect( bds.size.width - cellSize.width - 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height ); + + [self addCursorRect:iconRect cursor:[NSCursor pointingHandCursor]]; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + NSPoint curPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + NSRect iconRect; + + NSRect bds = [self bounds]; + NSSize cellSize = NSMakeSize(128,128); + + if ( viewAlignment == PDFileInfoAlignLeft ) + iconRect = NSMakeRect( 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height ); + else if ( viewAlignment == PDFileInfoAlignRight ) + iconRect = NSMakeRect( bds.size.width - cellSize.width - 10, bds.size.height - cellSize.height - 30, cellSize.width, cellSize.height ); + + if ( NSMouseInRect(curPoint,iconRect,[self isFlipped]) ) + { + if ( ![[NSWorkspace sharedWorkspace] openFile:[[self url] path]] ) + { + if ( ![[NSWorkspace sharedWorkspace] selectFile:[[self url] path] inFileViewerRootedAtPath: + [[[self url] path] stringByDeletingLastPathComponent]] ) + NSBeep(); + } + } + else + [super mouseDown:theEvent]; +} + +#pragma mark - + +- (NSURL*) url +{ + return url; +} + +- (void) setURL:(NSURL*)aURL +{ + if ( aURL != url ) + { + [url release]; + url = [aURL copyWithZone:[self zone]]; + + [[self window] invalidateCursorRectsForView:self]; + } +} + + +@end diff --git a/PDFontDisplay.h b/PDFontDisplay.h new file mode 100644 index 0000000..7875f77 --- /dev/null +++ b/PDFontDisplay.h @@ -0,0 +1,18 @@ +// +// PDFontDisplay.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDFontPreview; + +@interface PDFontDisplay : NSView +{ +} + +@end diff --git a/PDFontDisplay.m b/PDFontDisplay.m new file mode 100644 index 0000000..cd26c02 --- /dev/null +++ b/PDFontDisplay.m @@ -0,0 +1,63 @@ +// +// PDFontDisplay.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDFontDisplay + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) { + // Add initialization code here + } + return self; +} + +- (void)drawRect:(NSRect)rect { + + /* + This view whites out the background, draws a control rect around itself, + and then displays the font according to its superview's font and color preferences. + The result is similar to that found in Safari's or Mail's preferences. + */ + + NSRect bds = [self bounds]; + + //fills it white + [[NSColor whiteColor] set]; + NSRectFillUsingOperation(NSMakeRect( 1, 1, bds.size.width-2, bds.size.height-2), NSCompositeSourceOver); + + //get a string description of the font + NSString *drawString = [NSString stringWithFormat:@"%@ %i", [[(PDFontPreview*)[self superview] font] displayName], + [[NSNumber numberWithFloat:[[(PDFontPreview*)[self superview] font] pointSize]] intValue]]; + + //set up our attributes so we know how to draw the string + NSMutableDictionary *tempAttributes = [NSMutableDictionary dictionary]; + [tempAttributes setObject:[(PDFontPreview*)[self superview] font] forKey:NSFontAttributeName]; + + //make sure our color is correct + [tempAttributes setObject:[(PDFontPreview*)[self superview] color] forKey:NSForegroundColorAttributeName]; + + //grab the fonts size + NSSize stringSize = [drawString sizeWithAttributes:tempAttributes]; + //center a rect + NSRect stringRect = NSMakeRect( bds.size.width/2 - stringSize.width/2, bds.size.height/2 - stringSize.height/2, + stringSize.width, stringSize.height ); + + //and draw the string in the rect + [drawString drawInRect:stringRect withAttributes:tempAttributes]; + + //draws an outline around the guy, just like with other views + //last to cover up any text that might overflow into this single pixel line + [[NSColor controlShadowColor] set ]; + NSFrameRect(bds); +} + +@end diff --git a/PDFontPreview.h b/PDFontPreview.h new file mode 100644 index 0000000..220ebc4 --- /dev/null +++ b/PDFontPreview.h @@ -0,0 +1,96 @@ +// +// PDFontPreview.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDButtonColorWell; +@class PDFontDisplay; + +@interface PDFontPreview : NSView +{ + PDFontDisplay *fontDisplay; + NSButton *changeFont; + /*NSColorWell *fontColor;*/ + PDButtonColorWell *fontColor; + + NSFont *font; + NSColor *color; + + NSString *_defaultsKey; + NSString *colorDefaultsKey; + + id target; + SEL selector; +} + +// ------------------------------------------------- +// +// Key-Value methods for setting the three user defaults keys. +// It is important to set these values. +// +// ------------------------------------------------- + +// +// used for encoding the font object as archived data +- (void) setDefaultsKey:(NSString*)aKey; +- (NSString*) defaultsKey; + +- (void) setColorDefaultsKey:(NSString*)newObject; +- (NSString*) colorDefaultsKey; + + +// ------------------------------------------------- +// +// Key-Value methods for setting the initial font and color methods. +// It is not necessary to use these methods. Setting the user defaults +// keys using the above methods will initialize the color and font values. +// +// ------------------------------------------------- + +- (void) setFont:(NSFont*)newObject; +- (NSFont*) font; +- (void) setColor:(NSColor*)newObject; +- (NSColor*) color; + +// ------------------------------------------------- +// +// If you do not want the user to be able to change the font color, +// call setColorHidden and pass YES. +// +// ------------------------------------------------- + +- (void) setColorHidden:(BOOL)hideColor; +- (BOOL) colorHidden; + +// ------------------------------------------------- +// +// Target-Action behavior. PDFontPreview can behave like a control if +// you set a target and action. Whenever the font or color is changed, +// the action will be triggered. PDFontPreview passes itself as the only +// object to the selector. You can retrieve the new font and color settings +// by calling the above font and color accessors. +// +// ------------------------------------------------- + +- (void) setTarget:(id) newTarget; +- (void) setAction:(SEL) newSelector; + +// ------------------------------------------------- +// +// Internal methods, actions called by the Set Font button +// and the color well. You should not call these methods. +// +// ------------------------------------------------- + +- (void) selectFont:(id) sender; +- (void) selectColor:(id) sender; + +- (void) changeColor:(id) sender; + +@end diff --git a/PDFontPreview.m b/PDFontPreview.m new file mode 100644 index 0000000..293ec70 --- /dev/null +++ b/PDFontPreview.m @@ -0,0 +1,262 @@ +// +// PDFontPreview.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import +#import + +@implementation PDFontPreview + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) { + + NSRect oldFrame; + NSPoint buttonOrigin; + + //building the Set Font button from scratch + changeFont = [[NSButton alloc] initWithFrame:NSMakeRect( frameRect.size.width-104, frameRect.size.height/2-16, 104, 32 )]; + [changeFont setButtonType:NSMomentaryPushInButton]; + [changeFont setBezelStyle:NSRoundedBezelStyle]; + [changeFont setBordered:YES]; + [changeFont setTarget:self]; + [changeFont setAction:@selector(selectFont:)]; + [changeFont setTitle:NSLocalizedStringFromTableInBundle(@"set font title", @"PDFontPreview", [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], @"")]; + [changeFont sizeToFit]; + + oldFrame = [changeFont frame]; + oldFrame.size.width+=10; + [changeFont setFrame:oldFrame]; + + buttonOrigin = NSMakePoint(frameRect.size.width - [changeFont frame].size.width, frameRect.size.height/2-16 - 1); + + [changeFont setFrameOrigin:buttonOrigin]; + [self addSubview:changeFont]; + + //building the PDFontDisplay view from scratch + fontDisplay = [[PDFontDisplay alloc] initWithFrame: + NSMakeRect( 0, frameRect.size.height/2-13, buttonOrigin.x-25, 26 )]; + + [self addSubview:fontDisplay]; + + //building the Color button from scratch + /*fontColor = [[NSColorWell alloc] initWithFrame: + NSMakeRect( buttonOrigin.x-26, frameRect.size.height/2-13, 20, 26 )];*/ + + fontColor = [[PDButtonColorWell alloc] initWithFrame: + NSMakeRect( buttonOrigin.x-26, frameRect.size.height/2-13, 20, 26 )]; + [fontColor setColor:[NSColor blackColor]]; + //[fontColor setTarget:self]; + //[fontColor setAction:@selector(changeColor:)]; + + [fontColor setTarget:self]; + [fontColor setAction:@selector(selectColor:)]; + + [self addSubview:fontColor]; + + //default font and color + [self setFont:[NSFont systemFontOfSize:12.0]]; + [self setColor:[NSColor blackColor]]; + + //default keys - you must change these values in your object's init or awakeFromNib code. + + _defaultsKey = [[NSString alloc] initWithString:@"FontDefault"]; + colorDefaultsKey = [[NSString alloc] initWithString:@"Color Preview Default"]; + + //no target or selector + target = nil; + selector = nil; + + } + return self; +} + +- (void) dealloc { + + [_defaultsKey release]; + _defaultsKey = nil; + + [changeFont release]; + changeFont = nil; + [fontDisplay release]; + fontDisplay = nil; + + [colorDefaultsKey release]; + colorDefaultsKey = nil; + + [fontColor release]; + fontColor = nil; + [color release]; + color = nil; + [font release]; + font = nil; + + [super dealloc]; +} + +#pragma mark - + +- (NSString*) defaultsKey { return _defaultsKey; } + +- (void) setDefaultsKey:(NSString*)aKey { + + if ( _defaultsKey != aKey ) { + [_defaultsKey release]; + _defaultsKey = [aKey copyWithZone:[self zone]]; + } + + NSFont *aFont = [[NSUserDefaults standardUserDefaults] fontForKey:aKey]; + if ( aFont != nil ) [self setFont:aFont]; + +} + +- (void) setColorDefaultsKey:(NSString*)newObject { + + if ( colorDefaultsKey != newObject ) { + [colorDefaultsKey release]; + colorDefaultsKey = [newObject copyWithZone:[self zone]]; + } + + //and once we have our color, set the color and image well + NSData *theData=[[NSUserDefaults standardUserDefaults] dataForKey:newObject]; + if (theData) { + [self setColor:(NSColor *)[NSUnarchiver unarchiveObjectWithData:theData]]; + [fontColor setColor:[self color]]; + } +} + +- (NSString*) colorDefaultsKey { + return colorDefaultsKey; +} + +#pragma mark - + +- (void) setFont:(NSFont*)newObject { + + //copy our font object + if ( font != newObject ) { + [font release]; + font = [newObject copyWithZone:[self zone]]; + } + + // + //set the defaults for size and name + if ( [self defaultsKey] ) + [[NSUserDefaults standardUserDefaults] setFont:font forKey:[self defaultsKey]]; + + //anytime we change our font, we must change the display font + [fontDisplay setNeedsDisplay:YES]; + +} + +- (NSFont*) font { + return font; +} + +- (void) setColor:(NSColor*)newObject { + + //copy the color into our object + if ( color != newObject ) { + [color release]; + color = [newObject copyWithZone:[self zone]]; + } + + //set the user default + if ( [self colorDefaultsKey] ) + [[NSUserDefaults standardUserDefaults] setObject:[NSArchiver archivedDataWithRootObject:color] forKey:colorDefaultsKey]; + + //anytime we change our color, we must change the display color + [fontDisplay setNeedsDisplay:YES]; + +} + +- (NSColor*) color { + return color; +} + + +- (void) setColorHidden:(BOOL)hideColor { + + int dif = 0; + + //resize our font display accordingly + if ( hideColor && ![fontColor isHidden] ) + dif += ([fontColor frame].size.width-1); + else if ( !hideColor && [fontColor isHidden] ) + dif -= ([fontColor frame].size.width+-1); + + if ( dif ) { + NSRect displayRect = [fontDisplay frame]; + displayRect.size.width += dif; + [fontDisplay setFrame:displayRect]; + } + + //and pass the hiddenness on + [fontColor setHidden:hideColor]; +} + +- (BOOL) colorHidden { + return [fontColor isHidden]; +} + + +- (void) setTarget:(id) newTarget { + target = newTarget; +} + +- (void) setAction:(SEL) newSelector { + selector = newSelector; +} + +#pragma mark - + +- (void) selectFont:(id) sender { + //set me to first responder so I catch font changes + [[self window] makeFirstResponder:self]; + //set the font panel's current font + [[NSFontPanel sharedFontPanel] setPanelFont:[self font] isMultiple:NO]; + //show the font panel + [[NSFontPanel sharedFontPanel] makeKeyAndOrderFront:self]; +} + +- (void) selectColor:(id) sender { + [[self window] makeFirstResponder:fontColor]; + [[NSColorPanel sharedColorPanel] setColor:[self color]]; + [NSApp orderFrontColorPanel:fontColor]; +} + +- (void) changeColor:(id) sender { + //send it off to our display + [self setColor:[sender color]]; + [fontColor setColor:[sender color]]; + //and send our action + if ( target && selector ) [target performSelector:selector withObject:self]; +} + +- (void)changeFont:(id)sender { + + NSFont *oldFont = [self font]; + NSFont *newFont = [sender convertFont:oldFont]; + + [self setFont:newFont]; + + //and send our action + if ( target && selector ) [target performSelector:selector withObject:self]; +} + +- (void)drawRect:(NSRect)rect +{ + /* + This view does not draw anything. It's simply a superview which abstractly manages + its component parts, making it simpler for the programmer and user to interact with them. + */ +} + +@end diff --git a/PDGradientView.h b/PDGradientView.h new file mode 100644 index 0000000..d99fac5 --- /dev/null +++ b/PDGradientView.h @@ -0,0 +1,48 @@ +// +// PDGradientView.h +// SproutedInterface +// +// Created by Philip Dow on 10/20/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import // needed for Core Image + +@interface PDGradientView : NSView { + + NSColor *gradientStartColor; + NSColor *gradientEndColor; + NSColor *backgroundColor; + + int borders[4]; + BOOL bordered; + + NSColor *fillColor; + NSColor *borderColor; + +} + +- (int*) borders; +- (void) setBorders:(int*)sides; + +- (BOOL) bordered; +- (void) setBordered:(BOOL)flag; + +- (NSColor*) fillColor; +- (void) setFillColor:(NSColor*)aColor; + +- (NSColor*) borderColor; +- (void) setBorderColor:(NSColor*)aColor; + +- (NSColor *)gradientStartColor; +- (void)setGradientStartColor:(NSColor *)newGradientStartColor; +- (NSColor *)gradientEndColor; +- (void)setGradientEndColor:(NSColor *)newGradientEndColor; +- (NSColor *)backgroundColor; +- (void)setBackgroundColor:(NSColor *)newBackgroundColor; + +- (void) resetGradient; + +@end diff --git a/PDGradientView.m b/PDGradientView.m new file mode 100644 index 0000000..38bf01b --- /dev/null +++ b/PDGradientView.m @@ -0,0 +1,310 @@ +// +// PDGradientView.m +// SproutedInterface +// +// Created by Philip Dow on 10/20/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDGradientView + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + + if ( [self respondsToSelector:@selector(addTrackingArea:)] ) + { + //10.5 + [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.82 alpha:0.8]]; // 1.0, 0.6 + [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.92 alpha:0.8]]; // 1.0 + } + else + { + //10.4 + [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.92 alpha:0.8]]; // 1.0, 0.6 + [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.82 alpha:0.8]]; // 1.0 + } + [self setBackgroundColor:[NSColor windowBackgroundColor]]; // 1.0 + + fillColor = [[NSColor whiteColor] retain]; + borderColor = [[NSColor colorWithCalibratedRed:157.0/255.0 green:157.0/255.0 blue:157.0/255.0 alpha:1.0] retain]; + + bordered = NO; + + borders[0] = 0; // top + borders[1] = 0; // right + borders[2] = 0; // bottom + borders[3] = 0; // left + + } + return self; +} + +- (void) dealloc { + [gradientStartColor release]; + [gradientEndColor release]; + [backgroundColor release]; + [fillColor release]; + [borderColor release]; + + [super dealloc]; +} + +#pragma mark - + +- (void) resetGradient +{ + [self setGradientStartColor:[NSColor colorWithCalibratedWhite:0.92 alpha:0.6]]; // 1.0 + [self setGradientEndColor:[NSColor colorWithCalibratedWhite:0.82 alpha:0.6]]; // 1.0 + [self setBackgroundColor:[NSColor windowBackgroundColor]]; // 1.0 +} + +#pragma mark - + +- (int*) borders { + return borders; +} + +- (void) setBorders:(int*)sides { + + borders[0] = sides[0]; + borders[1] = sides[1]; + borders[2] = sides[2]; + borders[3] = sides[3]; +} + +- (BOOL) bordered { + return bordered; +} + +- (void) setBordered:(BOOL)flag { + bordered = flag; +} + +- (NSColor*) fillColor { + return fillColor; +} + +- (void) setFillColor:(NSColor*)aColor { + + if ( fillColor != aColor ) { + [fillColor release]; + fillColor = [aColor copyWithZone:[self zone]]; + } +} + +- (NSColor*) borderColor { + return borderColor; +} + +- (void) setBorderColor:(NSColor*)aColor { + + if ( borderColor != aColor ) { + [borderColor release]; + borderColor = [aColor copyWithZone:[self zone]]; + } +} + +- (NSColor *)gradientStartColor +{ + return gradientStartColor; +} + + +- (void)setGradientStartColor:(NSColor *)newGradientStartColor +{ + // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry. + + NSColor *newCalibratedGradientStartColor = [newGradientStartColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + + [newCalibratedGradientStartColor retain]; + [gradientStartColor release]; + gradientStartColor = newCalibratedGradientStartColor; + +} + + +- (NSColor *)gradientEndColor +{ + return gradientEndColor; +} + + +- (void)setGradientEndColor:(NSColor *)newGradientEndColor +{ + // Must ensure gradient colors are in NSCalibratedRGBColorSpace, or Core Image gets angry. + NSColor *newCalibratedGradientEndColor = [newGradientEndColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + + [newCalibratedGradientEndColor retain]; + [gradientEndColor release]; + gradientEndColor = newCalibratedGradientEndColor; +} + + +- (NSColor *)backgroundColor +{ + return backgroundColor; +} + + +- (void)setBackgroundColor:(NSColor *)newBackgroundColor +{ + [newBackgroundColor retain]; + [backgroundColor release]; + backgroundColor = newBackgroundColor; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect { + + // Construct rounded rect path + NSRect boxRect = [self bounds]; + NSRect bgRect = boxRect; + + int minX = NSMinX(bgRect); + int maxX = NSMaxX(bgRect); + int minY = NSMinY(bgRect); + int maxY = NSMaxY(bgRect); + + NSBezierPath *bgPath = [NSBezierPath bezierPathWithRect:rect]; + + // Draw solid color background + [backgroundColor set]; + [bgPath fill]; + + // Draw gradient background using Core Image + + // Wonder if there's a nicer way to get a CIColor from an NSColor... + CIColor* startColor = [CIColor colorWithRed:[gradientStartColor redComponent] + green:[gradientStartColor greenComponent] + blue:[gradientStartColor blueComponent] + alpha:[gradientStartColor alphaComponent]]; + CIColor* endColor = [CIColor colorWithRed:[gradientEndColor redComponent] + green:[gradientEndColor greenComponent] + blue:[gradientEndColor blueComponent] + alpha:[gradientEndColor alphaComponent]]; + + CIFilter *myFilter = [CIFilter filterWithName:@"CILinearGradient"]; + [myFilter setDefaults]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(minY)] + forKey:@"inputPoint0"]; + [myFilter setValue:[CIVector vectorWithX:(minX) + Y:(maxY)] + forKey:@"inputPoint1"]; + [myFilter setValue:startColor + forKey:@"inputColor0"]; + [myFilter setValue:endColor + forKey:@"inputColor1"]; + CIImage *theImage = [myFilter valueForKey:@"outputImage"]; + + + // Get a CIContext from the NSGraphicsContext, and use it to draw the CIImage + CGRect dest = CGRectMake(minX, minY, maxX - minX, maxY - minY); + + CGPoint pt = CGPointMake(bgRect.origin.x, bgRect.origin.y); + + NSGraphicsContext *nsContext = [NSGraphicsContext currentContext]; + [nsContext saveGraphicsState]; + + [bgPath addClip]; + + [[nsContext CIContext] drawImage:theImage + atPoint:pt + fromRect:dest]; + + [nsContext restoreGraphicsState]; + + if ( [self bordered] ) { + + NSPoint topLeft, topRight, bottomRight, bottomLeft; + + topLeft = NSMakePoint(0.5, boxRect.size.height-0.5); + topRight = NSMakePoint(boxRect.size.width, boxRect.size.height-0.5); + + bottomRight = NSMakePoint(boxRect.size.width-0.5, 0.5); + bottomLeft = NSMakePoint(0.5, 0.5); + + // does this actually work? + float scaleFactor = [[NSScreen mainScreen] userSpaceScaleFactor]; + if ( scaleFactor != 1.0 ) { + + // apply the scale factor + topLeft.x *= scaleFactor; + topLeft.y *= scaleFactor; + + topRight.x *= scaleFactor; + topRight.y *= scaleFactor; + + bottomRight.x *= scaleFactor; + bottomRight.y *= scaleFactor; + + bottomLeft.x *= scaleFactor; + bottomLeft.y *= scaleFactor; + + // adjust the points to integral boundaries + topLeft.x = ceil(topLeft.x); + topLeft.y = ceil(topLeft.y); + + topRight.x = ceil(topRight.x); + topRight.y = ceil(topRight.y); + + bottomRight.x = ceil(bottomRight.x); + bottomRight.y = ceil(bottomRight.y); + + bottomLeft.x = ceil(bottomLeft.x); + bottomLeft.y = ceil(bottomLeft.y); + + // convert back to user space + topLeft.x /= scaleFactor; + topLeft.y /= scaleFactor; + + topRight.x /= scaleFactor; + topRight.y /= scaleFactor; + + bottomRight.x /= scaleFactor; + bottomRight.y /= scaleFactor; + + bottomLeft.x /= scaleFactor; + bottomLeft.y /= scaleFactor; + } + + // + //draws an outline around the guy, just like with other views + NSBezierPath *borderPath = [NSBezierPath bezierPath]; + if ( borders[0] ) { + [borderPath moveToPoint:topLeft]; + [borderPath lineToPoint:topRight]; + } + if ( borders[1] ) { + [borderPath moveToPoint:topRight]; + [borderPath lineToPoint:bottomRight]; + } + if ( borders[2] ) { + [borderPath moveToPoint:bottomRight]; + [borderPath lineToPoint:bottomLeft]; + } + if ( borders[3] ) { + [borderPath moveToPoint:bottomLeft]; + [borderPath lineToPoint:topLeft]; + } + + [[self borderColor] set ]; + + [nsContext saveGraphicsState]; + [nsContext setShouldAntialias:NO]; + + [borderPath setLineWidth:1.0]; + [borderPath stroke]; + + [nsContext restoreGraphicsState]; + } +} + +@end diff --git a/PDHorizontallyCenteredText.h b/PDHorizontallyCenteredText.h new file mode 100644 index 0000000..50f91e9 --- /dev/null +++ b/PDHorizontallyCenteredText.h @@ -0,0 +1,25 @@ +// +// PDHorizontallyCenteredText.h +// SproutedInterface +// +// Created by Philip Dow on 6/19/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDHorizontallyCenteredText : NSTextFieldCell { + + BOOL selected; + BOOL boldsWhenSelected; +} + +- (BOOL) isSelected; +- (void) setSelected:(BOOL)isSelected; + +- (BOOL) boldsWhenSelected; +- (void) setBoldsWhenSelected:(BOOL)doesBold; + +@end diff --git a/PDHorizontallyCenteredText.m b/PDHorizontallyCenteredText.m new file mode 100644 index 0000000..3872ad6 --- /dev/null +++ b/PDHorizontallyCenteredText.m @@ -0,0 +1,97 @@ +// +// PDHorizontallyCenteredText.m +// SproutedInterface +// +// Created by Philip Dow on 6/19/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDHorizontallyCenteredText + +- (BOOL) isSelected +{ + return selected; +} + +- (void) setSelected:(BOOL)isSelected +{ + selected = isSelected; +} + +- (BOOL) boldsWhenSelected +{ + return boldsWhenSelected; +} + +- (void) setBoldsWhenSelected:(BOOL)doesBold +{ + boldsWhenSelected = doesBold; +} + +#pragma mark - + +- (NSColor*) textColor { + + //if ( [self isHighlighted] && ([[[self controlView] window] firstResponder] == [self controlView]) && + // [[[self controlView] window] isMainWindow] && [[[self controlView] window] isKeyWindow] ) + // return [NSColor whiteColor]; + if ( [self isHighlighted] && [[[self controlView] window] firstResponder] == [self controlView] ) + { + if ( [[[self controlView] window] isKindOfClass:[NSPanel class]] && [[[self controlView] window] isKeyWindow] ) + return [NSColor whiteColor]; + + else if ( [[[self controlView] window] isMainWindow] && [[[self controlView] window] isKeyWindow] ) + return [NSColor whiteColor]; + + else + return [super textColor]; + } + + else if ( [self isHighlighted] && [(NSTableView*)[self controlView] editedRow] != -1 && [(NSTableView*)[self controlView] editedColumn] != -1 ) + return [NSColor whiteColor]; + else + return [super textColor]; + +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + NSMutableAttributedString *attrString = [[[self attributedStringValue] mutableCopyWithZone:[self zone]] autorelease]; + [attrString addAttribute:NSParagraphStyleAttributeName value: + [NSParagraphStyle defaultParagraphStyleWithLineBreakMode:NSLineBreakByTruncatingTail] + range:NSMakeRange(0,[attrString length])]; + + NSSize stringSize = [attrString size]; + cellFrame.origin.y += ( cellFrame.size.height/2 - stringSize.height/2 ); + + if ([self isSelected]) + { + // prepare the text in white. + [attrString addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0,[attrString length])]; + + // bold the text if that option has been requested + if ( [attrString length] > 0 && [self boldsWhenSelected] ) + { + NSFont *originalFont = [attrString attribute:NSFontAttributeName atIndex:0 effectiveRange:nil]; + if ( originalFont ) { + NSFont *boldedFont = [[NSFontManager sharedFontManager] convertFont:originalFont toHaveTrait:NSBoldFontMask]; + if ( boldedFont ) + [attrString addAttribute:NSFontAttributeName value:boldedFont range:NSMakeRange(0,[attrString length])]; + } + } + } + + [attrString drawInRect:cellFrame]; + //[super drawInteriorWithFrame:cellFrame inView:controlView]; +} + +- (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + return nil; +} + +@end diff --git a/PDInvisibleButton.h b/PDInvisibleButton.h new file mode 100644 index 0000000..c64a9d4 --- /dev/null +++ b/PDInvisibleButton.h @@ -0,0 +1,17 @@ +// +// PDInvisibleButton.h +// SproutedInterface +// +// Created by Philip Dow on 1/9/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDInvisibleButton : NSButton { + +} + +@end diff --git a/PDInvisibleButton.m b/PDInvisibleButton.m new file mode 100644 index 0000000..5298b45 --- /dev/null +++ b/PDInvisibleButton.m @@ -0,0 +1,45 @@ +// +// PDInvisibleButton.m +// SproutedInterface +// +// Created by Philip Dow on 1/9/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +// +// USE: hidden escape button to, say, close a window? + +@implementation PDInvisibleButton + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDInvisibleButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDInvisibleButtonCell class]; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + // don't do a damn thing + return; +} + +@end diff --git a/PDInvisibleButtonCell.h b/PDInvisibleButtonCell.h new file mode 100644 index 0000000..1b6f1db --- /dev/null +++ b/PDInvisibleButtonCell.h @@ -0,0 +1,17 @@ +// +// PDInvisibleButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 1/9/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDInvisibleButtonCell : NSButtonCell { + +} + +@end diff --git a/PDInvisibleButtonCell.m b/PDInvisibleButtonCell.m new file mode 100644 index 0000000..2487839 --- /dev/null +++ b/PDInvisibleButtonCell.m @@ -0,0 +1,63 @@ +// +// PDInvisibleButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 1/9/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDInvisibleButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // perform no drawing + return; +} + +@end diff --git a/PDMatrixButton.h b/PDMatrixButton.h new file mode 100644 index 0000000..31675a4 --- /dev/null +++ b/PDMatrixButton.h @@ -0,0 +1,18 @@ +// +// PDButton.h +// SproutedInterface +// +// Created by Philip Dow on 12/4/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDMatrixButtonCell; + +@interface PDMatrixButton : NSButton { + +} + +@end diff --git a/PDMatrixButton.m b/PDMatrixButton.m new file mode 100644 index 0000000..4cc4bd7 --- /dev/null +++ b/PDMatrixButton.m @@ -0,0 +1,36 @@ +// +// PDMatrixButton.m +// SproutedInterface +// +// Created by Philip Dow on 5/10/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDMatrixButton + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDMatrixButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDMatrixButtonCell class]; +} + +@end diff --git a/PDMatrixButtonCell.h b/PDMatrixButtonCell.h new file mode 100644 index 0000000..7929027 --- /dev/null +++ b/PDMatrixButtonCell.h @@ -0,0 +1,16 @@ +// +// PDMatrixButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 5/10/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDMatrixButtonCell : NSButtonCell { + +} + +@end diff --git a/PDMatrixButtonCell.m b/PDMatrixButtonCell.m new file mode 100644 index 0000000..1ab9274 --- /dev/null +++ b/PDMatrixButtonCell.m @@ -0,0 +1,186 @@ +// +// PDMatrixButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 5/10/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +@implementation PDMatrixButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (id)initImageCell:(NSImage *)anImage { + + if ( self = [super initImageCell:anImage] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + + + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + int x = cellFrame.origin.x; + int y = cellFrame.origin.y; + + int height = cellFrame.size.height; + + if ( [self isHighlighted] || [self state] == NSOnState ) { + + if ( [self isHighlighted] ) { + + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else if ( [self state] == NSOnState ) { + + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + NSRect targetRect = NSInsetRect(cellFrame,0.5,2.5); + targetRect.size.width-=4.0; + + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] stroke]; + + } + + static int kImageOffset = 2; + + NSImage *image; + + if ( [self isHighlighted] ) { + + NSImage *original = [self image]; + NSImage *dark = [[NSImage alloc] initWithSize:NSMakeSize([original size].width,[original size].height)]; + + [dark lockFocus]; + [[NSColor blackColor] set]; + NSRectFillUsingOperation(NSMakeRect(0,0,[original size].width,[original size].height), NSCompositeSourceOver); + [dark unlockFocus]; + + //image = [[original copyWithZone:[self zone]] autorelease]; + image = [[NSImage alloc] initWithSize:NSMakeSize([original size].width,[original size].height)]; + [image setFlipped:[[self controlView] isFlipped]]; + + [image lockFocus]; + [original drawInRect:NSMakeRect(0,0,[original size].width,[original size].height) + fromRect:NSMakeRect(0,0,[original size].width,[original size].height) + operation:NSCompositeSourceOver fraction:1.0]; + [dark drawInRect:NSMakeRect(0,0,[original size].width,[original size].height) + fromRect:NSMakeRect(0,0,[original size].width,[original size].height) + operation:NSCompositePlusDarker fraction:0.20]; + [original drawInRect:NSMakeRect(0,0,[original size].width,[original size].height) + fromRect:NSMakeRect(0,0,[original size].width,[original size].height) + operation:NSCompositeDestinationIn fraction:1.0]; + [image unlockFocus]; + + [dark release]; + + } + else { + // + // pass it along + image = [[self image] copyWithZone:[self zone]]; + [image setFlipped:[[self controlView] isFlipped]]; + } + + NSSize imageSize = [image size]; + NSRect imageTarget = NSMakeRect(x + kImageOffset, y + height/2-imageSize.height/2, imageSize.width, imageSize.height); + + [image drawInRect:imageTarget fromRect:NSMakeRect(0,0,imageSize.width,imageSize.height) + operation:NSCompositeSourceOver fraction:1.0]; + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11.0], NSFontAttributeName, + ( [self isEnabled] ? [NSColor blackColor] : [NSColor lightGrayColor] ), NSForegroundColorAttributeName, nil]; + + NSSize stringSize = [[self title] sizeWithAttributes:attributes]; + + NSRect stringRect = NSMakeRect( x + kImageOffset*2 + imageSize.width, y + height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + [[self title] drawInRect:stringRect withAttributes:attributes]; + + [image release]; + +} + + +@end diff --git a/PDMediaBar.h b/PDMediaBar.h new file mode 100644 index 0000000..cd06da9 --- /dev/null +++ b/PDMediaBar.h @@ -0,0 +1,95 @@ +// +// PDMediaBar.h +// SproutedInterface +// +// Created by Philip Dow on 2/21/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +typedef enum { + kMediaBarDefaultItem = 100, + kMediaBarShowInFinder = 101, + kMediaBarOpenWithFinder = 102, + kMediaBarGetInfo = 103 +} MediaBarDefaultActions; + + +@class PDMediabarItem; + +@interface PDMediaBar : JournlerGradientView { + + id delegate; + + NSString *prefsIdentifier; + NSDictionary *barDictionary; + NSArray *itemIdentifiers; + NSArray *customItemDictionaries; + + NSArray *itemArray; +} + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +// the following accessors should not be called - think of them as private + +- (NSString*)prefsIdentifier; +- (void) setPrefsIdentifier:(NSString*)aString; + +- (NSDictionary*)barDictionary; +- (void) setBarDictionary:(NSDictionary*)aDictionary; + +- (NSArray*)itemIdentifiers; +- (void) setItemIdentifiers:(NSArray*)anArray; + +- (NSArray*)customItemDictionaries; +- (void) setCustomItemDictionaries:(NSArray*)anArray; + +- (NSArray*) itemArray; +- (void) setItemArray:(NSArray*)anArray; + +- (void) loadItems; +- (void) displayItems; + +- (IBAction) addCustomMediabarItem:(id)sender; +- (IBAction) editCustomMediabarItem:(id)sender; +- (IBAction) removeCustomMediabarItem:(id)sender; + +- (void) _removeCustomMediabarItem:(PDMediabarItem*)anItem; +- (void) _editCustomMediabarItem:(PDMediabarItem*)anItem; + +- (void) _didChangeFrame:(NSNotification*)aNotification; + +@end + +@interface NSObject (PDMediaBarDelegate) + +// +// for now the media bar only allows buttons +// it begins from the right with the first item returned by preferences + +- (void) setupMediabar:(PDMediaBar*)aMediabar url:(NSURL*)aURL; + +- (NSImage*) defaultOpenWithFinderImage:(PDMediaBar*)aMediabar; +- (float) mediabarMinimumWidthForUnmanagedControls:(PDMediaBar*)aMediabar; + +- (BOOL) canCustomizeMediabar:(PDMediaBar*)aMediabar; +- (NSString*) mediabarIdentifier:(PDMediaBar*)aMediabar; + +// the action method for user-defined mediabar items. +// to find out which mediabar the item is associated with, call -mediabar on it +- (IBAction) perfomCustomMediabarItemAction:(PDMediabarItem*)anItem; + +// subclasses may override when offering their own default items, +// call super to get support for any standard items you also include +- (PDMediabarItem*) mediabar:(PDMediaBar *)mediabar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoMediabar:(BOOL)flag; + +// subclasses should override to provide the default item identifiers +// listing is displayed from the right to the left in the media bar +- (NSArray*) mediabarDefaultItemIdentifiers:(PDMediaBar *)mediabar; + +@end diff --git a/PDMediaBar.m b/PDMediaBar.m new file mode 100644 index 0000000..0a6d7a3 --- /dev/null +++ b/PDMediaBar.m @@ -0,0 +1,591 @@ +// +// PDMediaBar.m +// SproutedInterface +// +// Created by Philip Dow on 2/21/07. +// Copyright Sprouted. All rights reserved. +// + +#import +#import +#import + +@implementation PDMediaBar + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + + [self setPostsFrameChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_didChangeFrame:) name:NSViewFrameDidChangeNotification object:self]; + } + return self; +} + +- (void) dealloc +{ + [prefsIdentifier release]; + [barDictionary release]; + [itemIdentifiers release]; + [customItemDictionaries release]; + [itemArray release]; + + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewFrameDidChangeNotification object:self]; + + [super dealloc]; +} + +- (void)drawRect:(NSRect)rect { + // Drawing code here. + + [super drawRect:rect]; +} + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +#pragma mark - + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + if ( ![[self delegate] canCustomizeMediabar:self] ) + return nil; + + float xMargin = [self bounds].size.width; + float barHeight = [self bounds].size.height; + + NSPoint local_point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + PDMediabarItem *anItem, *representedItem = nil; + NSEnumerator* enumerator = [itemArray objectEnumerator]; + + while ( anItem = [enumerator nextObject] ) + { + xMargin -= 4; + xMargin -= [anItem frame].size.width; + + NSRect itemFrame = NSMakeRect( xMargin, barHeight/2 - [anItem frame].size.height/2, + [anItem frame].size.width, [anItem frame].size.height); + + if ( [self mouse:local_point inRect:itemFrame] ) + { + representedItem = anItem; + break; + } + } + + NSBundle *myBundle = [NSBundle bundleWithIdentifier:@"com.sprouted.interface"]; + + NSMenu *contextMenu = [[[NSMenu alloc] initWithTitle:[NSString string]] autorelease]; + + NSMenuItem *addItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"add item title", @"Mediabar", myBundle, @"") + action:@selector(addCustomMediabarItem:) keyEquivalent:[NSString string]] autorelease]; + + [addItem setTarget:self]; + [addItem setRepresentedObject:representedItem]; + + [contextMenu addItem:addItem]; + + NSMenuItem *editItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"edit item title", @"Mediabar", myBundle, @"") + action:@selector(editCustomMediabarItem:) keyEquivalent:[NSString string]] autorelease]; + + [editItem setTarget:self]; + [editItem setRepresentedObject:representedItem]; + + [contextMenu addItem:editItem]; + + NSMenuItem *removeItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedStringFromTableInBundle(@"remove item title", @"Mediabar", myBundle, @"") + action:@selector(removeCustomMediabarItem:) keyEquivalent:[NSString string]] autorelease]; + + [removeItem setTarget:self]; + [removeItem setRepresentedObject:representedItem]; + + [contextMenu addItem:removeItem]; + + return contextMenu; + +} + +#pragma mark - + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +#pragma mark - + +- (NSString*)prefsIdentifier +{ + return prefsIdentifier; +} + +- (void) setPrefsIdentifier:(NSString*)aString +{ + if ( prefsIdentifier != aString ) + { + [prefsIdentifier release]; + prefsIdentifier = [aString copyWithZone:[self zone]]; + } +} + +- (NSDictionary*)barDictionary +{ + return barDictionary; +} + +- (void) setBarDictionary:(NSDictionary*)aDictionary +{ + if ( barDictionary != aDictionary ) + { + [barDictionary release]; + barDictionary = [aDictionary copyWithZone:[self zone]]; + } +} + +- (NSArray*)itemIdentifiers +{ + return itemIdentifiers; +} + +- (void) setItemIdentifiers:(NSArray*)anArray +{ + if ( itemIdentifiers != anArray ) + { + [itemIdentifiers release]; + itemIdentifiers = [anArray copyWithZone:[self zone]]; + } +} + +- (NSArray*)customItemDictionaries +{ + return customItemDictionaries; +} + +- (void) setCustomItemDictionaries:(NSArray*)anArray +{ + if ( customItemDictionaries != anArray ) + { + [customItemDictionaries release]; + customItemDictionaries = [anArray copyWithZone:[self zone]]; + } +} + +- (NSArray*) itemArray +{ + return itemArray; +} + +- (void) setItemArray:(NSArray*)anArray +{ + if ( itemArray != anArray ) + { + [itemArray release]; + itemArray = [anArray copyWithZone:[self zone]]; + } +} + +#pragma mark - + +- (void) loadItems +{ + if ( ![[self delegate] canCustomizeMediabar:self] ) + return; + + // clear out the old items first + NSView *aView; + NSEnumerator *enumerator = [[self itemArray] objectEnumerator]; + + while ( aView = [enumerator nextObject] ) + [aView removeFromSuperview]; + + // load in the new ones + NSMutableArray *myItems = [NSMutableArray array]; + + // build the bar from our defaults and from preferences + NSString *myPrefsIdentifier = [NSString stringWithFormat:@"PDMediaBar Configuration %@", [[self delegate] mediabarIdentifier:self]]; + NSDictionary *myBarDictionary = [[NSUserDefaults standardUserDefaults] dictionaryForKey:myPrefsIdentifier]; + + NSArray *myItemIdentifiers = nil; + NSArray *myCustomItemDictionaries = nil; + + if ( myBarDictionary == nil || ( myItemIdentifiers = [myBarDictionary objectForKey:@"ItemIdentifiers"] ) == nil ) + { + myItemIdentifiers = [[self delegate] mediabarDefaultItemIdentifiers:self]; + myBarDictionary = [NSDictionary dictionaryWithObject:myItemIdentifiers forKey:@"ItemIdentifiers"]; + [[NSUserDefaults standardUserDefaults] setObject:myBarDictionary forKey:myPrefsIdentifier]; + } + else + myCustomItemDictionaries = [myBarDictionary objectForKey:@"CustomItemDictionaries"]; + + [self setPrefsIdentifier:myPrefsIdentifier]; + [self setBarDictionary:myBarDictionary]; + [self setItemIdentifiers:myItemIdentifiers]; + [self setCustomItemDictionaries:myCustomItemDictionaries]; + + NSString *anIdentifier; + enumerator = [itemIdentifiers objectEnumerator]; + + while ( anIdentifier = [enumerator nextObject] ) + { + PDMediabarItem *anItem = [[self delegate] mediabar:self itemForItemIdentifier:anIdentifier willBeInsertedIntoMediabar:YES]; + if ( anItem != nil ) + { + [anItem setMediabar:self]; + [myItems addObject:anItem]; + } + else + { + // try building a custom item from it + if ( customItemDictionaries == nil ) + { + NSLog(@"%@ %s - no custom properties in prefs, unabe to build a custom item for media bar %@, item identifier %@", + [[self delegate] className], _cmd, [[self delegate] mediabarIdentifier:self], anIdentifier ); + continue; + } + + // find the item in our customs list + NSDictionary *aDictionary; + NSEnumerator *dictionariesEnumerator = [customItemDictionaries objectEnumerator]; + + while ( aDictionary = [dictionariesEnumerator nextObject] ) + { + if ( [anIdentifier isEqualToString:[aDictionary objectForKey:@"identifier"]] ) + { + anItem = [[[PDMediabarItem alloc] initWithDictionaryRepresentation:aDictionary] autorelease]; + if ( anItem == nil ) + NSLog(@"%@ %s - unable to initalize media bar item from dictionary %@", [[self delegate] className], _cmd, aDictionary); + else + { + [anItem setTarget:[self delegate]]; + [anItem setAction:@selector(perfomCustomMediabarItemAction:)]; + + [anItem setMediabar:self]; + [myItems addObject:anItem]; + } + + break; + } + } + } + } + + [self setItemArray:myItems]; +} + +- (void) displayItems +{ + if ( ![[self delegate] canCustomizeMediabar:self] ) + return; + + /* + NSView *aView; + NSEnumerator *enumerator = [[self itemArray] objectEnumerator]; + + while ( aView = [enumerator nextObject] ) + [aView removeFromSuperview]; + */ + + float xMargin = [self bounds].size.width; + float barHeight = [self bounds].size.height; + float minWidth = [[self delegate] mediabarMinimumWidthForUnmanagedControls:self]; + + PDMediabarItem *anItem; + NSEnumerator *enumerator = [itemArray objectEnumerator]; + + while ( anItem = [enumerator nextObject] ) + { + xMargin -= 4; + xMargin -= [anItem frame].size.width; + + NSRect itemFrame = NSMakeRect( xMargin, barHeight/2 - [anItem frame].size.height/2, + [anItem frame].size.width, [anItem frame].size.height); + [anItem setFrame:itemFrame]; + [self addSubview:anItem]; + + if ( xMargin < minWidth ) + [anItem setHidden:YES]; + else + [anItem setHidden:NO]; + } +} + +#pragma mark - + +- (IBAction) removeCustomMediabarItem:(id)sender +{ + if ( ![[self delegate] canCustomizeMediabar:self] ) + return; + + [self _removeCustomMediabarItem:[sender representedObject]]; +} + +- (IBAction) editCustomMediabarItem:(id)sender +{ + if ( ![[self delegate] canCustomizeMediabar:self] ) + return; + + [self _editCustomMediabarItem:[sender representedObject]]; +} + +#pragma mark - + +- (void) _removeCustomMediabarItem:(PDMediabarItem*)anItem +{ + // reset the preferences + NSMutableDictionary *myBarDictionary = [[[self barDictionary] mutableCopyWithZone:[self zone]] autorelease]; + if ( myBarDictionary == nil ) myBarDictionary = [NSMutableDictionary dictionary]; + + NSMutableArray *myItemIdentifiers = nil; + NSMutableArray *myCustomItemDictionaries = nil; + + if ( myBarDictionary == nil || ( myItemIdentifiers = [[[myBarDictionary objectForKey:@"ItemIdentifiers"] mutableCopyWithZone:[self zone]] autorelease] ) == nil ) + { + myItemIdentifiers = [[[[self delegate] mediabarDefaultItemIdentifiers:self] mutableCopyWithZone:[self zone]] autorelease]; + myCustomItemDictionaries = [NSMutableArray array]; + + myBarDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys: + myItemIdentifiers, @"ItemIdentifiers", + myCustomItemDictionaries, @"CustomItemDictionaries", nil]; + } + else + { + myCustomItemDictionaries = [[[myBarDictionary objectForKey:@"CustomItemDictionaries"] mutableCopyWithZone:[self zone]] autorelease]; + if ( myCustomItemDictionaries == nil ) + myCustomItemDictionaries = [NSMutableArray array]; + } + + int itemIdentifierIndex = [myItemIdentifiers indexOfObject:[anItem identifier]]; + if ( itemIdentifierIndex != NSNotFound ) + [myItemIdentifiers removeObjectAtIndex:itemIdentifierIndex]; + else + NSLog(@"%@ %s - unable to remove item with identifier %@", [self className], _cmd, [anItem identifier]); + + int dictionaryIndex = [[myCustomItemDictionaries valueForKey:@"identifier"] indexOfObject:[anItem identifier]]; + if ( dictionaryIndex != NSNotFound ) + [myCustomItemDictionaries removeObjectAtIndex:dictionaryIndex]; + else + NSLog(@"%@ %s - unable to remove item with identifier %@", [self className], _cmd, [anItem identifier]); + + // reset the items in the dictinoary + [myBarDictionary setObject:myItemIdentifiers forKey:@"ItemIdentifiers"]; + [myBarDictionary setObject:myCustomItemDictionaries forKey:@"CustomItemDictionaries"]; + + // reset the preferences + [[NSUserDefaults standardUserDefaults] setObject:myBarDictionary forKey:prefsIdentifier]; + + // reset our local representation + [self setCustomItemDictionaries:myCustomItemDictionaries]; + [self setItemIdentifiers:myItemIdentifiers]; + [self setBarDictionary:myBarDictionary]; + + // remove the item from the display + [anItem removeFromSuperview]; + + // rebuild the bar + [self loadItems]; + [self displayItems]; + + [self setNeedsDisplay:YES]; +} + +- (void) _editCustomMediabarItem:(PDMediabarItem*)anItem +{ + NewMediabarItemController *itemCreator = [[[NewMediabarItemController alloc] + initWithDictionaryRepresentation:[anItem dictionaryRepresentation]] autorelease]; + + [itemCreator setDelegate:self]; + [itemCreator setRepresentedObject:anItem]; + [itemCreator runAsSheetForWindow:[self window] attached:NO location:NSMakeRect(0,0,0,0)]; +} + +#pragma mark - + +- (IBAction) addCustomMediabarItem:(id)sender +{ + // subclasses may override to provide custom behavior + if ( [[self delegate] canCustomizeMediabar:self] ) + { + NewMediabarItemController *itemCreator = [[[NewMediabarItemController alloc] init] autorelease]; + + [itemCreator setDelegate:self]; + [itemCreator runAsSheetForWindow:[self window] attached:NO location:NSMakeRect(0,0,0,0)]; + } + + else + { + NSBeep(); + } +} + +- (void) mediabarItemCreateDidSaveAction:(NewMediabarItemController*)mediabarItemCreator +{ + PDMediabarItem *theRepresentedObject = [mediabarItemCreator representedObject]; + + // create a new item if no item is being edited + if ( theRepresentedObject == nil ) + { + + // the delegate method from the media bar item creator - subclasses may override if they wish + NSDictionary *dictionaryRepresentation = [mediabarItemCreator dictionaryRepresentation]; + + // reset the preferences + NSMutableDictionary *myBarDictionary = [[[self barDictionary] mutableCopyWithZone:[self zone]] autorelease]; + if ( myBarDictionary == nil ) myBarDictionary = [NSMutableDictionary dictionary]; + + NSMutableArray *myItemIdentifiers = nil; + NSMutableArray *myCustomItemDictionaries = nil; + + if ( myBarDictionary == nil || ( myItemIdentifiers = [[[myBarDictionary objectForKey:@"ItemIdentifiers"] mutableCopyWithZone:[self zone]] autorelease] ) == nil ) + { + myItemIdentifiers = [[[[self delegate] mediabarDefaultItemIdentifiers:self] mutableCopyWithZone:[self zone]] autorelease]; + myCustomItemDictionaries = [NSMutableArray array]; + + myBarDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys: + myItemIdentifiers, @"ItemIdentifiers", + myCustomItemDictionaries, @"CustomItemDictionaries", nil]; + } + else + { + myCustomItemDictionaries = [[[myBarDictionary objectForKey:@"CustomItemDictionaries"] mutableCopyWithZone:[self zone]] autorelease]; + if ( myCustomItemDictionaries == nil ) + myCustomItemDictionaries = [NSMutableArray array]; + } + + [myItemIdentifiers addObject:[dictionaryRepresentation objectForKey:@"identifier"]]; + [myCustomItemDictionaries addObject:dictionaryRepresentation]; + + [myBarDictionary setObject:myItemIdentifiers forKey:@"ItemIdentifiers"]; + [myBarDictionary setObject:myCustomItemDictionaries forKey:@"CustomItemDictionaries"]; + + [[NSUserDefaults standardUserDefaults] setObject:myBarDictionary forKey:prefsIdentifier]; + + [self setCustomItemDictionaries:myCustomItemDictionaries]; + [self setItemIdentifiers:myItemIdentifiers]; + [self setBarDictionary:myBarDictionary]; + + // rebuild the bar + [self loadItems]; + [self displayItems]; + + } + + // modify the represented item if one was being edited + else + { + // the delegate method from the media bar item creator - subclasses may override if they wish + + NSDictionary *dictionaryRepresentation = [mediabarItemCreator dictionaryRepresentation]; + + // save the preferences + NSMutableDictionary *myBarDictionary = [[[self barDictionary] mutableCopyWithZone:[self zone]] autorelease]; + if ( myBarDictionary == nil ) myBarDictionary = [NSMutableDictionary dictionary]; + + NSMutableArray *myItemIdentifiers = nil; + NSMutableArray *myCustomItemDictionaries = nil; + + if ( myBarDictionary == nil || ( myItemIdentifiers = [[[myBarDictionary objectForKey:@"ItemIdentifiers"] mutableCopyWithZone:[self zone]] autorelease] ) == nil ) + { + myItemIdentifiers = [[[[self delegate] mediabarDefaultItemIdentifiers:self] mutableCopyWithZone:[self zone]] autorelease]; + myCustomItemDictionaries = [NSMutableArray array]; + + myBarDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys: + myItemIdentifiers, @"ItemIdentifiers", + myCustomItemDictionaries, @"CustomItemDictionaries", nil]; + } + else + { + myCustomItemDictionaries = [[[myBarDictionary objectForKey:@"CustomItemDictionaries"] mutableCopyWithZone:[self zone]] autorelease]; + if ( myCustomItemDictionaries == nil ) + myCustomItemDictionaries = [NSMutableArray array]; + } + + /* + int itemIdentifierIndex = [myItemIdentifiers indexOfObject:[theRepresentedObject identifier]]; + if ( itemIdentifierIndex != NSNotFound ) + [myItemIdentifiers removeObjectAtIndex:itemIdentifierIndex]; + else + NSLog(@"%@ %s - unable to remove item with identifier %@", [self className], _cmd, [theRepresentedObject identifier]); + */ + + int dictionaryIndex = [[myCustomItemDictionaries valueForKey:@"identifier"] indexOfObject:[theRepresentedObject identifier]]; + if ( dictionaryIndex != NSNotFound ) + [myCustomItemDictionaries replaceObjectAtIndex:dictionaryIndex withObject:dictionaryRepresentation]; + else + NSLog(@"%@ %s - unable to edit item with identifier %@", [self className], _cmd, [theRepresentedObject identifier]); + + // reset the items in the dictinoary + [myBarDictionary setObject:myItemIdentifiers forKey:@"ItemIdentifiers"]; + [myBarDictionary setObject:myCustomItemDictionaries forKey:@"CustomItemDictionaries"]; + + // reset the preferences + [[NSUserDefaults standardUserDefaults] setObject:myBarDictionary forKey:prefsIdentifier]; + + // reset our local representation + [self setCustomItemDictionaries:myCustomItemDictionaries]; + [self setItemIdentifiers:myItemIdentifiers]; + [self setBarDictionary:myBarDictionary]; + + // re-attribute the item + [theRepresentedObject setAttributesFromDictionaryRepresentation:dictionaryRepresentation]; + + } + + [self setNeedsDisplay:YES]; +} + +#pragma mark - + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + BOOL enabled = YES; + SEL action = [menuItem action]; + + if ( ![[self delegate] canCustomizeMediabar:self] ) + return NO; + + + if ( action == @selector(addCustomMediabarItem:) ) + enabled = YES; + + else if ( action == @selector(editCustomMediabarItem:) ) + enabled = ( [[menuItem representedObject] isKindOfClass:[PDMediabarItem class]] && ( [[[menuItem representedObject] typeIdentifier] intValue] != kMenubarItemDefault ) ); + + else if ( action == @selector(removeCustomMediabarItem:) ) + enabled = ( [[menuItem representedObject] isKindOfClass:[PDMediabarItem class]] && ( [[[menuItem representedObject] typeIdentifier] intValue] != kMenubarItemDefault ) ); + + return enabled; +} + +#pragma mark - + +- (void) _didChangeFrame:(NSNotification*)aNotification +{ + float minWidth = [[self delegate] mediabarMinimumWidthForUnmanagedControls:self]; + float xMargin = [self bounds].size.width; + + PDMediabarItem *anItem; + NSEnumerator *enumerator = [itemArray objectEnumerator]; + + while ( anItem = [enumerator nextObject] ) + { + xMargin -= 4; + xMargin -= [anItem frame].size.width; + + if ( xMargin < minWidth ) + [anItem setHidden:YES]; + else + [anItem setHidden:NO]; + } +} + +@end diff --git a/PDMediabarItem.h b/PDMediabarItem.h new file mode 100644 index 0000000..ca2be9b --- /dev/null +++ b/PDMediabarItem.h @@ -0,0 +1,59 @@ +// +// PDMediabarItem.h +// SproutedInterface +// +// Created by Philip Dow on 2/20/07. +// Copyright Sprouted. All rights reserved. +// + +#import + +typedef enum { + kMenubarItemDefault = 0, + kMenubarItemURI = 1, + kMenubarItemAppleScript = 2, +} MenubarItemType; + +@class PDMediaBar; + +@interface PDMediabarItem : NSButton { + + NSString *identifier; + NSNumber *typeIdentifier; + + NSURL *targetURI; + NSAttributedString *targetScript; + + PDMediaBar *mediabar; +} + +- (id) initWithItemIdentifier:(NSString*)aString; +- (id) initWithDictionaryRepresentation:(NSDictionary*)aDictionary; + +- (NSDictionary*) dictionaryRepresentation; +- (void) setAttributesFromDictionaryRepresentation:(NSDictionary*)aDictionary; + +- (NSString*)identifier; +- (void) setIdentifier:(NSString*)aString; + +- (NSSize) size; +- (void) setSize:(NSSize)aSize; + +- (PDMediaBar*) mediabar; +- (void) setMediabar:(PDMediaBar*)aMediabar; + +// a custom button should target the media controller itself +// a special function that grabs the target information and takes the appropriate action +// a default method will handle this, but it may be overridden + +- (NSNumber*) typeIdentifier; +- (void) setTypeIdentifier:(NSNumber*)aNumber; + +- (NSURL*) targetURI; +- (void) setTargetURI:(NSURL*)aURL; + +- (NSAttributedString*) targetScript; +- (void) setTargetScript:(NSAttributedString*)aString; + + +@end diff --git a/PDMediabarItem.m b/PDMediabarItem.m new file mode 100644 index 0000000..91e8b9f --- /dev/null +++ b/PDMediabarItem.m @@ -0,0 +1,229 @@ +// +// PDMediabarItem.m +// SproutedInterface +// +// Created by Philip Dow on 2/20/07. +// Copyright Sprouted. All rights reserved. +// + +#import +#import + +@implementation PDMediabarItem + +- (id) initWithItemIdentifier:(NSString*)aString +{ + if ( self = [self init] ) + { + [self setIdentifier:aString]; + } + + return self; +} + +- (id) initWithDictionaryRepresentation:(NSDictionary*)aDictionary +{ + if ( self = [self init] ) + { + [self setIdentifier:[aDictionary objectForKey:@"identifier"]]; + [self setTypeIdentifier:[aDictionary objectForKey:@"typeIdentifier"]]; + + NSData *scriptData = [aDictionary objectForKey:@"targetScript"]; + if ( scriptData != nil ) [self setTargetScript:[NSKeyedUnarchiver unarchiveObjectWithData:scriptData]]; + + NSData *imageData = [aDictionary objectForKey:@"image"]; + if ( imageData != nil ) [self setImage:[NSKeyedUnarchiver unarchiveObjectWithData:imageData]]; + [self setTitle:[aDictionary objectForKey:@"title"]]; + [self setToolTip:[aDictionary objectForKey:@"tooltip"]]; + + NSString *uriString = [aDictionary objectForKey:@"targetURI"]; + if ( uriString != nil ) [self setTargetURI:[NSURL URLWithString:uriString]]; + + } + + return self; +} + +- (id) init +{ + if ( self = [super initWithFrame:NSMakeRect(0,0,32,32)] ) + { + [(NSButtonCell*)[self cell] setImagePosition:NSImageOnly]; + [(NSButtonCell*)[self cell] setControlSize:NSRegularControlSize]; + [(NSButtonCell*)[self cell] setButtonType:NSMomentaryChangeButton]; + [(NSButtonCell*)[self cell] setLineBreakMode:NSLineBreakByWordWrapping]; + [(NSButtonCell*)[self cell] setBaseWritingDirection:NSWritingDirectionNatural]; + //[(NSButtonCell*)[self cell] setType:NSImageCellType]; + + [self setBordered:NO]; + [self setBezelStyle:NSRegularSquareBezelStyle]; + [(NSButtonCell*)[self cell] setBezeled:NO]; + [self setTransparent:NO]; + [self setImagePosition:NSImageOnly]; + [self setShowsBorderOnlyWhileMouseInside:NO]; + [self setAutoresizingMask:(NSViewMinXMargin)]; + [self setFont:[NSFont controlContentFontOfSize:11]]; + + + [self setAllowsMixedState:NO]; + [self setState:NSOffState]; + + [self setContinuous:NO]; + //[self sendActionOn:NSLeftMouseUpMask]; + + } + + return self; +} + +- (void) dealloc +{ + [identifier release]; + [typeIdentifier release]; + [targetURI release]; + [targetScript release]; + //[mediabar release]; + + [super dealloc]; +} + +#pragma mark - + +- (NSDictionary*) dictionaryRepresentation +{ + NSMutableDictionary *representation = [NSMutableDictionary dictionaryWithCapacity:4]; + + if ( identifier != nil ) [representation setObject:[self identifier] forKey:@"identifier"]; + if ( typeIdentifier != nil ) [representation setObject:[self typeIdentifier] forKey:@"typeIdentifier"]; + if ( targetURI != nil ) [representation setObject:[[self targetURI] absoluteString] forKey:@"targetURI"]; + if ( targetScript != nil ) [representation setObject:[NSKeyedArchiver archivedDataWithRootObject:[self targetScript]] forKey:@"targetScript"]; + + if ( [self image] != nil ) [representation setObject:[NSKeyedArchiver archivedDataWithRootObject:[self image]] forKey:@"image"]; + if ( [self title] != nil ) [representation setObject:[self title] forKey:@"title"]; + if ( [self toolTip] != nil ) [representation setObject:[self toolTip] forKey:@"tooltip"]; + + return representation; +} + +- (void) setAttributesFromDictionaryRepresentation:(NSDictionary*)aDictionary +{ + [self setIdentifier:[aDictionary objectForKey:@"identifier"]]; + [self setTypeIdentifier:[aDictionary objectForKey:@"typeIdentifier"]]; + + NSData *scriptData = [aDictionary objectForKey:@"targetScript"]; + if ( scriptData != nil ) [self setTargetScript:[NSKeyedUnarchiver unarchiveObjectWithData:scriptData]]; + + NSData *imageData = [aDictionary objectForKey:@"image"]; + if ( imageData != nil ) [self setImage:[NSKeyedUnarchiver unarchiveObjectWithData:imageData]]; + [self setTitle:[aDictionary objectForKey:@"title"]]; + [self setToolTip:[aDictionary objectForKey:@"tooltip"]]; + + NSString *uriString = [aDictionary objectForKey:@"targetURI"]; + if ( uriString != nil ) [self setTargetURI:[NSURL URLWithString:uriString]]; + +} + +#pragma mark - + +- (NSString *)identifier +{ + return identifier; +} + +- (void) setIdentifier:(NSString*)aString +{ + if ( identifier != aString ) + { + [identifier release]; + identifier = [aString copyWithZone:[self zone]]; + } +} + +- (NSSize) size +{ + return [self frame].size; +} + +- (void) setSize:(NSSize)aSize +{ + NSRect aFrame = [self frame]; + aFrame.size = aSize; + [self setFrame:aFrame]; +} + +- (PDMediaBar*) mediabar +{ + return mediabar; +} + +- (void) setMediabar:(PDMediaBar*)aMediabar +{ + if ( mediabar != aMediabar ) + { + //[mediabar release]; + //mediabar = [aMediabar retain]; + + // do not retain otherwise there is a retain loop between the mediabar and the mediabar items + mediabar = aMediabar; + } +} + +#pragma mark - + +- (NSNumber*) typeIdentifier +{ + return typeIdentifier; +} + +- (void) setTypeIdentifier:(NSNumber*)aNumber +{ + if ( typeIdentifier != aNumber ) + { + [typeIdentifier release]; + typeIdentifier = [aNumber copyWithZone:[self zone]]; + } +} + +- (NSURL*) targetURI +{ + return targetURI; +} + +- (void) setTargetURI:(NSURL*)aURL +{ + if ( targetURI != aURL ) + { + [targetURI release]; + targetURI = [aURL copyWithZone:[self zone]]; + } +} + +- (NSAttributedString*) targetScript +{ + return targetScript; +} + +- (void) setTargetScript:(NSAttributedString*)aString +{ + if ( targetScript != aString ) + { + [targetScript release]; + targetScript = [aString copyWithZone:[self zone]]; + } +} + +#pragma mark - + +- (void) setTitle:(NSString*)aString +{ + [super setTitle:aString]; + [self setImagePosition:NSImageOnly]; + //[(NSButtonCell*)[self cell] setType:NSImageCellType]; +} + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + return [[self mediabar] menuForEvent:theEvent]; +} + +@end diff --git a/PDOutlineView.h b/PDOutlineView.h new file mode 100644 index 0000000..d32f682 --- /dev/null +++ b/PDOutlineView.h @@ -0,0 +1,24 @@ +// +// PDOutlineView.h +// SproutedInterface +// +// Created by Philip Dow on 2/1/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDOutlineView : NSOutlineView { + +} + +@end + +@interface NSObject (PDOutlineViewDelegate) + +- (void) outlineView:(NSOutlineView*)anOutlineView leftNavigationEvent:(NSEvent*)anEvent; +- (void) outlineView:(NSOutlineView*)anOutlineView rightNavigationEvent:(NSEvent*)anEvent; + +@end \ No newline at end of file diff --git a/PDOutlineView.m b/PDOutlineView.m new file mode 100644 index 0000000..d2d0409 --- /dev/null +++ b/PDOutlineView.m @@ -0,0 +1,48 @@ +// +// PDOutlineView.m +// SproutedInterface +// +// Created by Philip Dow on 2/1/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDOutlineView + +- (void)keyDown:(NSEvent *)event +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning", [self className], _cmd) + #endif + + unsigned int modifierFlags = [event modifierFlags]; + unichar key = [[event charactersIgnoringModifiers] characterAtIndex:0]; + + if ( key == NSLeftArrowFunctionKey && [[self delegate] respondsToSelector:@selector(outlineView:leftNavigationEvent:)] && ( modifierFlags & NSCommandKeyMask ) ) + [[self delegate] outlineView:self leftNavigationEvent:event]; + else if ( key == NSRightArrowFunctionKey && [[self delegate] respondsToSelector:@selector(outlineView:rightNavigationEvent:)] && ( modifierFlags & NSCommandKeyMask ) ) + [[self delegate] outlineView:self rightNavigationEvent:event]; + else + { + [super keyDown:event]; + } + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending", [self className], _cmd) + #endif +} + +- (void)cancelOperation:(id)sender +{ + if ([self currentEditor] != nil) + { + [self abortEditing]; + + // We lose focus so re-establish + [[self window] makeFirstResponder:self]; + } +} + +@end diff --git a/PDPhotoView.h b/PDPhotoView.h new file mode 100644 index 0000000..c50a115 --- /dev/null +++ b/PDPhotoView.h @@ -0,0 +1,75 @@ + +// I believe I override a number of methods in MUPhotoView +// so as to use a cell with the class, MUPhotoCell. + +// +// +// MUPhotoView +// +// Copyright (c) 2006 Blake Seely +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// * You include a link to http://www.blakeseely.com in your final product. +// +// Version History: +// +// Version 1.0 - April 17, 2006 - Initial Release +// Version 1.1 - April 29, 2006 - Photo removal support, Added support for reduced-size drawing during live resize +// Version 1.2 - September 24, 2006 - Updated selection behavior, Changed to MIT license, Fixed issue where no images would show, fixed autoscroll + +#import +#import + +//#import +//#import "MUPhotoView.h" + +//! MUPhotoView displays a grid of photos similar to iPhoto's main photo view. The class gives developers several options for providing images - via bindings or delegation. + +//! MUPhotoView displays a resizeable grid of photos, similar to iPhoto's photo view functionality. MUPhotoView provides developers with two different options for passing photo information to the view +//! Most importantly, MUPhotoView currently only deals with an array of photos. It does not yet know how to display titles or any other metadata. It also does not know how to find NSImage objects +//! that are inside another object - it expects NSImage objects. The first method for providing those objects it by binding an array of NSImage objects to the "photosArray" key of the view. +//! If this key has been bound, MUPhotoView will fetch all the images it displays from that binding. The second method is to have a delegate object provide the photos. MUPhotoView will only +//! call the delegate's photo methods if the photosArray key has not been bound. Please see the MUPhotoViewDelegate category documentation for descriptions of the methods. +@interface PDPhotoView : MUPhotoView { + // Please do not access ivars directly - use the accessor methods documented below + + BOOL drawsBackground; + unsigned indexForMenuEvent; + + NSCell *cell; + NSCursor *hoverCursor; + + BOOL amPrinting; +} + +- (NSCell*) cell; +- (void) setCell:(NSCell*)aCell; + +- (NSCursor*) hoverCursor; +- (void) setHoverCursor:(NSCursor*)aCursor; + +- (unsigned) indexForMenuEvent; +- (void) setIndexForMenuEvent:(unsigned)anIndex; + +- (BOOL) drawsBackground; +- (void) setDrawsBackground:(BOOL)draws; + +- (void) ownerWillClose:(NSNotification*)aNotification; + +//- (float)calculatePrintHeight; + +@end + +@interface NSObject (MUPhotoViewMoreDelegateMethods) + +- (NSString*) photoView:(MUPhotoView*)photoView titleForObjectAtIndex:(unsigned int)index; +- (NSString*) photoView:(MUPhotoView*)photoView tooltipForObjectAtIndex:(unsigned int)index; + +@end diff --git a/PDPhotoView.m b/PDPhotoView.m new file mode 100644 index 0000000..61c3035 --- /dev/null +++ b/PDPhotoView.m @@ -0,0 +1,786 @@ + +// I believe I override a number of methods in MUPhotoView +// so as to use a cell with the class, MUPhotoCell. + +// +// MUPhotoView +// +// Copyright (c) 2006 Blake Seely +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// * You include a link to http://www.blakeseely.com in your final product. +// +// Version History: +// +// Version 1.0 - April 17, 2006 - Initial Release +// Version 1.1 - April 29, 2006 - Photo removal support, Added support for reduced-size drawing during live resize +// Version 1.2 - September 24, 2006 - Updated selection behavior, Changed to MIT license, Fixed issue where no images would show, fixed autoscroll + +#import +#import + +@implementation PDPhotoView + +#pragma mark - +// Initializers and Dealloc +#pragma mark Initializers and Dealloc + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) { + + drawsBackground = YES; + hoverCursor = nil; + amPrinting = NO; + + MUPhotoCell *defaultCell = [[[MUPhotoCell alloc] initImageCell:nil] autorelease]; + [self setCell:defaultCell]; + + } + + return self; +} + +#pragma mark - + +- (void) dealloc +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + [cell release], cell = nil; + [hoverCursor release], hoverCursor = nil; + + [super dealloc]; +} + +- (void) ownerWillClose:(NSNotification*)aNotification +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( autoscrollTimer != nil ) + { + [autoscrollTimer invalidate]; + autoscrollTimer = nil; + } + + if ( photoResizeTimer != nil ) + { + [photoResizeTimer invalidate]; + photoResizeTimer = nil; + } + +} + +#pragma mark - + +- (NSCell*) cell +{ + return cell; +} + +- (void) setCell:(NSCell*)aCell +{ + if ( cell != aCell ) + { + [cell release]; + cell = [aCell copyWithZone:[self zone]]; + } +} + +- (NSCursor*) hoverCursor +{ + return hoverCursor; +} + +- (void) setHoverCursor:(NSCursor*)aCursor +{ + if ( hoverCursor != aCursor ) + { + [hoverCursor release]; + hoverCursor = [aCursor retain]; + } +} + +- (unsigned) indexForMenuEvent +{ + return indexForMenuEvent; +} + +- (void) setIndexForMenuEvent:(unsigned)anIndex +{ + indexForMenuEvent = anIndex; +} + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + [self setIndexForMenuEvent:[self photoIndexForPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]]]; + return [super menuForEvent:theEvent]; +} + +- (BOOL) drawsBackground +{ + return drawsBackground; +} + +- (void) setDrawsBackground:(BOOL)draws +{ + drawsBackground = draws; +} + +#pragma mark - + +- (void)setSelectionIndexes:(NSIndexSet *)indexes +{ + // CHANGE: allow the delegate to modify the selection even if the selected photo index is available + + NSMutableIndexSet *oldSelection = nil; + + // Set the new selection, but save the old selection so we know exactly what to redraw + if (nil != [self selectedPhotoIndexes]) + { + oldSelection = [[self selectedPhotoIndexes] retain]; + if ( [delegate respondsToSelector:@selector(photoView:willSetSelectionIndexes:)] ) + indexes = [delegate photoView:self willSetSelectionIndexes:indexes]; + [self setSelectedPhotoIndexes:indexes]; + } + else if (nil != delegate) + { + // We have to iterate through the photos to figure out which ones the delegate thinks are selected - that's the only way to know the old selection when in delegate mode + oldSelection = [[NSMutableIndexSet alloc] init]; + int i, count = [self photoCount]; + for( i = 0; i < count; i += 1 ) + { + if ([self isPhotoSelectedAtIndex:i]) + { + [oldSelection addIndex:i]; + } + } + + // Now update the selection + indexes = [delegate photoView:self willSetSelectionIndexes:indexes]; + [delegate photoView:self didSetSelectionIndexes:indexes]; + } + + [self dirtyDisplayRectsForNewSelection:indexes oldSelection:oldSelection]; + [oldSelection release]; +} + +- (void)setPhotosArray:(NSArray *)aPhotosArray +{ + [super setPhotosArray:aPhotosArray]; + [[self window] invalidateCursorRectsForView:self]; + // call super's implementation and invalidate our cursor rects +} + +- (void)setPhotoSize:(float)aPhotoSize +{ + [super setPhotoSize:aPhotoSize]; + [[self window] invalidateCursorRectsForView:self]; + // call super's implementation and invalidate our cursor rects +} + +- (void)setPhotoVerticalSpacing:(float)aPhotoVerticalSpacing +{ + [super setPhotoVerticalSpacing:aPhotoVerticalSpacing]; + [[self window] invalidateCursorRectsForView:self]; + // call super's implementation and invalidate our cursor rects +} + +- (void)setPhotoHorizontalSpacing:(float)aPhotoHorizontalSpacing +{ + [super setPhotoHorizontalSpacing:aPhotoHorizontalSpacing]; + [[self window] invalidateCursorRectsForView:self]; + // call super's implementation and invalidate our cursor rects +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect +{ + if ( [NSGraphicsContext currentContextDrawingToScreen] ) + [self removeAllToolTips]; // djw: are these really working? + + if ( [self drawsBackground] ) + { + // draw the background color + [[self backgroundColor] set]; + [NSBezierPath fillRect:rect]; + } + + // update internal grid size, adjust height based on the new grid size + // because I may not find out that the photos array has changed until I draw and read the photos from the delegate, this call has to stay here + [self updateGridAndFrame]; + + // get the number of photos + unsigned photoCount = [self photoCount]; + if (0 == photoCount) + return; + + // any other setup + if (useHighQualityResize) { + [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; + } + + NSCell *drawingCell = [self cell]; + + /**** BEGIN Drawing Photos ****/ + NSRange rangeToDraw = [self photoIndexRangeForRect:rect]; // adjusts for photoCount if the rect goes outside my range + unsigned index; + unsigned lastIndex = rangeToDraw.location + rangeToDraw.length; + // Our version of photoIndexRangeForRect: returns one item more in the range than the MUPhotoView 1.2 version. Hence we also + // must do one less iteration so here we do < instead of <= + for (index = rangeToDraw.location; index < lastIndex; index++) { + + // Get the image at the current index - a gray bezier anywhere in the view means it asked for an image, but got nil for that index + NSImage *photo = nil; + if ([self inLiveResize]) { + photo = [self fastPhotoAtIndex:index]; + } + + if (nil == photo) { + photo = [self photoAtIndex:index]; + } + + // scale it to the appropriate size, this method should automatically set high quality if necessary + photo = [self scalePhoto:photo]; + + // get all the appropriate positioning information + NSRect gridRect = [self centerScanRect:[self gridRectForIndex:index]]; + NSSize scaledSize = [self scaledPhotoSizeForSize:[photo size]]; + NSRect photoRect = [self rectCenteredInRect:gridRect withSize:scaledSize]; + photoRect = [self centerScanRect:photoRect]; + + //**** BEGIN Background Drawing - any drawing that technically goes under the image ****/ + // kSelectionStyleShadowBox draws a semi-transparent rounded rect behind/around the image + if ([self isPhotoSelectedAtIndex:index] && [self useShadowSelection]) { + + NSBezierPath *shadowBoxPath = [self shadowBoxPathForRect:gridRect]; + [shadowBoxColor set]; + [shadowBoxPath fill]; + } + + //**** END Background Drawing ****/ + + // draw the current photo + + NSString *photoTitle = nil; + if ( [[self delegate] respondsToSelector:@selector(photoView:titleForObjectAtIndex:)] ) + photoTitle = [[self delegate] photoView:self titleForObjectAtIndex:index]; + + [drawingCell setTitle:photoTitle]; + [drawingCell setObjectValue:photo]; + + // kBorderStyleShadow - set the appropriate shadow + if ([self useShadowBorder]) { + [borderShadow set]; + } + + [drawingCell drawWithFrame:photoRect inView:self]; + + [noShadow set]; + + // register the tooltip area - photoRect + if ( [NSGraphicsContext currentContextDrawingToScreen] ) + [self addToolTipRect:photoRect owner:self userData:nil]; + + // restore the photo's flipped status + + // BEGIN Foreground Drawing - includes outline borders, selection rectangles + if ([self isPhotoSelectedAtIndex:index] && [self useBorderSelection]) { + NSBezierPath *selectionBorder = [NSBezierPath bezierPathWithRect:NSInsetRect(photoRect,-3.0,-3.0)]; + [selectionBorder setLineWidth:[self selectionBorderWidth]]; + [[self selectionBorderColor] set]; + [selectionBorder stroke]; + } else if ([self useOutlineBorder]) { + photoRect = NSInsetRect(photoRect,0.5,0.5); // line up the 1px border so it completely fills a single row of pixels + NSBezierPath *outline = [NSBezierPath bezierPathWithRect:photoRect]; + [outline setLineWidth:1.0]; + [borderOutlineColor set]; + [outline stroke]; + } + + + //**** END Foreground Drawing ****// + + + } + + //**** END Drawing Photos ****// +} + +- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData +{ + unsigned idx = [self photoIndexForPoint:point]; + if (idx < [self photoCount] && [[self delegate] respondsToSelector:@selector(photoView:tooltipForObjectAtIndex:)] ) + { + return [delegate photoView:self tooltipForObjectAtIndex:[self photoIndexForPoint:point]]; + } + return nil; +} + +- (void)resetCursorRects +{ + if ( [self hoverCursor] == nil ) + return; + + int i; + for ( i = 0; i < [[self photosArray] count]; i++ ) + [self addCursorRect:[self photoRectForIndex:i] cursor:[self hoverCursor]]; +} + +#pragma mark - + +- (void) mouseDown:(NSEvent *) event +{ + if ( [event clickCount] == 2) + { + // There could be more than one selected photo. In that case, call the delegates doubleClickOnPhotoAtIndex routine for + // each selected photo. + unsigned int selectedIndex = [[self selectionIndexes] firstIndex]; + while (selectedIndex != NSNotFound) { + [delegate photoView:self doubleClickOnPhotoAtIndex:selectedIndex withFrame:[self photoRectForIndex:selectedIndex]]; + selectedIndex = [[self selectionIndexes] indexGreaterThanIndex:selectedIndex]; + } + } + else + { + mouseDown = YES; + mouseDownPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + mouseCurrentPoint = mouseDownPoint; + + unsigned clickedIndex = [self photoIndexForPoint:mouseDownPoint]; + NSRect photoRect = [self photoRectForIndex:clickedIndex]; + unsigned int flags = [event modifierFlags]; + NSMutableIndexSet* indexes = [[self selectionIndexes] mutableCopy]; + BOOL imageHit = NSPointInRect(mouseDownPoint, photoRect); + + if (imageHit) { + if (flags & NSCommandKeyMask) { + // Flip current image selection state. + if ([indexes containsIndex:clickedIndex]) { + [indexes removeIndex:clickedIndex]; + } else { + [indexes addIndex:clickedIndex]; + } + } else { + if (flags & NSShiftKeyMask) { + // Add range to selection. + if ([indexes count] == 0) { + [indexes addIndex:clickedIndex]; + } else { + unsigned int origin = (clickedIndex < [indexes lastIndex]) ? clickedIndex :[indexes lastIndex]; + unsigned int length = (clickedIndex < [indexes lastIndex]) ? [indexes lastIndex] - clickedIndex : clickedIndex - [indexes lastIndex]; + + length++; + [indexes addIndexesInRange:NSMakeRange(origin, length)]; + } + } else { + if (![self isPhotoSelectedAtIndex:clickedIndex]) { + // Photo selection without modifiers. + [indexes removeAllIndexes]; + [indexes addIndex:clickedIndex]; + } + } + } + + potentialDragDrop = YES; + } else { + if ((flags & NSShiftKeyMask) == 0) { + [indexes removeAllIndexes]; + } + potentialDragDrop = NO; + } + + [self setSelectionIndexes:indexes]; + [indexes release]; + } +} + +- (void)mouseUp:(NSEvent *)event +{ + return; + // don't do a damn thing + // bug: calling set needs display results in background drawing over image parts without the images being asked to draw again +} + +- (void)mouseDragged:(NSEvent *)event +{ + + + if (0 == columns) return; + mouseCurrentPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + + // if the mouse has moved less than 5px in either direction, don't register the drag yet + float xFromStart = fabs((mouseDownPoint.x - mouseCurrentPoint.x)); + float yFromStart = fabs((mouseDownPoint.y - mouseCurrentPoint.y)); + if ((xFromStart < 5) && (yFromStart < 5)) { + return; + + } else if (potentialDragDrop && (nil != delegate)) { + // create a drag image + unsigned clickedIndex = [self photoIndexForPoint:mouseDownPoint]; + NSImage *clickedImage = [self photoAtIndex:clickedIndex]; + //BOOL flipped = [clickedImage isFlipped]; + //[clickedImage setFlipped:NO]; + NSSize scaledSize = [self scaledPhotoSizeForSize:[clickedImage size]]; + if (nil == clickedImage) { // creates a red image, which should let the user/developer know something is wrong + clickedImage = [[[NSImage alloc] initWithSize:NSMakeSize(photoSize,photoSize)] autorelease]; + [clickedImage lockFocus]; + [[NSColor redColor] set]; + [NSBezierPath fillRect:NSMakeRect(0,0,photoSize,photoSize)]; + [clickedImage unlockFocus]; + } + NSImage *dragImage = [[NSImage alloc] initWithSize:scaledSize]; + + // draw the drag image as a semi-transparent copy of the image the user dragged, and optionally a red badge indicating the number of photos + [dragImage lockFocus]; + [clickedImage drawInRect:NSMakeRect(0,0,scaledSize.width,scaledSize.height) fromRect:NSMakeRect(0,0,[clickedImage size].width,[clickedImage size].height) operation:NSCompositeCopy fraction:0.5]; + [dragImage unlockFocus]; + + //[clickedImage setFlipped:flipped]; + + // if there's more than one image, put a badge on the photo + if ([[self selectionIndexes] count] > 1) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; + [attributes setObject:[NSColor whiteColor] forKey:NSForegroundColorAttributeName]; + [attributes setObject:[NSFont fontWithName:@"Helvetica" size:14] forKey:NSFontAttributeName]; + NSAttributedString *badgeString = [[NSAttributedString alloc] initWithString:[[NSNumber numberWithInt:[[self selectionIndexes] count]] stringValue] attributes:attributes]; + NSSize stringSize = [badgeString size]; + int diameter = stringSize.width; + if (stringSize.height > diameter) diameter = stringSize.height; + diameter += 5; + + // calculate the badge circle + int minY = 5; + int maxX = [dragImage size].width - 5; + int maxY = minY + diameter; + int minX = maxX - diameter; + NSBezierPath *circle = [NSBezierPath bezierPathWithOvalInRect:NSMakeRect(minX,minY,maxX-minX,maxY-minY)]; + // draw the circle + [dragImage lockFocus]; + [[NSColor colorWithDeviceRed:1 green:0.1 blue:0.1 alpha:0.7] set]; + [circle fill]; + [dragImage unlockFocus]; + + // draw the string + NSPoint point; + point.x = maxX - ((maxX - minX) / 2) - 1; + point.y = (maxY - minY) / 2; + point.x = point.x - (stringSize.width / 2); + point.y = point.y - (stringSize.height / 2) + 7; + + [dragImage lockFocus]; + [badgeString drawAtPoint:point]; + [dragImage unlockFocus]; + + [badgeString release]; + [attributes release]; + } + + // get the pasteboard and register the returned types with delegate as the owner + NSPasteboard *pb = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pb declareTypes:[NSArray array] owner:nil]; // clear the pasteboard + [delegate photoView:self fillPasteboardForDrag:pb]; + + // place the cursor in the center of the drag image + NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil]; + NSSize imageSize = [dragImage size]; + p.x = p.x - imageSize.width / 2; + p.y = p.y + imageSize.height / 2; + + [self dragImage:dragImage at:p offset:NSZeroSize event:event pasteboard:pb source:self slideBack:YES]; + + [dragImage release]; + + } else { + // adjust the mouse current point so that it's not outside the frame + NSRect frameRect = [self frame]; + if (mouseCurrentPoint.x < NSMinX(frameRect)) + mouseCurrentPoint.x = NSMinX(frameRect); + if (mouseCurrentPoint.x > NSMaxX(frameRect)) + mouseCurrentPoint.x = NSMaxX(frameRect); + if (mouseCurrentPoint.y < NSMinY(frameRect)) + mouseCurrentPoint.y = NSMinY(frameRect); + if (mouseCurrentPoint.y > NSMaxY(frameRect)) + mouseCurrentPoint.y = NSMaxY(frameRect); + + // determine the rect for the current drag area + float minX, maxX, minY, maxY; + minX = (mouseCurrentPoint.x < mouseDownPoint.x) ? mouseCurrentPoint.x : mouseDownPoint.x; + minY = (mouseCurrentPoint.y < mouseDownPoint.y) ? mouseCurrentPoint.y : mouseDownPoint.y; + maxX = (mouseCurrentPoint.x > mouseDownPoint.x) ? mouseCurrentPoint.x : mouseDownPoint.x; + maxY = (mouseCurrentPoint.y > mouseDownPoint.y) ? mouseCurrentPoint.y : mouseDownPoint.y; + if (maxY > NSMaxY(frameRect)) + maxY = NSMaxY(frameRect); + if (maxX > NSMaxX(frameRect)) + maxX = NSMaxX(frameRect); + + NSRect selectionRect = NSMakeRect(minX,minY,maxX-minX,maxY-minY); + + unsigned minIndex = [self photoIndexForPoint:NSMakePoint(minX, minY)]; + unsigned xRun = [self photoIndexForPoint:NSMakePoint(maxX, minY)] - minIndex + 1; + unsigned yRun = [self photoIndexForPoint:NSMakePoint(minX, maxY)] - minIndex + 1; + unsigned selectedRows = (yRun / columns); + + // Save the current selection (if any), then populate the drag indexes + // this allows us to shift band select to add to the current selection. + [dragSelectedPhotoIndexes removeAllIndexes]; + [dragSelectedPhotoIndexes addIndexes:[self selectionIndexes]]; + + // add indexes in the drag rectangle + int i; + for (i = 0; i <= selectedRows; i++) { + unsigned rowStartIndex = (i * columns) + minIndex; + int j; + for (j = rowStartIndex; j < (rowStartIndex + xRun); j++) { + if (NSIntersectsRect([self photoRectForIndex:j],selectionRect)) + [dragSelectedPhotoIndexes addIndex:j]; + } + } + + // if requested, set the selection. this could cause a rapid series of KVO notifications, so if this is false, the view tracks + // the selection internally, but doesn't pass it to the bindings or the delegates until the drag is over. + // This will cause an appropriate redraw. + if (sendsLiveSelectionUpdates) + { + [self setSelectionIndexes:dragSelectedPhotoIndexes]; + } + + [[self superview] autoscroll:event]; + [self setNeedsDisplayInRect:[self visibleRect]]; + } +} + + +- (NSImage *)fastPhotoAtIndex:(unsigned)index +{ + NSImage *fastPhoto = nil; + if ((nil != [self photosArray]) && (index < [[self photosArray] count])) + { + fastPhoto = [photosFastArray objectAtIndex:index]; + if ((NSNull *)fastPhoto == [NSNull null]) + { + // Change this if you want higher/lower quality fast photos + float fastPhotoSize = 100.0; + + NSImageRep *fullSizePhotoRep = [[self scalePhoto:[self photoAtIndex:index]] bestRepresentationForDevice:nil]; + + // Figure out what the scaled size is + float longSide = [fullSizePhotoRep pixelsWide]; + if (longSide < [fullSizePhotoRep pixelsHigh]) + longSide = [fullSizePhotoRep pixelsHigh]; + + float scale = fastPhotoSize / longSide; + + NSSize scaledSize; + scaledSize.width = [fullSizePhotoRep pixelsWide] * scale; + scaledSize.height = [fullSizePhotoRep pixelsHigh] * scale; + + // Draw the full-size image into our fast, small image. + fastPhoto = [[NSImage alloc] initWithSize:scaledSize]; + //[fastPhoto setFlipped:YES]; + [fastPhoto lockFocus]; + [fullSizePhotoRep drawInRect:NSMakeRect(0.0, 0.0, scaledSize.width, scaledSize.height)]; + [fastPhoto unlockFocus]; + + // Save it off + [photosFastArray replaceObjectAtIndex:index withObject:fastPhoto]; + + [fastPhoto autorelease]; + } + } else if ((nil != delegate) && ([delegate respondsToSelector:@selector(photoView:fastPhotoAtIndex:)])) { + fastPhoto = [delegate photoView:self fastPhotoAtIndex:index]; + } + + // if the above calls failed, try to just fetch the full size image + if (![fastPhoto isValid]) { + fastPhoto = [self photoAtIndex:index]; + } + + return fastPhoto; +} + +- (NSImage *)scaleImage:(NSImage *)image toSize:(float)size +{ + NSImageRep *fullSizePhotoRep = [[self scalePhoto:image] bestRepresentationForDevice:nil]; + + float longSide = [fullSizePhotoRep pixelsWide]; + if (longSide < [fullSizePhotoRep pixelsHigh]) + longSide = [fullSizePhotoRep pixelsHigh]; + + float scale = size / longSide; + + NSSize scaledSize; + scaledSize.width = [fullSizePhotoRep pixelsWide] * scale; + scaledSize.height = [fullSizePhotoRep pixelsHigh] * scale; + + NSImage *fastPhoto = [[NSImage alloc] initWithSize:scaledSize]; + //[fastPhoto setFlipped:YES]; + [fastPhoto lockFocus]; + [fullSizePhotoRep drawInRect:NSMakeRect(0.0, 0.0, scaledSize.width, scaledSize.height)]; + [fastPhoto unlockFocus]; + + return [fastPhoto autorelease]; +} + +#pragma mark - + +- (void)updateGridAndFrame +{ + /**** BEGIN Dimension calculations and adjustments ****/ + + + // get the number of photos + unsigned photoCount = [self photoCount]; + + // calculate the base grid size + gridSize.height = [self photoSize] + [self photoVerticalSpacing]; + gridSize.width = [self photoSize] + [self photoHorizontalSpacing]; + + // if there are no photos, return + if (0 == photoCount) { + columns = 0; + rows = 0; + float width = [self frame].size.width; + float height = [[[self enclosingScrollView] contentView] frame].size.height; + [self setFrameSize:NSMakeSize(width, height)]; + return; + } + + // calculate the number of columns (ivar) + float width = [self frame].size.width; + columns = width / gridSize.width; + + // minimum 1 column + if (1 > columns) + columns = 1; + + // if we have fewer photos than columns, adjust downward + if (photoCount < columns) + columns = photoCount; + + // adjust the grid size width for extra space + gridSize.width += (width - (columns * gridSize.width)) / columns; + + // calculate the number of rows of photos based on the total count and the number of columns (ivar) + rows = photoCount / columns; + if (0 < (photoCount % columns)) + rows++; + // adjust my frame height to contain all the photos + float height = rows * gridSize.height; + NSScrollView *scroll = [self enclosingScrollView]; + if ((nil != scroll) && (height < [[scroll contentView] frame].size.height)) + height = [[scroll contentView] frame].size.height; + + // set my new frame size + [self setFrameSize:NSMakeSize(width, height)]; + + + + /**** END Dimension calculations and adjustments ****/ + return; +} + + +- (void)updatePhotoResizing +{ + NSTimeInterval timeSinceResize = [[NSDate date] timeIntervalSinceReferenceDate] - [photoResizeTime timeIntervalSinceReferenceDate]; + if (timeSinceResize > 1) { + isDonePhotoResizing = YES; + //[photoResizeTimer invalidate]; + + // **** PhilDow change - release timer **** + //[photoResizeTimer release]; + //photoResizeTimer = nil; + } + + if ( [self inLiveResize] ) + [self viewDidEndLiveResize]; +} + +#pragma mark - + +- (NSAttributedString *)pageHeader +{ + return nil; +} + +- (NSAttributedString *)pageFooter +{ + return nil; +} + +/* +// Return the number of pages available for printing +- (BOOL)knowsPageRange:(NSRangePointer)range { + + [self updateGridAndFrame]; + + NSRect bounds = NSMakeRect(0, 0, gridSize.width, gridSize.height); + float printHeight = [self calculatePrintHeight]; + + range->location = 1; + range->length = NSHeight(bounds) / printHeight + 1; + return YES; +} + +// Return the drawing rectangle for a particular page number +- (NSRect)rectForPage:(int)page { + NSRect bounds = NSMakeRect(0, 0, gridSize.width, gridSize.height); + float pageHeight = [self calculatePrintHeight]; + return NSMakeRect( NSMinX(bounds), NSMaxY(bounds) - page * pageHeight, + NSWidth(bounds), pageHeight ); +} + +// Calculate the vertical size of the view that fits on a single page +- (float)calculatePrintHeight { + // Obtain the print info object for the current operation + NSPrintInfo *pi = [[NSPrintOperation currentOperation] printInfo]; + + // Calculate the page height in points + NSSize paperSize = [pi paperSize]; + float pageHeight = paperSize.height - [pi topMargin] - [pi bottomMargin]; + + // Convert height to the scaled view + float scale = [[[pi dictionary] objectForKey:NSPrintScalingFactor] + floatValue]; + return pageHeight / scale; +} +*/ + +/* +- (void)beginDocument +{ + amPrinting = YES; + [super beginDocument]; +} + +- (void)endDocument +{ + [super endDocument]; + amPrinting = NO; +} +*/ + +/* +- (void)print:(id)sender +{ + amPrinting = YES; + [super print:sender]; + amPrinting = NO; +} +*/ + +@end + diff --git a/PDPopUpButton.h b/PDPopUpButton.h new file mode 100644 index 0000000..30b95be --- /dev/null +++ b/PDPopUpButton.h @@ -0,0 +1,18 @@ +// +// PDPopupButton.h +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDPopUpButtonCell; + +@interface PDPopUpButton : NSPopUpButton { + +} + +@end diff --git a/PDPopUpButton.m b/PDPopUpButton.m new file mode 100644 index 0000000..f245df0 --- /dev/null +++ b/PDPopUpButton.m @@ -0,0 +1,86 @@ +// +// PDPopupButton.m +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDPopUpButton + +- (id)initWithCoder:(NSCoder *)decoder { + + /* + NSKeyedUnarchiver *coder = (id)decoder; + + // gather info about the superclass's cell and save the archiver's old mapping + Class superCell = [[self superclass] cellClass]; + NSString *oldClassName = NSStringFromClass( superCell ); + + NSLog(@"%@ -> %@", oldClassName, NSStringFromClass([[self class] cellClass])); + + Class oldClass = [coder classForClassName: oldClassName]; + if( !oldClass ) oldClass = superCell; + + // override what comes out of the unarchiver + [coder setClass: [[self class] cellClass] forClassName: oldClassName]; + + // unarchive + self = [super initWithCoder: coder]; + + // set it back + //[coder setClass: oldClass forClassName: oldClassName]; + + NSLog([[self cell] className]); + */ + + /* + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + + [anArchiver encodeClassName:@"NSPopUpButtonCell" intoClassName:@"PDPopUpButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + } + */ + + if ( self = [super initWithCoder:decoder] ) { + NSMenu *theMenu = [[self menu] copyWithZone:[self zone]]; + [self setCell:[[[PDPopUpButtonCell alloc] + initTextCell:[self title] + pullsDown:[self pullsDown]] autorelease]]; + [self setMenu:theMenu]; + [theMenu release]; + } + + return self; +} + + +- (void) awakeFromNib { + + [[self cell] setMenu:[self menu]]; + +} + + ++ (Class) cellClass +{ + return [PDPopUpButtonCell class]; +} + + +//- (BOOL) isFlipped { return YES; } + +- (BOOL)isOpaque { return NO; } + + +@end diff --git a/PDPopUpButtonCell.h b/PDPopUpButtonCell.h new file mode 100644 index 0000000..3743058 --- /dev/null +++ b/PDPopUpButtonCell.h @@ -0,0 +1,16 @@ +// +// PDPopupButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDPopUpButtonCell : NSPopUpButtonCell { + +} + +@end diff --git a/PDPopUpButtonCell.m b/PDPopUpButtonCell.m new file mode 100644 index 0000000..a71f30b --- /dev/null +++ b/PDPopUpButtonCell.m @@ -0,0 +1,133 @@ +// +// PDPopupButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 12/10/05. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +@implementation PDPopUpButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + } + + return self; + +} + +- (id)initTextCell:(NSString *)stringValue pullsDown:(BOOL)pullDown { + + if ( self = [super initTextCell:stringValue pullsDown:pullDown] ) { + + [self setBordered:NO]; + } + + return self; +} + +- (void) dealloc { + + [super dealloc]; + +} + +#pragma mark - + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor, *arrowColor; + + if ( [self isHighlighted] ) { + + arrowColor = [NSColor colorWithCalibratedRed:40.0/255.0 green:40.0/255.0 blue:40.0/255.0 alpha:0.9]; + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else { + + arrowColor = [NSColor colorWithCalibratedRed:40.0/255.0 green:40.0/255.0 blue:40.0/255.0 alpha:0.8]; + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + int height = cellFrame.size.height; + int width = cellFrame.size.width; + + NSMutableParagraphStyle *pStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]]; + [pStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11.0], NSFontAttributeName, + ( [self isEnabled] ? [NSColor blackColor] : [NSColor lightGrayColor] ), NSForegroundColorAttributeName, + pStyle, NSParagraphStyleAttributeName, nil]; + + NSSize stringSize = [[self title] sizeWithAttributes:attributes]; + + NSRect stringRect = NSMakeRect(width/2.0-stringSize.width/2.0, height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + NSRect targetRect = NSMakeRect( cellFrame.origin.x, stringRect.origin.y-2.0, + cellFrame.size.width, stringRect.size.height+4.0 ); + + targetRect = NSInsetRect(targetRect,3.5,0.5); + + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:8.5] stroke]; + + NSBezierPath *arrowsPath = [NSBezierPath bezierPath]; + [arrowsPath appendBezierPathWithTriangleInRect:NSMakeRect(0,1,5,4) orientation:AMTriangleUp]; + [arrowsPath appendBezierPathWithTriangleInRect:NSMakeRect(0,-5,5,4) orientation:AMTriangleDown]; + + NSAffineTransform *transform = [NSAffineTransform transform]; + [transform translateXBy:width-17.0 yBy:height/2.0]; + + [arrowsPath transformUsingAffineTransform:transform]; + [arrowColor set]; + [arrowsPath fill]; + + [[self titleOfSelectedItem] drawInRect:NSMakeRect(12, height/2-stringSize.height/2, width-30, stringSize.height) + withAttributes:attributes]; + +} + +@end diff --git a/PDPopUpButtonToolbarItem.h b/PDPopUpButtonToolbarItem.h new file mode 100644 index 0000000..2f6dafc --- /dev/null +++ b/PDPopUpButtonToolbarItem.h @@ -0,0 +1,21 @@ +// +// PDPopUpButtonToolbarItem.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDPopUpButtonToolbarItem : NSPopUpButton +{ + +} + +- (NSSize) iconSize; +- (void) setIconSize:(NSSize)aSize; + +@end diff --git a/PDPopUpButtonToolbarItem.m b/PDPopUpButtonToolbarItem.m new file mode 100644 index 0000000..e6daac0 --- /dev/null +++ b/PDPopUpButtonToolbarItem.m @@ -0,0 +1,77 @@ +// +// PDPopUpButtonToolbarItem.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDPopUpButtonToolbarItem + + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) + { + NSMenu *theMenu = [[self menu] copyWithZone:[self zone]]; + + [self setCell:[[[PDPopUpButtonToolbarItemCell alloc] + initTextCell:[self title] + pullsDown:[self pullsDown]] autorelease]]; + [self setMenu:theMenu]; + + [self setIconSize:NSMakeSize(32,32)]; + [[self cell] setFont:[NSFont systemFontOfSize:11]]; + + [theMenu release]; + } + + /* + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + + [anArchiver encodeClassName:@"NSPopUpButtonCell" intoClassName:@"PDPopUpButtonToolbarItemCell"]; + [anArchiver encodeRootObject:[self cell]]; + + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + [self setIconSize:NSMakeSize(32,32)]; + [[self cell] setFont:[NSFont systemFontOfSize:11]]; + + } + */ + + return self; +} + + +- (void) awakeFromNib { + + [[self cell] setMenu:[self menu]]; + +} + + ++ (Class) cellClass +{ + return [PDPopUpButtonToolbarItemCell class]; +} + +- (NSSize) iconSize +{ + return [(PDPopUpButtonToolbarItemCell*)[self cell] iconSize]; +} + +-(void) setIconSize:(NSSize)aSize +{ + [(PDPopUpButtonToolbarItemCell*)[self cell] setIconSize:aSize]; + [self setNeedsDisplay:YES]; +} + + +@end diff --git a/PDPopUpButtonToolbarItemCell.h b/PDPopUpButtonToolbarItemCell.h new file mode 100644 index 0000000..bda059f --- /dev/null +++ b/PDPopUpButtonToolbarItemCell.h @@ -0,0 +1,22 @@ + +// +// PDPopUpButtonToolbarItemCell.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDPopUpButtonToolbarItemCell : NSPopUpButtonCell +{ + + NSSize size; +} + +- (NSSize) iconSize; +- (void) setIconSize:(NSSize)aSize; + +@end diff --git a/PDPopUpButtonToolbarItemCell.m b/PDPopUpButtonToolbarItemCell.m new file mode 100644 index 0000000..34b92c3 --- /dev/null +++ b/PDPopUpButtonToolbarItemCell.m @@ -0,0 +1,63 @@ + +// +// PDPopUpButtonToolbarItemCell.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDPopUpButtonToolbarItemCell + + +- (NSSize) iconSize +{ + return size; +} + +- (void) setIconSize:(NSSize)aSize +{ + size = aSize; +} + +#pragma mark Drawing + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + [ self drawInteriorWithFrame:cellFrame inView:controlView ]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + NSImage *image = [self image]; + + NSRect sourceRect = NSMakeRect( 0.0, 0.0, [ image size ].width ,[ image size ].height); + NSRect destRect = sourceRect; + NSRect controlBounds = [ controlView bounds ]; + + NSGraphicsContext* context = [ NSGraphicsContext currentContext ]; + [ context saveGraphicsState ]; + [context setImageInterpolation:NSImageInterpolationHigh]; + + if ( [ controlView isFlipped ] ) + { + NSAffineTransform* flipTransform = [ NSAffineTransform transform ]; + [ flipTransform translateXBy:0.0 yBy:NSMaxY(controlBounds) ]; + [ flipTransform scaleXBy:1.0 yBy:-1.0 ]; + [ flipTransform concat ]; + } + + destRect.origin.x = ( controlBounds.size.width - [self iconSize].width ) / 2.0; + destRect.origin.y = ( controlBounds.size.height - [self iconSize].height ) / 2.0; + destRect.size.width = [self iconSize].width; + destRect.size.height = [self iconSize].height; + + [ image drawInRect:destRect fromRect:sourceRect operation:NSCompositeSourceOver fraction:( [(NSControl*)[self controlView] isEnabled] ? 1.0 : 0.55 ) ]; + + [ context restoreGraphicsState ]; +} + +@end diff --git a/PDPredicateBuilder.h b/PDPredicateBuilder.h new file mode 100644 index 0000000..1a36a4c --- /dev/null +++ b/PDPredicateBuilder.h @@ -0,0 +1,36 @@ +// +// PDPredicateBuilder.h +// SproutedInterface +// +// Created by Philip Dow on 4/10/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// And the .m? + +@protocol PDPredicateBuilder + +- (NSCompoundPredicateType) compoundPredicateType; +- (void) setCompoundPredicateType:(NSCompoundPredicateType)predicateType; + +- (NSPredicate*) predicate; +- (void) setPredicate:(NSPredicate*)aPredicate; + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (NSView*) contentView; + +- (NSSize) requiredSize; +- (void) setMinWidth:(float)width; + +- (BOOL) validatePredicate; + +@end + +@interface NSObject (PDPredicateBuilderDelegate) + +- (void) predicateBuilder:(id)aPredicateBuilder predicateDidChange:(NSPredicate*)newPredicate; +- (void) predicateBuilder:(id)aPredicateBuilder sizeDidChange:(NSSize)newSize; + +@end \ No newline at end of file diff --git a/PDPrintTextView.h b/PDPrintTextView.h new file mode 100644 index 0000000..26a6f24 --- /dev/null +++ b/PDPrintTextView.h @@ -0,0 +1,41 @@ +// +// PDPrintTextView.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +// +// This class overrides two methods to provide custom header +// and footers during printing: +// - (NSAttributedString *)pageHeader; +// - (NSAttributedString *)pageFooter; +// +// + +#import + +@interface PDPrintTextView : NSTextView +{ + BOOL printHeader; + BOOL printFooter; + + NSString *printTitle; + NSString *printDate; +} + +- (BOOL) printHeader; +- (void) setPrintHeader:(BOOL)print; + +- (BOOL) printFooter; +- (void) setPrintFooter:(BOOL)print; + +- (NSString*) printTitle; +- (void) setPrintTitle:(NSString*)title; + +- (NSString*) printDate; +- (void) setPrintDate:(NSString*)date; + +@end diff --git a/PDPrintTextView.m b/PDPrintTextView.m new file mode 100644 index 0000000..3f24fa2 --- /dev/null +++ b/PDPrintTextView.m @@ -0,0 +1,136 @@ +// +// PDPrintTextView.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDPrintTextView + +- (id)initWithFrame:(NSRect)frameRect textContainer:(NSTextContainer *)aTextContainer { + if ( self = [super initWithFrame:frameRect textContainer:aTextContainer] ) { + printTitle = [[NSString alloc] init]; + printDate = [[NSString alloc] init]; + + } + return self; +} + +- (void) dealloc { + [printTitle release]; + printTitle = nil; + [printDate release]; + printDate = nil; + [super dealloc]; +} + +#pragma mark - + +- (BOOL) printHeader { return printHeader; } + +- (void) setPrintHeader:(BOOL)print { + printHeader = print; +} + +- (BOOL) printFooter { return printFooter; } + +- (void) setPrintFooter:(BOOL)print { + printFooter = print; +} + +- (NSString*) printTitle { return ( printTitle ? printTitle : [NSString string] ); } + +- (void) setPrintTitle:(NSString*)title { + if ( printTitle != title ) { + [printTitle release]; + printTitle = [title copyWithZone:[self zone]]; + } +} + +- (NSString*) printDate { return ( printDate ? printDate : [NSString string] ); } + +- (void) setPrintDate:(NSString*)date { + if ( printDate != date ) { + [printDate release]; + printDate = [date copyWithZone:[self zone]]; + } +} + +#pragma mark - + +- (NSString *)printJobTitle { + + return [self printTitle]; + +} + +- (NSAttributedString *)pageHeader { + + // + // For now returns a string including the journal title and the date + // Will very likely allow for customization later + // + + NSAttributedString *theHeader = nil; + + if ( [self printHeader] ) { + + // format the title and date appropriately + /* + NSMutableDictionary *attributes; + NSMutableParagraphStyle *paragraph; + NSAttributedString *supersReturn; + NSAttributedString *attributedHeader; + NSString *plainText; + + supersReturn = [super pageHeader]; + paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + attributes = [[supersReturn attributesAtIndex:0 effectiveRange:nil] mutableCopy]; + plainText = [NSString stringWithFormat:@"%@\n%@", [self printJobTitle], [self printDate]]; + + [paragraph setAlignment:NSRightTextAlignment]; + [attributes setObject:paragraph forKey:NSParagraphStyleAttributeName]; + + attributedHeader = [[NSAttributedString alloc] initWithString:plainText attributes:attributes]; + + // clean up those mutable copies + [attributes release]; + [paragraph release]; + + return [attributedHeader autorelease]; + */ + + theHeader = [super pageHeader]; + + } + else { + + theHeader = [[[NSAttributedString alloc] initWithString:[NSString string]] autorelease]; + + } + + return theHeader; +} + +- (NSAttributedString *)pageFooter { + + // + // Use super's implementation + // - I'm not sure how to figure out which page is being queried + // + + NSAttributedString *theFooter = nil; + + if ( [self printFooter] ) + theFooter = [super pageFooter]; + else + theFooter = [[[NSAttributedString alloc] initWithString:[NSString string]] autorelease]; + + return theFooter; +} + +@end diff --git a/PDRankCell.h b/PDRankCell.h new file mode 100644 index 0000000..e606e05 --- /dev/null +++ b/PDRankCell.h @@ -0,0 +1,27 @@ +// +// PDRankCell.h +// SproutedInterface +// +// Created by Philip Dow on 9/13/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDRankCell : NSTextFieldCell { + float minRank, maxRank, rank; +} + +- (float) minRank; +- (void) setMinRank:(float)value; + +- (float) maxRank; +- (void) setMaxRank:(float)value; + +- (float) rank; +- (void) setRank:(float)value; + + +@end diff --git a/PDRankCell.m b/PDRankCell.m new file mode 100644 index 0000000..d5bb1f3 --- /dev/null +++ b/PDRankCell.m @@ -0,0 +1,120 @@ +// +// PDRankCell.m +// SproutedInterface +// +// Created by Philip Dow on 9/13/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import + +@implementation PDRankCell + +- (id)initWithCoder:(NSCoder *)decoder { + if ( self = [super initWithCoder:decoder] ) { + minRank = 0.0; + maxRank = 1.0; + } + return self; +} + +- (id)initTextCell:(NSString *)aString { + if ( self = [super initTextCell:aString] ) { + minRank = 0.0; + maxRank = 1.0; + } + return self; +} + +#pragma mark - + +- (float) minRank { + return minRank; +} + +- (void) setMinRank:(float)value { + minRank = value; +} + +- (float) maxRank { + return maxRank; +} + +- (void) setMaxRank:(float)value { + maxRank = value; +} + +- (float) rank { + return rank; +} + +- (void) setRank:(float)value { + rank = value; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + NSNumber *rankObject = [self objectValue]; + float aRank = [rankObject floatValue]; + + // draw the rank + if ( aRank != 0 ) { + + NSRect inset = cellFrame; + + inset.origin.x += 2; + inset.size.width -= 4; + inset.origin.y += 1; + inset.size.height -= 2; + + float delta = ( maxRank - minRank ); + if ( delta == 0 ) delta = 0.000001; + + float rankPercent = ( aRank - minRank ) / delta; + float distance = ( inset.size.width * rankPercent ); + + NSRect rankRect = NSMakeRect( inset.origin.x, + inset.origin.y + ( inset.size.height / 2 ) - 5, + distance, 10); + + NSColor *gradientStart, *gradientEnd; + + gradientStart = [NSColor colorWithCalibratedRed:195.0/255.0 green:195.0/255.0 blue:195.0/255.0 alpha:0.8]; + gradientEnd = [NSColor colorWithCalibratedRed:161.0/255.0 green:161.0/255.0 blue:161.0/255.0 alpha:0.8]; + + NSRect top, bottom; + NSDivideRect(rankRect, &top, &bottom, rankRect.size.height/2, NSMinYEdge); + top.size.height++; + + NSBezierPath *contentPath = [NSBezierPath bezierPath]; + NSBezierPath *clipPath = [NSBezierPath bezierPathWithRoundedRect:rankRect cornerRadius:5.0]; + + int i; + for ( i = 1; i < distance; i+=2 ) + { + [contentPath moveToPoint:NSMakePoint(rankRect.origin.x+i, rankRect.origin.y)]; + [contentPath lineToPoint:NSMakePoint(rankRect.origin.x+i, rankRect.origin.y+rankRect.size.height)]; + } + + NSGraphicsContext *context = [NSGraphicsContext currentContext]; + [context saveGraphicsState]; + [clipPath setClip]; + + [[NSBezierPath bezierPathWithRect:top] linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + [[NSBezierPath bezierPathWithRect:bottom] linearGradientFillWithStartColor:gradientEnd endColor:gradientStart]; + + //[context setShouldAntialias:NO]; + + //[[NSColor colorWithCalibratedWhite:1.0 alpha:0.3] set]; + //[contentPath setLineWidth:1.0]; + //[contentPath stroke]; + + [context restoreGraphicsState]; + } +} + + +@end diff --git a/PDSelfValidatingToolbarItem.h b/PDSelfValidatingToolbarItem.h new file mode 100644 index 0000000..b495a16 --- /dev/null +++ b/PDSelfValidatingToolbarItem.h @@ -0,0 +1,25 @@ +// +// PDSelfEnablingToolbarItem.h +// SproutedInterface +// +// Created by Philip Dow on 12/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDSelfValidatingToolbarItem : NSToolbarItem { + + BOOL forcedEnabled; + BOOL forcedEnabling; +} + +- (BOOL) forcedEnabled; +- (void) setForcedEnabled:(BOOL)doEnable; + +- (BOOL) forcedEnabling; +- (void) setForcedEnabling:(BOOL)doForce; + +@end diff --git a/PDSelfValidatingToolbarItem.m b/PDSelfValidatingToolbarItem.m new file mode 100644 index 0000000..9a50db0 --- /dev/null +++ b/PDSelfValidatingToolbarItem.m @@ -0,0 +1,43 @@ +// +// PDSelfEnablingToolbarItem.m +// SproutedInterface +// +// Created by Philip Dow on 12/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDSelfValidatingToolbarItem + +- (BOOL) forcedEnabled +{ + return forcedEnabled; +} + +- (void) setForcedEnabled:(BOOL)doEnable +{ + forcedEnabled = doEnable; + //[self validate]; +} + +- (BOOL) forcedEnabling +{ + return forcedEnabling; +} + +- (void) setForcedEnabling:(BOOL)doForce +{ + forcedEnabling = doForce; +} + +#pragma mark - + +- (void)validate +{ + [self setEnabled:( [self forcedEnabling] ? [self forcedEnabled] : ( [NSApp targetForAction:[self action]] != nil ) )]; +} + +@end diff --git a/PDStylesButton.h b/PDStylesButton.h new file mode 100644 index 0000000..1efa933 --- /dev/null +++ b/PDStylesButton.h @@ -0,0 +1,21 @@ +// +// PDStylesButton.h +// SproutedInterface +// +// Created by Philip Dow on 5/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDStylesButtonCell; + +@interface PDStylesButton : NSButton { + +} + +- (int) superscriptValue; +- (void) setSuperscriptValue:(int)offset; + +@end diff --git a/PDStylesButton.m b/PDStylesButton.m new file mode 100644 index 0000000..ee17f05 --- /dev/null +++ b/PDStylesButton.m @@ -0,0 +1,43 @@ +// +// PDStylesButton.m +// SproutedInterface +// +// Created by Philip Dow on 5/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +@implementation PDStylesButton + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSButtonCell" intoClassName:@"PDStylesButtonCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDStylesButtonCell class]; +} + +- (int) superscriptValue { + return [[self cell] superscriptValue]; +} + +- (void) setSuperscriptValue:(int)offset { + [[self cell] setSuperscriptValue:offset]; +} + +@end diff --git a/PDStylesButtonCell.h b/PDStylesButtonCell.h new file mode 100644 index 0000000..c41c78b --- /dev/null +++ b/PDStylesButtonCell.h @@ -0,0 +1,20 @@ +// +// PDStylesButtonCell.h +// SproutedInterface +// +// Created by Philip Dow on 5/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface PDStylesButtonCell : NSButtonCell { + + int _superscriptValue; +} + +- (int) superscriptValue; +- (void) setSuperscriptValue:(int)offset; + +@end diff --git a/PDStylesButtonCell.m b/PDStylesButtonCell.m new file mode 100644 index 0000000..ef2bf6f --- /dev/null +++ b/PDStylesButtonCell.m @@ -0,0 +1,161 @@ +// +// PDStylesButtonCell.m +// SproutedInterface +// +// Created by Philip Dow on 5/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +@implementation PDStylesButtonCell + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (id)initTextCell:(NSString *)aString { + + if ( self = [super initTextCell:aString] ) { + + [self setBordered:NO]; + + } + + return self; + +} + +- (int) superscriptValue { return _superscriptValue; } + +- (void) setSuperscriptValue:(int)offset { + _superscriptValue = offset; +} + +- (NSRect)drawingRectForBounds:(NSRect)theRect { + return theRect; +} + +- (NSRect)titleRectForBounds:(NSRect)theRect { + return theRect; +} + + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + // + // bypass the frame + // + + [self drawInteriorWithFrame:cellFrame inView:controlView]; + +} + + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + float alpha = ( [self isEnabled] ? 1.0 : 0.70 ); + NSColor *gradientStart, *gradientEnd, *borderColor; + + if ( [self isHighlighted] || [self state] == NSOnState ) { + + borderColor = [NSColor colorWithCalibratedRed:149.0/255.0 green:149.0/255.0 blue:149.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:alpha]; + + } + + else { + + borderColor = [NSColor colorWithCalibratedRed:173.0/255.0 green:173.0/255.0 blue:173.0/255.0 alpha:alpha]; + gradientEnd = [NSColor colorWithCalibratedRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:alpha]; + gradientStart = [NSColor colorWithCalibratedRed:253.0/255.0 green:253.0/255.0 blue:253.0/255.0 alpha:alpha]; + + } + + int height = cellFrame.size.height; + int width = cellFrame.size.width; + + + // + // draw the gradient + + NSRect targetRect = NSInsetRect(cellFrame,0.5,0.5); + + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:2.0] + linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + [borderColor set]; + [[NSBezierPath bezierPathWithRoundedRect:targetRect cornerRadius:2.0] stroke]; + + // + // draw the string value + + NSAttributedString *attr_string = [self attributedTitle]; + if ( attr_string != nil ) { + + NSSize stringSize = [attr_string size]; + NSRect stringRect = NSMakeRect(width/2.0-stringSize.width/2.0, height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + if ( _superscriptValue != 0 ) { + + int widthOffset = stringSize.width/3/2; + + NSAttributedString *partNorm = [attr_string attributedSubstringFromRange:NSMakeRange(0,1)]; + NSMutableAttributedString *partScript = + [[attr_string attributedSubstringFromRange:NSMakeRange(1,[attr_string length]-1)] mutableCopy]; + + NSFont *aFont = [partScript attribute:NSFontAttributeName atIndex:0 effectiveRange:nil]; + NSFont *sizedFont = [[NSFontManager sharedFontManager] convertFont:aFont toSize:[aFont pointSize]-3]; + + [partScript addAttribute:NSFontAttributeName value:sizedFont range:NSMakeRange(0,[partScript length])]; + + [partNorm drawAtPoint:NSMakePoint(stringRect.origin.x+widthOffset, stringRect.origin.y)]; + [partScript drawAtPoint: + NSMakePoint(stringRect.origin.x+widthOffset+(stringRect.size.width/[attr_string length]), + stringRect.origin.y - (_superscriptValue*3))]; + + } + else { + + [attr_string drawInRect:stringRect]; + + } + + } + else { + + NSString *title = [self title]; + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:11.0], NSFontAttributeName, + ( [self isEnabled] ? [NSColor blackColor] : [NSColor lightGrayColor] ), NSForegroundColorAttributeName, nil]; + + NSSize stringSize = [title sizeWithAttributes:attributes]; + NSRect stringRect = NSMakeRect(width/2.0-stringSize.width/2.0, height/2.0-stringSize.height/2.0, + stringSize.width, stringSize.height); + + [title drawInRect:stringRect withAttributes:attributes]; + + } + + + +} + + +@end diff --git a/PDTableView.h b/PDTableView.h new file mode 100644 index 0000000..d14c9fa --- /dev/null +++ b/PDTableView.h @@ -0,0 +1,25 @@ +// +// PDTableView.h +// SproutedInterface +// +// Created by Philip Dow on 2/1/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDTableView : NSTableView { + +} + +@end + + +@interface NSObject (PDTableViewDelegate) + +- (void) tableView:(NSTableView*)aTableView leftNavigationEvent:(NSEvent*)anEvent; +- (void) tableView:(NSTableView*)aTableView rightNavigationEvent:(NSEvent*)anEvent; + +@end \ No newline at end of file diff --git a/PDTableView.m b/PDTableView.m new file mode 100644 index 0000000..eda3c1a --- /dev/null +++ b/PDTableView.m @@ -0,0 +1,49 @@ +// +// PDTableView.m +// SproutedInterface +// +// Created by Philip Dow on 2/1/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation PDTableView + +- (void)keyDown:(NSEvent *)event +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s - beginning", [self className], _cmd) + #endif + + unsigned int modifierFlags = [event modifierFlags]; + unichar key = [[event charactersIgnoringModifiers] characterAtIndex:0]; + + if ( key == NSLeftArrowFunctionKey && [[self delegate] respondsToSelector:@selector(tableView:leftNavigationEvent:)] && ( modifierFlags & NSCommandKeyMask ) ) + [[self delegate] tableView:self leftNavigationEvent:event]; + else if ( key == NSRightArrowFunctionKey && [[self delegate] respondsToSelector:@selector(tableView:rightNavigationEvent:)] && ( modifierFlags & NSCommandKeyMask ) ) + [[self delegate] tableView:self rightNavigationEvent:event]; + else + { + [super keyDown:event]; + } + + #ifdef __DEBUG__ + NSLog(@"%@ %s - ending", [self className], _cmd) + #endif + +} + +- (void)cancelOperation:(id)sender +{ + if ([self currentEditor] != nil) + { + [self abortEditing]; + + // We lose focus so re-establish + [[self window] makeFirstResponder:self]; + } +} + +@end diff --git a/PDTabsView.h b/PDTabsView.h new file mode 100644 index 0000000..d02613f --- /dev/null +++ b/PDTabsView.h @@ -0,0 +1,128 @@ +// +// PDTabsView.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@class PDTabs; + +@interface PDTabsView : NSView +{ + int availableWidth; + int closeDown; + + int _flashingTab; + int _malFlash; + BOOL _flashing; + + int _tabToSelect; + int _targetTabForContext; + BOOL _amSwitching; + + BOOL _tabFromTop; + BOOL drawsShadow; + + NSPoint _lastViewLoc; + NSDate *_lastStillMoment; + + NSPopUpButton *morePop; + NSMenuItem *popTitle; + + NSColor *backgroundColor; + + int lastTabCount; + int hoverIndex; + int closeHoverIndex; + int selectingIndex; + NSMutableArray *titleTrackingRects; + NSMutableArray *closeButtonTrackingRects; + + NSImage *tabCloseFront; + NSImage *tabCloseFrontDown; + + NSImage *tabCloseBack; + NSImage *tabCloseBackDown; + + NSImage *backRollover; + NSImage *frontRollover; + + int borders[4]; + + // Jourlner Additions -------------------------- + + NSImage *totalImage; + + IBOutlet id delegate; + IBOutlet id dataSource; + + NSMenu *contextMenu; +} + +- (id) delegate; +- (void) setDelegate:(id)anObject; + +- (id) dataSource; +- (void) setDataSource:(id)anObject; + +- (int) selectedTab; + +#pragma mark - + +- (BOOL) tabFromTop; +- (void) setTabFromTop:(BOOL)direction; + +- (BOOL) drawsShadow; +- (void) setDrawsShadow:(BOOL)shadow; + +- (int*) borders; +- (void) setBorders:(int*)theBorders; + +- (int) availableWidth; +- (void) setAvailableWidth:(int)tabWidth; + +- (NSColor*) backgroundColor; +- (void) setBackgroundColor:(NSColor*)color; + +- (void) handleRegisterDragTypes; +- (void) handleDeregisterDragTypes; + +- (void) flashTab:(int)tab; +- (void) flash:(NSTimer*)timer; + +- (void) closeTab:(int)tab; +- (void) selectTab:(int)newSelection; + +- (IBAction) selectTabByPop:(id)sender; + +- (IBAction) newTab:(id)sender; +- (IBAction) closeTargetedTab:(id)sender; +- (IBAction) closeOtherTabs:(id)sender; + +- (void) updateTrackingRects; +- (void) _updateTrackingRects:(NSNotification*)aNotification; +- (void) _toolbarDidChangeVisible:(NSNotification*)aNotification; + +- (NSRect) frameOfTabAtIndex:(int)theIndex; +- (NSRect) frameOfCloseButtonAtIndex:(int)theIndex; + +@end + +@interface NSObject (PDTabsDataSource) + +- (unsigned int) numberOfTabsInTabView:(PDTabsView*)aTabView; +- (unsigned int) selectedTabIndexInTabView:(PDTabsView*)aTabView; +- (NSString*) tabsView:(PDTabsView*)aTabView titleForTabAtIndex:(unsigned int)index; + +@end + +@interface NSObject (PDTabsDelegate) + +- (void) tabsView:(PDTabsView*)aTabView removedTabAtIndex:(int)index; +- (void) tabsView:(PDTabsView*)aTabView selectedTabAtIndex:(int)index; + +@end diff --git a/PDTabsView.m b/PDTabsView.m new file mode 100644 index 0000000..affea23 --- /dev/null +++ b/PDTabsView.m @@ -0,0 +1,1316 @@ + +// +// PDTabsView.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import + +#import + +#import +#import +#import + +#define kMaxTabWidth 180 +#define kMinTabWidth 84 +#define kTabOffset 12 +#define kTabHeight 21 +#define kLabelOffset 3 +#define kCloseOffset 4 + +//static NSString *kABPeopleUIDsPboardType = @"ABPeopleUIDsPboardType"; +//static NSString *kMailMessagePboardType = @"MV Super-secret message transfer pasteboard type"; + +static NSDictionary* TitleAttributes() +{ + static NSDictionary *textAttributes = nil; + if ( textAttributes == nil ) + { + NSMutableParagraphStyle *paragraphStyle; + + paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; + [paragraphStyle setAlignment:NSLeftTextAlignment]; + [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + textAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:11], NSFontAttributeName, + [NSColor colorWithCalibratedWhite:0.55 alpha:1.0], NSForegroundColorAttributeName, + paragraphStyle, NSParagraphStyleAttributeName, nil]; + } + return textAttributes; +} + +@implementation PDTabsView + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect]) != nil) + { + // Add initialization code here + + NSMutableParagraphStyle *tempStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopyWithZone:[self zone]]; + [tempStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + + tabCloseFront = [BundledImageWithName(@"tabclosefront.tif", @"com.sprouted.interface") retain]; + tabCloseBack = [BundledImageWithName(@"tabcloseback.tif", @"com.sprouted.interface") retain]; + + tabCloseFrontDown = [BundledImageWithName(@"tabclosefrontdown.tif", @"com.sprouted.interface") retain]; + tabCloseBackDown = [BundledImageWithName(@"tabclosebackdown.tif", @"com.sprouted.interface") retain]; + + backRollover = [BundledImageWithName(@"tabclosebackroll.tif", @"com.sprouted.interface") retain]; + frontRollover = [BundledImageWithName(@"tabclosefrontroll.tif", @"com.sprouted.interface") retain]; + + // build a popup button that indicates more + NSImage *moreImage = BundledImageWithName(@"more.tif", @"com.sprouted.interface"); + popTitle = [[NSMenuItem alloc] initWithTitle:@"" + action:nil + keyEquivalent:@""]; + + [popTitle setImage:moreImage]; + + morePop = [[NSPopUpButton alloc] initWithFrame:NSMakeRect( frameRect.size.width - 28, 6, 28, 10 ) pullsDown:YES]; + + [morePop setBordered:NO]; + [morePop setTarget:self]; + [morePop setAction:@selector(selectTabByPop:)]; + [morePop setAutoresizingMask:NSViewMinXMargin]; + [morePop setHidden:YES]; + [[morePop menu] addItem:popTitle]; + [[morePop cell] setArrowPosition:NSPopUpNoArrow]; + + [self addSubview:morePop]; + + _flashingTab = -1; + closeDown = -1; + _targetTabForContext = -1; + _tabToSelect = -1; + + hoverIndex = -1; + selectingIndex = -1; + closeHoverIndex = -1; + + borders[0] = 0; borders[1] = 0; borders[2] = 0; borders[3] = 0; + + drawsShadow = YES; + _amSwitching = NO; + _lastViewLoc = NSZeroPoint; + _lastStillMoment = [[NSDate date] retain]; + + titleTrackingRects = [[NSMutableArray alloc] init]; + closeButtonTrackingRects = [[NSMutableArray alloc] init]; + + [self setAutoresizingMask:NSViewWidthSizable|NSViewMinYMargin]; + + //totalImage = [[NSImage alloc] initWithSize:frameRect.size]; + + //backgroundColor = [[NSColor windowBackgroundColor] retain]; + backgroundColor = [[NSColor colorWithCalibratedWhite:230.0/255.0 alpha:1.0] retain]; + + // build the contextual menu + contextMenu = [[NSMenu alloc] initWithTitle:@"Context"]; + + NSMenuItem *newTabItem = [[[NSMenuItem alloc] + initWithTitle:NSLocalizedStringFromTableInBundle( + @"new tab", + @"PDTabsView", + [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], + @"") + action:@selector(newTab:) + keyEquivalent:@""] autorelease]; + + NSMenuItem *closeTabItem = [[[NSMenuItem alloc] + initWithTitle:NSLocalizedStringFromTableInBundle( + @"close tab", + @"PDTabsView", + [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], + @"") + action:@selector(closeTargetedTab:) + keyEquivalent:@""] autorelease]; + + NSMenuItem *closeOtherTabsItem = [[[NSMenuItem alloc] + initWithTitle:NSLocalizedStringFromTableInBundle( + @"close other tabs", + @"PDTabsView", + [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], + @"") + action:@selector(closeOtherTabs:) + keyEquivalent:@""] autorelease]; + + [newTabItem setTarget:self]; + [closeTabItem setTarget:self]; + [closeOtherTabsItem setTarget:self]; + + [contextMenu addItem:newTabItem]; + [contextMenu addItem:closeTabItem]; + [contextMenu addItem:[NSMenuItem separatorItem]]; + [contextMenu addItem:closeOtherTabsItem]; + + [self setMenu:contextMenu]; + + // a default _tabFromTop of no means the tabs will draw from the bottom without programmatic change + _tabFromTop = YES; + + [self handleRegisterDragTypes]; + + [self setPostsBoundsChangedNotifications:YES]; + [self setPostsFrameChangedNotifications:YES]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_updateTrackingRects:) + name:NSViewBoundsDidChangeNotification + object:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_updateTrackingRects:) + name:NSViewFrameDidChangeNotification + object:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_toolbarDidChangeVisible:) + name:PDToolbarDidHideNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_toolbarDidChangeVisible:) + name:PDToolbarDidShowNotification + object:nil]; + + // clean up + [tempStyle release]; + } + return self; +} + +- (void) dealloc +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s", [self className], _cmd); + #endif + + [backgroundColor release]; + [_lastStillMoment release]; + + [morePop release]; + [popTitle release]; + + [tabCloseFront release]; + [tabCloseBack release]; + + [tabCloseFrontDown release]; + [tabCloseBackDown release]; + + [backRollover release]; + [frontRollover release]; + + //[totalImage release]; + + [contextMenu release]; + [titleTrackingRects release]; + [closeButtonTrackingRects release]; + + [self handleDeregisterDragTypes]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [super dealloc]; +} + +#pragma mark - + +- (id) delegate +{ + return delegate; +} + +- (void) setDelegate:(id)anObject +{ + delegate = anObject; +} + +- (id) dataSource +{ + return dataSource; +} + +- (void) setDataSource:(id)anObject +{ + dataSource = anObject; +} + +- (int) selectedTab +{ + return [[self dataSource] selectedTabIndexInTabView:self]; +} + +#pragma mark - + +- (int*) borders +{ + return borders; +} + +- (void) setBorders:(int*)theBorders +{ + borders[0] = theBorders[0]; + borders[1] = theBorders[1]; + borders[2] = theBorders[2]; + borders[3] = theBorders[3]; +} + +- (BOOL) tabFromTop +{ + return _tabFromTop; +} + +- (void) setTabFromTop:(BOOL)direction +{ + _tabFromTop = direction; +} + +- (BOOL) drawsShadow +{ + return drawsShadow; +} + +- (void) setDrawsShadow:(BOOL)shadow +{ + drawsShadow = shadow; +} + +- (int) availableWidth +{ + return availableWidth; +} + +- (void) setAvailableWidth:(int)tabWidth +{ + availableWidth = tabWidth; +} + +- (NSColor*) backgroundColor +{ + return backgroundColor; +} + +- (void) setBackgroundColor:(NSColor*)color +{ + if ( backgroundColor != color ) + { + [backgroundColor release]; + backgroundColor = [color copyWithZone:[self zone]]; + } +} + +#pragma mark - +#pragma mark Dragging & Autotabselecting + +- (void) handleRegisterDragTypes +{ + // how can I just register for everything under the sun? + [self registerForDraggedTypes:[NSArray arrayWithObjects: + kABPeopleUIDsPboardType, kMailMessagePboardType, NSFilenamesPboardType, kWebURLsWithTitlesPboardType, NSURLPboardType, + NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, NSTIFFPboardType, NSPICTPboardType, nil]]; + /* PDFolderIDPboardType, PDEntryIDPboardType, PDResourceIDPboardType, nil]]; */ +} + +- (void) handleDeregisterDragTypes +{ + [self unregisterDraggedTypes]; +} + +- (BOOL)performDragOperation:(id )sender +{ + return NO; +} + +- (unsigned int)dragOperationForDraggingInfo:(id )dragInfo type:(NSString *)type { + return NSDragOperationGeneric; +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + if ( [self isHidden] ) + return NSDragOperationNone; + + return NSDragOperationGeneric; +} + +- (void)draggingExited:(id )sender +{ + //we aren't particularily interested in this so we will do nothing + //this is one of the methods that we do not have to implement +} + +- (NSDragOperation)draggingUpdated:(id )sender +{ + + // + // - record the last point, set a time, invalidate the timer if it's already going + // + + NSPoint mouseLoc = [sender draggingLocation]; + NSPoint viewLoc = [self convertPoint:mouseLoc fromView:nil]; + + int i; + int overTab = 0; + + // calculate positional variables + int myX = viewLoc.x - kTabOffset; // 12 (kTabOffset) takes into account our self imposed left offset + //int myY = viewLoc.y; + + // calculate the tab visisble count + int tabsAvailable = ([self bounds].size.width - kTabOffset*2) / [self availableWidth]; + //int actualTabs = [[self displayText] count]; + int actualTabs = [dataSource numberOfTabsInTabView:self]; + int limit = ( tabsAvailable <= actualTabs ? tabsAvailable : actualTabs ); + + // do nothing if there is nothing to display + //if ( [self availableWidth] == 0 || [displayText count] == 1 ) + if ( [self availableWidth] == 0 || actualTabs == 1 ) + return NSDragOperationNone; + + // otherwise find out which tab the mouse is over + for ( i = 0; i < limit; i++ ) { + if ( myX > i * [self availableWidth] && myX < (i+1) * [self availableWidth] ) { + overTab = i; + break; + } + } + + // if the viewLoc is within the selected tab, do nothing + if ( overTab == [self selectedTab] || _amSwitching) + return NSDragOperationNone; + + // check the current viewLoc against the last viewLoc + if ( viewLoc.x == _lastViewLoc.x && viewLoc.y == _lastViewLoc.y ) { + + // how long has it been? + if ( [[NSDate date] timeIntervalSinceDate:_lastStillMoment] >= 0.5 ) { + + // if over 1 second, flash and select this tab + _amSwitching = YES; + _tabToSelect = overTab; + [self flashTab:overTab]; + + return NSDragOperationNone; + + } + else { + + return NSDragOperationGeneric; + + } + + } + else { + + // reset the last view loc + _lastViewLoc.x = viewLoc.x; + _lastViewLoc.y = viewLoc.y; + + [_lastStillMoment release]; + _lastStillMoment = [[NSDate date] retain]; + + return NSDragOperationGeneric; + + } + + return NSDragOperationGeneric; + +} + +- (BOOL)prepareForDragOperation:(id )sender +{ + return ( ![self isHidden] ); +} + +- (void)concludeDragOperation:(id )sender +{ + +} + +- (BOOL)ignoreModifierKeysWhileDragging +{ + return YES; +} + +#pragma mark - + +- (IBAction) newTab:(id)sender +{ + if ( [[self delegate] respondsToSelector:@selector(newTab:)] ) + [[self delegate] performSelector:@selector(newTab:) withObject:self]; + else + NSBeep(); +} + +- (void) closeTab:(int)tab +{ + NSRect invalidatedRect = [self frameOfTabAtIndex:tab]; + invalidatedRect.size.width = [self bounds].size.width - invalidatedRect.origin.x; + + // let the interested folks know what's up + if ( delegate != nil && [delegate respondsToSelector:@selector(tabsView:removedTabAtIndex:)] ) + [delegate tabsView:self removedTabAtIndex:tab]; + + hoverIndex = -1; + closeHoverIndex = -1; + + [self setNeedsDisplayInRect:invalidatedRect]; +} + +- (void) selectTab:(int)newSelection +{ + if ( [delegate respondsToSelector:@selector(selectedTabIndexInTabView:)] ) + { + NSRect previousRect = [self frameOfTabAtIndex:[[self delegate] selectedTabIndexInTabView:self]]; + [self setNeedsDisplayInRect:previousRect]; + } + + NSRect invalidatedRect = [self frameOfTabAtIndex:newSelection]; + + // let the interested folks know what's up + if ( delegate != nil && [delegate respondsToSelector:@selector(tabsView:selectedTabAtIndex:)] ) + [delegate tabsView:self selectedTabAtIndex:newSelection]; + + // invalidate these guys just for good measure + closeHoverIndex = -1; + [self setNeedsDisplayInRect:invalidatedRect]; +} + +#pragma mark - + +- (void) flashTab:(int)tab +{ + // + // uses a timer to flash a tab, thus drawing attention to it + // make sure there is any point to doing this + + // if the tab being flashed is the tab currently selected, beep + if ( tab == [self selectedTab] ) + { + NSBeep(); + return; + } + + _flashing = NO; + _malFlash = 0; + _flashingTab = tab; + + // fire off the timer + [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(flash:) userInfo:nil repeats:YES]; +} + +- (void) flash:(NSTimer*)timer +{ + + // invert the flash + _flashing = !_flashing; + + // invalidate the timer if this is the last time through + if ( _malFlash == 4 ) + { + _flashing = NO; + _flashingTab = -1; + + if ( _tabToSelect != -1 ) + [self selectTab:_tabToSelect]; + + _amSwitching = NO; + + [timer invalidate]; + return; + } + else + { + _malFlash++; + } + + [self setNeedsDisplayInRect:[self frameOfTabAtIndex:_tabToSelect]]; +} + + +#pragma mark - +#pragma mark Perform the drawing + +- (void)drawRect:(NSRect)rect +{ + + // + // responsible for producing the the appearance of a tabbed display + // - check the available width + // - correctly position the text and close buttons + // - properly render the selected tab + // + + int i; + int tabsAvailable; + int availableCellWidth; + + NSRect bds = [self bounds]; + + int tabCount = [dataSource numberOfTabsInTabView:self]; + if ( tabCount != 0 ) + { + availableCellWidth = ( bds.size.width - kTabOffset*2 ) / tabCount; + + if ( availableCellWidth > kMaxTabWidth ) availableCellWidth = kMaxTabWidth; + if ( availableCellWidth < kMinTabWidth ) availableCellWidth = kMinTabWidth; + + tabsAvailable = (bds.size.width - kTabOffset*2) / availableCellWidth; + + if ( tabsAvailable < tabCount ) + availableCellWidth = ( bds.size.width - 10 - kTabOffset*2 ) / tabsAvailable; + // an additional 10 pixels for the more indicator + + [self setAvailableWidth:availableCellWidth]; + } + else + { + [self setAvailableWidth:0]; + availableCellWidth = 0; + tabsAvailable = 0; + } + + //[totalImage setSize:bds.size]; + //[totalImage lockFocus]; + + //[[NSColor clearColor] set]; + //NSRectFillUsingOperation(bds, NSCompositeSourceOver); + + // fill with the label bar color + //[[NSColor windowBackgroundColor] set]; + [[NSColor colorWithCalibratedWhite:230.0/255.0 alpha:1.0] set]; + NSRectFillUsingOperation(bds, NSCompositeSourceOver); + + // draw a gradient over that + NSColor *gradientEnd = [NSColor colorWithCalibratedWhite:0.86 alpha:0.8]; //0.6 0.82 + NSColor *gradientStart = [NSColor colorWithCalibratedWhite:0.88 alpha:0.8]; // 0.92 + [[NSBezierPath bezierPathWithRect:bds] linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + NSColor *darkBorder = ( borders[0] == YES ? [NSColor darkGrayColor] : [[NSColor darkGrayColor] colorWithAlphaComponent:0.5] ); + NSColor *lightBorder = ( borders[0] == YES ? [NSColor colorWithCalibratedWhite:1.0 alpha:0.82] : [NSColor colorWithCalibratedWhite:1.0 alpha:0.4] ); + + if ( YES ) + { + NSGraphicsContext *context = [NSGraphicsContext currentContext]; + [context saveGraphicsState]; + [context setShouldAntialias:NO]; + + //[[NSColor darkGrayColor] set]; + [darkBorder set]; + [[NSBezierPath bezierPathWithLineFrom:NSMakePoint(0,bds.size.height-1) to:NSMakePoint(bds.size.width,bds.size.height-1) lineWidth:1] stroke]; + + //[[NSColor colorWithCalibratedWhite:1.0 alpha:0.9] set]; + [lightBorder set]; + [[NSBezierPath bezierPathWithLineFrom:NSMakePoint(0,bds.size.height-2) to:NSMakePoint(bds.size.width,bds.size.height-2) lineWidth:1] stroke]; + + [context restoreGraphicsState]; + } + + // forget what this is for + /* + NSImage *shadowBackground = [[[NSImage alloc] initWithSize:NSMakeSize(bds.size.width,bds.size.height)] autorelease]; + [shadowBackground lockFocus]; + + //[[NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0] set]; + [[NSColor colorWithCalibratedWhite:230.0/255.0 alpha:1.0] set]; + NSRectFillUsingOperation(bds, NSCompositeSourceOver); + + [shadowBackground unlockFocus]; + [shadowBackground drawInRect:bds fromRect:bds operation:NSCompositeSourceOver fraction:0.2]; + */ + + // frame ourselves with a shadow + + //NSShadow *shadow = nil; + + //[totalImage unlockFocus]; + + //[backgroundColor set]; + //NSRectFillUsingOperation(bds, NSCompositeSourceOver); + + // draw a gradient over that + //[[NSBezierPath bezierPathWithRect:bds] linearGradientFillWithStartColor:gradientStart endColor:gradientEnd]; + + // composite the tab image on top if it all - seems wasteful + //[totalImage compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; + + // run through the available titles until we can go no further,drawing the titles and the associated close buttons + for ( i = 0; i < tabCount; i++ ) + { + if ( (i+1) * availableCellWidth <= bds.size.width - kTabOffset*2 ) + { + if ( _flashing && _flashingTab == i ) + { + + // redraw the background if we're flashing + [[NSColor colorWithCalibratedRed:0.6 green:0.6 blue:0.6 alpha:0.5] set]; + NSRectFillUsingOperation(NSMakeRect(i * availableCellWidth + kTabOffset, 1, availableCellWidth - 1, bds.size.height - 2 ), NSCompositeSourceOver); + + /* + NSRect hoverRect = NSMakeRect(i * availableCellWidth + kTabOffset + 1, 2, availableCellWidth - 1 - 2, 17 ); + NSBezierPath *aPath = [NSBezierPath bezierPathWithRoundedRect:hoverRect cornerRadius:8.0]; + + [[NSColor colorWithCalibratedRed:0.45 green:0.45 blue:0.45 alpha:1.0] set]; + [aPath fill]; + */ + } + + else if ( i == hoverIndex ) + { + // height = 22 + // stateRect.origin.x+=1; stateRect.origin.y+=2; stateRect.size.width-=1; stateRect.size.height-=5; + + [[NSColor colorWithCalibratedWhite:0.9 alpha:0.9] set]; + NSRectFillUsingOperation( NSMakeRect( i * availableCellWidth + ( hoverIndex == 0 ? 0 : kTabOffset ), + 0, + availableCellWidth - 1 + ( hoverIndex == 0 ? kTabOffset : 0 ), + bds.size.height -1 ) + , NSCompositeSourceOver); + + /* + NSRect hoverRect = NSMakeRect(i * availableCellWidth + kTabOffset + 1, 2, availableCellWidth - 1 - 2, 17 ); + NSBezierPath *aPath = [NSBezierPath bezierPathWithRoundedRect:hoverRect cornerRadius:8.0]; + + if ( i != selectingIndex ) + [[NSColor colorWithCalibratedRed:0.6 green:0.6 blue:0.6 alpha:1.0] set]; + else + [[NSColor colorWithCalibratedRed:0.45 green:0.45 blue:0.45 alpha:1.0] set]; + + [aPath fill]; + */ + } + + // draw the title identifying this tab + NSString *theTitle = [dataSource tabsView:self titleForTabAtIndex:i]; + theTitle = ( theTitle != nil ? theTitle : [NSString string] ); + + NSMutableAttributedString *drawString = [[[[NSAttributedString alloc] + initWithString:theTitle attributes:TitleAttributes()] mutableCopyWithZone:[self zone]] autorelease]; + + if ( /* i == hoverIndex || */ ( _flashing == YES && _flashingTab == i ) ) + [drawString addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0,[drawString length])]; + else if ( i == [self selectedTab] ) + [drawString addAttribute:NSForegroundColorAttributeName value:[NSColor blackColor] range:NSMakeRange(0,[drawString length])]; + + int left; + if ( tabCount == 1 ) + left = 22; + else + left = i * availableCellWidth + 36; + + float heightOffset = kLabelOffset; + NSRect drawRect = NSMakeRect( left - 2, heightOffset, availableCellWidth - 36, [NSFont smallSystemFontSize]+4 ); + // + 30 : space for an initial tab, space for the close button + // initial space is 12 (kTabOffset) + + [drawString drawInRect:drawRect]; + + //if ( !(i == hoverIndex || i == hoverIndex-1) ) + { + // draw the separator + [[NSGraphicsContext currentContext] saveGraphicsState]; + [[NSGraphicsContext currentContext] setShouldAntialias:NO]; + + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.15] set]; + [[NSBezierPath bezierPathWithLineFrom:NSMakePoint((i+1) * availableCellWidth + kTabOffset - 1, 1) /*2*/ + to:NSMakePoint((i+1) * availableCellWidth + kTabOffset - 1,[self bounds].size.height - 3) lineWidth:1.0] stroke]; /*4*/ + + [[NSGraphicsContext currentContext] restoreGraphicsState]; + } + + // draw the close button for this tab, but only if there is more than one tab + if ( tabCount != 1 ) + { + NSImage *closeButton; + + if ( i == closeDown ) + closeButton = ( i == [self selectedTab] ? tabCloseFrontDown : tabCloseBackDown ); + else + { + if ( i == /*hoverIndex*/ closeHoverIndex ) + //closeButton = ( i == [self selectedTab] ? frontRollover : backRollover ); + closeButton = backRollover; + else + closeButton = ( i == [self selectedTab] ? tabCloseFront : tabCloseBack ); + //closeButton = tabCloseBack; + } + + float closeHeightOffset = kCloseOffset; + NSRect closeRect = NSMakeRect( i * availableCellWidth + 17 - 1, closeHeightOffset, [closeButton size].width, [closeButton size].height ); + + [closeButton drawInRect:closeRect fromRect:NSMakeRect(0,0,[closeButton size].width, [closeButton size].height) + operation:NSCompositeSourceOver fraction:1.0]; + } + + if ( i == tabCount - 1 && ![morePop isHidden] ) + [morePop setHidden:YES]; + } + else + { + // once we hit this point, we need to indicate that more tabs are available + // and then break out of the loop so that we don't repeat this code + + if ( _flashing && _flashingTab >= i ) + { + // redraw the background if we're flashing + NSRect popFrame = [morePop frame]; + + popFrame.origin.x+=6; + popFrame.origin.y-=3; + popFrame.size.width-=8; + popFrame.size.height+=8; + + [[NSColor colorWithCalibratedRed:0.6 green:0.6 blue:0.6 alpha:0.5] set]; + + NSRectFillUsingOperation(popFrame, NSCompositeSourceOver); + } + + // clean our the menu and rebuild it + [morePop removeAllItems]; + [[morePop menu] addItem:popTitle]; + + int rt; + for ( rt = i; rt < tabCount - 1; rt++ ) + { + NSString *theTitle = [dataSource tabsView:self titleForTabAtIndex:rt]; + theTitle = ( theTitle != nil ? theTitle : [NSString string] ); + + NSMenuItem *anItem = [[[NSMenuItem alloc] initWithTitle:theTitle + action:@selector(selectTabByPop:) + keyEquivalent:@""] autorelease]; + + [[morePop menu] addItem:anItem]; + } + + [morePop setHidden:NO]; + + break; + } + } + + // add the tracking rects if the tab count differs + if ( lastTabCount != tabCount ) + { + [self updateTrackingRects]; + lastTabCount = tabCount; + } +} + +- (NSRect) frameOfTabAtIndex:(int)theIndex +{ + + if ( [[self delegate] respondsToSelector:@selector(numberOfTabsInTabView:)] && theIndex != -1 ) + { + if ( theIndex >= [[self delegate] numberOfTabsInTabView:self] ) + { + //NSLog(@"%@ %s - index %i is greater than avaible count %i", [self className], _cmd, theIndex, [[self delegate] numberOfTabsInTabView:self] - 1 ); + return NSZeroRect; + } + else + { + return NSMakeRect(theIndex * [self availableWidth] + (theIndex == 0 ? 0 : kTabOffset ), 0, + [self availableWidth] + ( theIndex == 0 ? kTabOffset : 0 ), [self bounds].size.height ); + } + } + else + { + return NSZeroRect; + } +} + +- (NSRect) frameOfCloseButtonAtIndex:(int)theIndex +{ + if ( [[self delegate] respondsToSelector:@selector(numberOfTabsInTabView:)] && theIndex != -1 ) + { + if ( theIndex >= [[self delegate] numberOfTabsInTabView:self] ) + { + //NSLog(@"%@ %s - index %i is greater than avaible count %i", [self className], _cmd, theIndex, [[self delegate] numberOfTabsInTabView:self] - 1 ); + return NSZeroRect; + } + else + { + return NSMakeRect( theIndex * [self availableWidth] + 17 - 1, + kCloseOffset, + [backRollover size].width, + [backRollover size].height ); + } + } + else + { + return NSZeroRect; + } +} + +#pragma mark - +#pragma mark Tracking + +- (void) updateTrackingRects +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + int i; + int tabsAvailable; + int availableCellWidth; + + NSRect bds = [self bounds]; + int tabCount = [dataSource numberOfTabsInTabView:self]; + + // remove the previous tooltips + [self removeAllToolTips]; + + // remove the previous tracking rectangles + for ( i = 0; i < [titleTrackingRects count]; i++ ) + [self removeTrackingRect:[[titleTrackingRects objectAtIndex:i] intValue]]; + for ( i = 0; i < [closeButtonTrackingRects count]; i++ ) + [self removeTrackingRect:[[closeButtonTrackingRects objectAtIndex:i] intValue]]; + + [titleTrackingRects removeAllObjects]; + [closeButtonTrackingRects removeAllObjects]; + + if ( tabCount != 0 ) + { + availableCellWidth = ( bds.size.width - kTabOffset*2 ) / tabCount; + + if ( availableCellWidth > kMaxTabWidth ) availableCellWidth = kMaxTabWidth; + if ( availableCellWidth < kMinTabWidth ) availableCellWidth = kMinTabWidth; + + tabsAvailable = (bds.size.width - kTabOffset*2) / availableCellWidth; + + if ( tabsAvailable < tabCount ) + availableCellWidth = ( bds.size.width - 10 - kTabOffset*2 ) / tabsAvailable; + // an additional 10 pixels for the more indicator + } + else + { + availableCellWidth = 0; + tabsAvailable = 0; + } + + + // run through the available titles until we can go no further,drawing the titles and the associated close buttons + for ( i = 0; i < tabCount; i++ ) + { + if ( (i+1) * availableCellWidth <= bds.size.width - kTabOffset*2 ) + { + + int left; + if ( tabCount == 1 ) + left = 18; + else + left = i * availableCellWidth + 36; + + float heightOffset = kLabelOffset; + + NSRect tooltipRect = NSMakeRect( left, heightOffset, availableCellWidth - 36, 17 ); + NSRect drawRect = NSMakeRect(i * availableCellWidth + kTabOffset + 4, 2, availableCellWidth - 1 - 8, 17 ); + + NSTrackingRectTag aTrackingRect = [self addTrackingRect:drawRect owner:self userData:nil assumeInside:NO]; + [titleTrackingRects addObject:[NSNumber numberWithInt:aTrackingRect]]; + + if ( [[self delegate] respondsToSelector:@selector(tabsView:titleForTabAtIndex:)] ) + [self addToolTipRect:tooltipRect owner:[[[self delegate] tabsView:self titleForTabAtIndex:i] retain] userData:nil]; + + // + 30 : space for an initial tab, space for the close button + // initial space is 12 (kTabOffset) + + // draw the close button for this tab, but only if there is more than one tab + if ( tabCount != 1 ) + { + float closeHeightOffset = kCloseOffset; + NSRect closeRect = NSMakeRect( i * availableCellWidth + 17, closeHeightOffset, [tabCloseFrontDown size].width, [tabCloseFrontDown size].height ); + + [self addToolTipRect:closeRect owner: + [NSLocalizedStringFromTableInBundle(@"close tab tip", @"PDTabsView", [NSBundle bundleWithIdentifier:@"com.sprouted.interface"], @"") retain] userData:nil]; + + NSTrackingRectTag aTrackingRect = [self addTrackingRect:closeRect owner:self userData:nil assumeInside:NO]; + [closeButtonTrackingRects addObject:[NSNumber numberWithInt:aTrackingRect]]; + } + } + else + { + // once we hit this point, we need to indicate that more tabs are available + // and then break out of the loop so that we don't repeat this code + + if ( _flashing && _flashingTab >= i ) + { + // redraw the background if we're flashing + NSRect popFrame = [morePop frame]; + + popFrame.origin.x+=6; + popFrame.origin.y-=3; + popFrame.size.width-=8; + popFrame.size.height+=8; + } + + break; + } + } + +} + +- (void) _updateTrackingRects:(NSNotification*)aNotification +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + [self updateTrackingRects]; +} + +- (void) _toolbarDidChangeVisible:(NSNotification*)aNotification +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( [[self window] toolbar] == [aNotification object] ) + [self updateTrackingRects]; +} + +#pragma mark - + +- (void)mouseEntered:(NSEvent *)theEvent +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + int i; + BOOL forceHoverUpdate = NO; + NSTrackingRectTag trackTag = [theEvent trackingNumber]; + + // first check for a match with the close button + + for ( i = 0; i < [closeButtonTrackingRects count]; i++ ) + { + if ( trackTag == [[closeButtonTrackingRects objectAtIndex:i] intValue] ) + { + closeHoverIndex = i; + if ( hoverIndex != closeHoverIndex ) + { + forceHoverUpdate = YES; + hoverIndex = i; + } + } + } + + // then check for a match with the whole thing + if ( hoverIndex == -1 ) + { + for ( i = 0; i < [titleTrackingRects count]; i++ ) + { + if ( trackTag == [[titleTrackingRects objectAtIndex:i] intValue] ) + { + hoverIndex = i; + forceHoverUpdate = YES; + } + } + } + + if ( closeHoverIndex != -1 ) + { + #ifdef __DEBUG__ + NSLog(@"%@ %s - hovering at %i", [self className], _cmd, closeHoverIndex); + #endif + + NSRect invalidatedRect = [self frameOfCloseButtonAtIndex:closeHoverIndex]; + invalidatedRect.origin.x-=1; invalidatedRect.size.width+=2; + [self setNeedsDisplayInRect:invalidatedRect]; + } + + if ( hoverIndex != -1 && forceHoverUpdate ) + { + #ifdef __DEBUG__ + NSLog(@"%@ %s - hovering at %i", [self className], _cmd, hoverIndex); + #endif + + NSRect invalidatedRect = [self frameOfTabAtIndex:hoverIndex]; + invalidatedRect.origin.x-=1; invalidatedRect.size.width+=2; + [self setNeedsDisplayInRect:invalidatedRect]; + } +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + #ifdef __DEBUG__ + NSLog(@"%@ %s",[self className],_cmd); + #endif + + if ( [[self delegate] respondsToSelector:@selector(numberOfTabsInTabView:)] + && closeHoverIndex != -1 && closeHoverIndex < [[self delegate] numberOfTabsInTabView:self] ) + { + NSRect invalidatedRect = [self frameOfCloseButtonAtIndex:closeHoverIndex]; + invalidatedRect.origin.x-=1; invalidatedRect.size.width+=2; + [self setNeedsDisplayInRect:invalidatedRect]; + + closeHoverIndex = -1; + } + + else if ( [[self delegate] respondsToSelector:@selector(numberOfTabsInTabView:)] + && hoverIndex != -1 && hoverIndex < [[self delegate] numberOfTabsInTabView:self] ) + { + NSRect invalidatedRect = [self frameOfTabAtIndex:hoverIndex]; + invalidatedRect.origin.x-=1; invalidatedRect.size.width+=2; + [self setNeedsDisplayInRect:invalidatedRect]; + + hoverIndex = -1; + } + +} + + +#pragma mark - + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + // converts the event into a tab selection or close and + // sends ourself the message + + BOOL clickedInEmptySpace = YES; + BOOL closing = NO; + int i; + + // mouse location and x coordinates + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + int myX = mouseLoc.x - kTabOffset; // 12 (kTabOffset) takes into account our self imposed left offset + int myY = mouseLoc.y; + + int actualTabs = [dataSource numberOfTabsInTabView:self]; + + // do nothing if there is nothing to display + if ( [self availableWidth] == 0 ) + { + return; + } + else if ( actualTabs == 1 ) + { + // bail unless the user double-clicked outside of the tab's area + if ( myX > 1 * [self availableWidth] + && myX < [self bounds].size.width - 30 + && [theEvent clickCount] > 1 + && [[self delegate] respondsToSelector:@selector(newTab:)] ) + { + // create and select the new tab + [[self delegate] performSelector:@selector(newTab:) withObject:self]; + [self selectTab:[dataSource numberOfTabsInTabView:self]-1]; + } + else + { + return; + } + } + else + { + int tabsAvailable = ([self bounds].size.width - kTabOffset*2) / [self availableWidth]; + int limit = ( tabsAvailable <= actualTabs ? tabsAvailable : actualTabs ); + + // selecting within a close box + + for ( i = 0; i < limit; i++ ) + { + if ( myX >= i * [self availableWidth] + 5 && myX <= i * [self availableWidth] + 5 + [tabCloseFront size].width + && myY >= kCloseOffset && myY <= kCloseOffset + [tabCloseFront size].height ) + { + // enter my own even loop until we have some kind of result + BOOL keepOn = YES; + BOOL isInside = YES; + NSPoint mouseLoc; + + NSRect invalidatedRect; + NSRect innenRect = NSMakeRect(i * [self availableWidth] + 17, kCloseOffset, [tabCloseFront size].width, [tabCloseFront size].height); + + closeDown = i; + clickedInEmptySpace = NO; + + [self displayRect:[self frameOfTabAtIndex:i]]; + + while (keepOn) + { + theEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask]; + + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + isInside = [self mouse:mouseLoc inRect:innenRect]; + + switch ([theEvent type]) + { + case NSLeftMouseDragged: + invalidatedRect = [self frameOfTabAtIndex:i]; + closeDown = ( isInside ? i : -1 ); + [self displayRect:invalidatedRect]; + break; + + case NSLeftMouseUp: + invalidatedRect = [self frameOfTabAtIndex:i]; + if (isInside) [self closeTab:i]; + closeDown = -1; + [self displayRect:invalidatedRect]; + keepOn = NO; + + break; + default: + /* Ignore any other kind of event. */ + break; + } + }; + + //[self setNeedsDisplay:YES]; + closing = YES; + } + } + + // basic tab selection + if ( !closing ) + { + for ( i = 0; i < limit; i++ ) + { + if ( myX > i * [self availableWidth] && myX < (i+1) * [self availableWidth] ) + { + // do not process this if this tab is already selected + if ( i != [self selectedTab] ) + { + selectingIndex = i; + NSRect hoverRect = NSMakeRect(selectingIndex * [self availableWidth] + kTabOffset, 2, [self availableWidth] - 1, 17 ); + [self setNeedsDisplayInRect:hoverRect]; + [self selectTab:i]; + } + + clickedInEmptySpace = NO; + break; + } + } + + closeDown = -1; + } + + // clicked in empty space, clicked count > 1, new delegate wants new tabs + if ( clickedInEmptySpace == YES + && myX < [self bounds].size.width - 30 + && [theEvent clickCount] > 1 + && [[self delegate] respondsToSelector:@selector(newTab:)] ) + { + // create and select the new tab + [[self delegate] performSelector:@selector(newTab:) withObject:self]; + [self selectTab:[dataSource numberOfTabsInTabView:self]-1]; + } + } +} + +#pragma mark - + +- (void)mouseUp:(NSEvent *)theEvent +{ + NSRect hoverRect = NSMakeRect(selectingIndex * [self availableWidth] + kTabOffset, 2, [self availableWidth] - 1, 17 ); + selectingIndex = -1; + [self setNeedsDisplayInRect:hoverRect]; +} + +- (IBAction) selectTabByPop:(id)sender +{ + int tabsAvailable = ([self bounds].size.width - kTabOffset*2) / [self availableWidth]; + int selectedItem = [morePop indexOfSelectedItem]; + + int tabToSelect = tabsAvailable + selectedItem - 1; + + [self selectTab:tabToSelect]; +} + +#pragma mark - + +- (NSMenu *)menuForEvent:(NSEvent *)theEvent +{ + _targetTabForContext = -1; + + NSPoint local_point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + int i, limit, tabsAvailable, actualTabs; + int myX = local_point.x - kTabOffset; + + actualTabs = [[self dataSource] numberOfTabsInTabView:self]; + + // do nothing if there is nothing to display + if ( [self availableWidth] == 0 || actualTabs == 1 ) + return [super menuForEvent:theEvent]; + + tabsAvailable = ([self bounds].size.width - kTabOffset*2) / [self availableWidth]; + limit = ( tabsAvailable <= actualTabs ? tabsAvailable : actualTabs ); + + for ( i = 0; i < limit; i++ ) + { + if ( myX > i * [self availableWidth] && myX < (i+1) * [self availableWidth] ) + { + _targetTabForContext = i; + break; + } + } + + return [super menuForEvent:theEvent]; +} + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + BOOL enabled = YES; + SEL action = [menuItem action]; + + if ( action == @selector(newTab:) ) + enabled = [[self delegate] respondsToSelector:@selector(newTab:)]; + else if ( action == @selector(closeTargetedTab:) ) + enabled = ( [[self dataSource] numberOfTabsInTabView:self] != 1 && _targetTabForContext != -1 ); + else if ( action == @selector(closeOtherTabs:) ) + enabled = ( [[self dataSource] numberOfTabsInTabView:self] != 1 && _targetTabForContext != -1 ); + + return enabled; +} + +- (IBAction) closeTargetedTab:(id)sender +{ + if ( _targetTabForContext == - 1 ) + { + NSBeep(); return; + } + + [self closeTab:_targetTabForContext]; + _targetTabForContext = -1; +} + +- (IBAction) closeOtherTabs:(id)sender +{ + if ( _targetTabForContext == - 1 ) + { + NSBeep(); return; + } + + int i; + int numTabs = [[self dataSource] numberOfTabsInTabView:self]; + + // close the tabs behind + for ( i = numTabs - 1; i > _targetTabForContext; i-- ) + [self closeTab:i]; + + // close the tabs in front + for ( i = 0; i < _targetTabForContext; i++ ) + [self closeTab:0]; + + _targetTabForContext = -1; +} + +- (void)viewDidMoveToWindow +{ + if ( [self window] != nil ) + [self updateTrackingRects]; +} + +@end diff --git a/PDTokenField.h b/PDTokenField.h new file mode 100644 index 0000000..b21e52f --- /dev/null +++ b/PDTokenField.h @@ -0,0 +1,25 @@ +// +// PDTokenField.h +// SproutedInterface +// +// Created by Philip Dow on 8/20/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Note that PDTokenField does not require PDTokenFieldCell +// + +#import + + +@interface PDTokenField : NSTokenField { + +} + +@end + +@interface NSObject (PDTokenFieldDelegate) + +- (void)tokenField:(PDTokenField *)tokenField didReadTokens:(NSArray*)theTokens fromPasteboard:(NSPasteboard *)pboard; + +@end \ No newline at end of file diff --git a/PDTokenField.m b/PDTokenField.m new file mode 100644 index 0000000..f0b6b3f --- /dev/null +++ b/PDTokenField.m @@ -0,0 +1,45 @@ +// +// PDTokenField.m +// SproutedInterface +// +// Created by Philip Dow on 8/20/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Note that PDTokenField does not require PDTokenFieldCell +// + +#import + + +@implementation PDTokenField + +- (BOOL)performDragOperation:(id )sender +{ + if ([super performDragOperation:sender]) + { + //NSLog(@"perform custom drag operation"); + + if ( [self delegate] != nil && [[self delegate] respondsToSelector:@selector(tokenField:didReadTokens:fromPasteboard:)] ) + [[self delegate] tokenField:self didReadTokens:[self objectValue] fromPasteboard:[sender draggingPasteboard]]; + + return YES; + } + else + { + return NO; + } +} + +-(NSArray *)tokenFieldCell:(NSTokenFieldCell *)tokenFieldCell readFromPasteboard:(NSPasteboard *)pboard +{ + id tokens = [super tokenFieldCell:tokenFieldCell readFromPasteboard:pboard]; + + if ( [self delegate] != nil && [[self delegate] respondsToSelector:@selector(tokenField:didReadTokens:fromPasteboard:)] ) + [[self delegate] tokenField:self didReadTokens:tokens fromPasteboard:pboard]; + + return tokens; +} + + +@end diff --git a/PDTokenFieldCell.h b/PDTokenFieldCell.h new file mode 100644 index 0000000..e1bd353 --- /dev/null +++ b/PDTokenFieldCell.h @@ -0,0 +1,31 @@ +// +// PDTokenFieldCell.h +// SproutedInterface +// +// Created by Philip Dow on 7/16/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Note that PDTokenFieldCell does not require PDTokenField +// + +#import + + +@interface PDTokenFieldCell : NSTokenFieldCell { + +} + +@end + +@interface NSTokenFieldCell (SuperImplemented) + +- (id) _tokensFromPasteboard:(id)fp8; + +@end + +@interface NSObject (PDTokenFieldCellDelegate) + +- (void)tokenFieldCell:(PDTokenFieldCell *)tokenFieldCell didReadTokens:(NSArray*)theTokens fromPasteboard:(NSPasteboard *)pboard; + +@end \ No newline at end of file diff --git a/PDTokenFieldCell.m b/PDTokenFieldCell.m new file mode 100644 index 0000000..496c197 --- /dev/null +++ b/PDTokenFieldCell.m @@ -0,0 +1,67 @@ +// +// PDTokenFieldCell.m +// SproutedInterface +// +// Created by Philip Dow on 7/16/07. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Note that PDTokenFieldCell does not require PDTokenField +// + +#import + + +@implementation PDTokenFieldCell + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + //NSLog(@"%@ %s view is a %@",[self className],_cmd,[controlView className]); + + [self setControlSize:NSSmallControlSize]; + [super drawWithFrame:cellFrame inView:controlView]; +} + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + //NSLog(@"%@ %s view is a %@",[self className],_cmd,[controlView className]); + + // a small adjustment if we're running 10.4 but not 10.5 + if ( ![self respondsToSelector:@selector(scriptingValueForSpecifier:)] ) + cellFrame.origin.y -= 1; + + [self setControlSize:NSSmallControlSize]; + [super drawInteriorWithFrame:cellFrame inView:controlView]; +} + +#pragma mark - +#pragma mark Fixes for Bindings Problem with Dragging & Copy/Paste + +- (BOOL)performDragOperation:(id )sender +{ + if ([super performDragOperation:sender]) + { + //NSLog(@"perform custom drag operation"); + + if ( [self delegate] != nil && [[self delegate] respondsToSelector:@selector(tokenFieldCell:didReadTokens:fromPasteboard:)] ) + [[self delegate] tokenFieldCell:self didReadTokens:[self objectValue] fromPasteboard:[sender draggingPasteboard]]; + + return YES; + } + else + { + return NO; + } +} + +- (id) _tokensFromPasteboard:(id)fp8 +{ + id tokens = [super _tokensFromPasteboard:fp8]; + + if ( [self delegate] != nil && [[self delegate] respondsToSelector:@selector(tokenFieldCell:didReadTokens:fromPasteboard:)] ) + [[self delegate] tokenFieldCell:self didReadTokens:tokens fromPasteboard:fp8]; + + return tokens; +} + +@end diff --git a/PDToolbar.h b/PDToolbar.h new file mode 100644 index 0000000..f2a80f7 --- /dev/null +++ b/PDToolbar.h @@ -0,0 +1,32 @@ +// +// PDDelegatedToolbar.h +// SproutedInterface +// +// Created by Philip Dow on 12/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define PDToolbarDidShowNotification @"PDToolbarDidShowNotification" +#define PDToolbarDidHideNotification @"PDToolbarDidHideNotification" + +@interface PDToolbar : NSToolbar { + +} + +- (NSToolbarItem*) itemWithTag:(int)aTag; +- (NSToolbarItem*) itemWithIdentifier:(NSString*)identifier; + +@end + +@interface NSObject (PDToolbarDelegate) + +- (void) toolbarDidChangeSizeMode:(PDToolbar*)aToolbar; +- (void) toolbarDidChangeDisplayMode:(PDToolbar*)aToolbar; + +- (void) toolbarDidShow:(PDToolbar*)aToolbar; +- (void) toolbarDidHide:(PDToolbar*)aToolbar; + +@end \ No newline at end of file diff --git a/PDToolbar.m b/PDToolbar.m new file mode 100644 index 0000000..766febd --- /dev/null +++ b/PDToolbar.m @@ -0,0 +1,85 @@ +// +// PDDelegatedToolbar.m +// SproutedInterface +// +// Created by Philip Dow on 12/1/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation PDToolbar + +- (NSToolbarItem*) itemWithTag:(int)aTag +{ + NSToolbarItem *anItem, *theItem = nil; + NSEnumerator *enumerator = [[self items] objectEnumerator]; + + while ( anItem = [enumerator nextObject] ) + { + if ( [anItem tag] == aTag ) + { + theItem = anItem; + break; + } + } + + return theItem; +} + +- (NSToolbarItem*) itemWithIdentifier:(NSString*)identifier +{ + NSToolbarItem *anItem, *theItem = nil; + NSEnumerator *enumerator = [[self items] objectEnumerator]; + + while ( anItem = [enumerator nextObject] ) + { + if ( [[anItem itemIdentifier] isEqualToString:identifier] ) + { + theItem = anItem; + break; + } + } + + return theItem; +} + +#pragma mark - + +- (void)setDisplayMode:(NSToolbarDisplayMode)displayMode +{ + [super setDisplayMode:displayMode]; + if ( [[self delegate] respondsToSelector:@selector(toolbarDidChangeDisplayMode:)] ) + [[self delegate] toolbarDidChangeDisplayMode:self]; +} + +- (void)setSizeMode:(NSToolbarSizeMode)sizeMode +{ + [super setSizeMode:sizeMode]; + if ( [[self delegate] respondsToSelector:@selector(toolbarDidChangeSizeMode:)] ) + [[self delegate] toolbarDidChangeSizeMode:self]; + +} + +- (void)setVisible:(BOOL)shown +{ + [super setVisible:shown]; + + if ( shown ) + [[NSNotificationCenter defaultCenter] postNotificationName:PDToolbarDidShowNotification + object:self + userInfo:nil]; + else + [[NSNotificationCenter defaultCenter] postNotificationName:PDToolbarDidHideNotification + object:self + userInfo:nil]; + + if (shown && [[self delegate] respondsToSelector:@selector(toolbarDidShow:)] ) + [[self delegate] toolbarDidShow:self]; + else if ( !shown && [[self delegate] respondsToSelector:@selector(toolbarDidHide:)] ) + [[self delegate] toolbarDidHide:self]; +} + +@end diff --git a/PDURLTextField.h b/PDURLTextField.h new file mode 100644 index 0000000..52e3082 --- /dev/null +++ b/PDURLTextField.h @@ -0,0 +1,29 @@ +// +// PDURLTextField.h +// SproutedInterface +// +// Created by Philip Dow on 5/28/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@interface PDURLTextField : NSTextField { + + NSString *_url_title; +} + ++ (NSImage*) defaultImage; + +- (NSString*)URLTitle; +- (void) setURLTitle:(NSString*)aTitle; + +- (NSImage*) image; +- (void) setImage:(NSImage*)anImage; + +- (double) estimatedProgress; +- (void) setEstimatedProgress:(double)estimate; + +@end diff --git a/PDURLTextField.m b/PDURLTextField.m new file mode 100644 index 0000000..848269c --- /dev/null +++ b/PDURLTextField.m @@ -0,0 +1,163 @@ +// +// PDURLTextField.m +// SproutedInterface +// +// Created by Philip Dow on 5/28/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import +#import +#import + +#define kWebURLsWithTitlesPboardType @"WebURLsWithTitlesPboardType" + +static NSString *kFileURLIdentifier = @"file://"; + +@implementation PDURLTextField + + +- (id)initWithCoder:(NSCoder *)decoder { + + if ( self = [super initWithCoder:decoder] ) { + + NSArchiver * anArchiver = [[[NSArchiver alloc] + initForWritingWithMutableData:[NSMutableData dataWithCapacity: 256]] autorelease]; + [anArchiver encodeClassName:@"NSTextFieldCell" intoClassName:@"PDURLTextFieldCell"]; + [anArchiver encodeRootObject:[self cell]]; + [self setCell:[NSUnarchiver unarchiveObjectWithData:[anArchiver archiverData]]]; + + _url_title = [[NSString alloc] init]; + [self setImage:[PDURLTextField defaultImage]]; + + } + + return self; +} + + ++ (Class) cellClass +{ + return [PDURLTextFieldCell class]; +} + +- (void) dealloc { + [_url_title release]; + _url_title = nil; + [super dealloc]; +} + +#pragma mark - + ++ (NSImage*) defaultImage +{ + return BundledImageWithName(@"PDURLTextFieldWebDefault.tiff", @"com.sprouted.interface"); +} + + +- (void)setStringValue:(NSString *)aString { + [super setStringValue:aString]; + if ( [[self stringValue] rangeOfString:kFileURLIdentifier options:NSCaseInsensitiveSearch].location == 0 ) + [self setImage:BundledImageWithName(@"PDURLTextFieldFileDefault.png", @"com.sprouted.interface")]; + [self setURLTitle:nil]; +} + +- (void)setObjectValue:(id )object +{ + [super setObjectValue:object]; + if ( [[self stringValue] rangeOfString:kFileURLIdentifier options:NSCaseInsensitiveSearch].location == 0 ) + [self setImage:BundledImageWithName(@"PDURLTextFieldFileDefault.png", @"com.sprouted.interface")]; + [self setURLTitle:nil]; +} + +- (NSString*)URLTitle { + if (_url_title != nil && [_url_title length] != 0 ) + return _url_title; + else + return [self stringValue]; +} + +- (void) setURLTitle:(NSString*)aTitle { + if ( _url_title != aTitle ) { + [_url_title release]; + _url_title = [aTitle copyWithZone:[self zone]]; + } +} + +- (NSImage*) image { return [[self cell] image]; } + +- (void) setImage:(NSImage*)anImage { + [[self cell] setImage:anImage]; +} + +- (double) estimatedProgress { return [[self cell] estimatedProgress]; } + +- (void) setEstimatedProgress:(double)estimate { + [[self cell] setEstimatedProgress:estimate]; + [self setNeedsDisplay:YES]; +} + +#pragma mark - + +- (void)mouseDragged:(NSEvent *)theEvent +{ + static int kTextOffest = 4.0; + + // do not execute a drag if there is nothing to drag + if ( [self stringValue] == nil || [[self stringValue] length] == 0 ) return; + + NSPoint image_location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + + NSImage *my_image = [[self image] copyWithZone:[self zone]];; + NSString *drag_title = [self URLTitle]; + if ( !drag_title || [drag_title length] == 0 ) drag_title = [self stringValue]; + + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [self font], NSFontAttributeName, + [NSColor colorWithCalibratedWhite:0.2 alpha:1.0], NSForegroundColorAttributeName, nil]; + + NSSize image_size = [my_image size]; + NSSize title_size = [drag_title sizeWithAttributes:attributes]; + NSSize total_size = NSMakeSize( (image_size.width + kTextOffest + title_size.width), + (image_size.height > title_size.height ? image_size.height : title_size.height) ); + + NSSize drag_offset = NSMakeSize(image_size.width/2, image_size.height/2); + image_location.x -= drag_offset.width; + image_location.y += drag_offset.height; + + NSImage *drag_image = [[NSImage alloc] initWithSize:total_size]; + [my_image setFlipped:[drag_image isFlipped]]; + + [drag_image lockFocus]; + + [my_image compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; + [drag_title drawAtPoint:NSMakePoint(image_size.width+kTextOffest,0) withAttributes:attributes]; + + [drag_image unlockFocus]; + + NSArray *types = [NSArray arrayWithObjects: + kWebURLsWithTitlesPboardType, NSURLPboardType, nil]; + + NSURL *url = [NSURL URLWithString:[self stringValue]]; + + NSArray *url_array = [NSArray arrayWithObjects:[self stringValue],nil]; + NSArray *title_array = [NSArray arrayWithObjects:drag_title, nil]; + NSArray *web_urls_array = [NSArray arrayWithObjects:url_array,title_array,nil]; + + [pboard declareTypes:types owner:self]; + + [pboard setPropertyList:web_urls_array forType:kWebURLsWithTitlesPboardType]; + [url writeToPasteboard:pboard]; + + [self dragImage:drag_image at:image_location offset:NSMakeSize(0.0,0.0) + event:theEvent pasteboard:pboard source:self slideBack:YES]; + + [my_image release]; + [drag_image release]; + + return; +} + +@end diff --git a/PDURLTextFieldCell.h b/PDURLTextFieldCell.h new file mode 100644 index 0000000..441c92b --- /dev/null +++ b/PDURLTextFieldCell.h @@ -0,0 +1,43 @@ +// +// PDURLTextFieldCell.h +// SproutedInterface +// +// Created by Philip Dow on 5/28/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +typedef enum { + kPDAppearanceStyleBlue = 1, + kPDAppearanceStyleGraphite = 2 +} PDAppearanceStyle; + +@interface PDURLTextFieldCell : NSTextFieldCell { + + double _estimated_progress; + PDAppearanceStyle _appearanceStyle; + + NSImage *_image; + NSColor *_progress_gradient_start, *_progress_gradient_end; + +} + +- (void) _initializeColors; + +- (NSRect) textRectForFrame:(NSRect)frame; +- (NSRect) imageRectForFrame:(NSRect)frame; +- (NSRect) progressRectForFrame:(NSRect)frame; + +- (NSImage*) image; +- (void) setImage:(NSImage*)anImage; + +- (double) estimatedProgress; +- (void) setEstimatedProgress:(double)estimate; + +- (void) drawFocusRingWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; +- (void) drawProgressIndicatorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView; +- (void) drawImageWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; + +@end diff --git a/PDURLTextFieldCell.m b/PDURLTextFieldCell.m new file mode 100644 index 0000000..4e843cf --- /dev/null +++ b/PDURLTextFieldCell.m @@ -0,0 +1,229 @@ +// +// PDURLTextFieldCell.m +// SproutedInterface +// +// Created by Philip Dow on 5/28/06. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import +#import + +@implementation PDURLTextFieldCell + + +- (id)initWithCoder:(NSCoder *)decoder { + if ( self = [super initWithCoder:decoder] ) { + _appearanceStyle = kPDAppearanceStyleBlue; + [self _initializeColors]; + } + return self; +} + + +- (id)initImageCell:(NSImage *)anImage { + if ( self = [super initImageCell:anImage] ) { + _appearanceStyle = kPDAppearanceStyleBlue; + [self _initializeColors]; + } + return self; +} + +- (id)initTextCell:(NSString *)aString { + if ( self = [super initTextCell:aString] ) { + _appearanceStyle = kPDAppearanceStyleBlue; + [self _initializeColors]; + } + return self; +} + +- (void) dealloc { + [_image release]; + [_progress_gradient_start release]; + [_progress_gradient_end release]; + [super dealloc]; +} + +#pragma mark - + +- (void) _initializeColors { + if ( _appearanceStyle == kPDAppearanceStyleGraphite ) { + _progress_gradient_start = [[NSColor + colorWithCalibratedRed:187.0/255.0 green:196.0/255.0 blue:209.0/255.0 alpha:1.0] retain]; + _progress_gradient_end = [[NSColor + colorWithCalibratedRed:174.0/255.0 green:185.0/255.0 blue:201.0/255.0 alpha:1.0] retain]; + } + else { + _progress_gradient_start = [[NSColor + colorWithCalibratedRed:167.0/255.0 green:209.0/255.0 blue:255.0/255.0 alpha:1.0] retain]; + _progress_gradient_end = [[NSColor + colorWithCalibratedRed:126.0/255.0 green:186.0/255.0 blue:255.0/255.0 alpha:1.0] retain]; + } +} + +#pragma mark - + +- (NSRect)textRectForFrame:(NSRect)frame +{ + frame.origin.x += 20; + frame.size.width -= 20; + return frame; +} + +- (NSRect) imageRectForFrame:(NSRect)frame { + frame.origin.x+=2; + frame.size.width = 18; + return frame; +} + +- (NSRect) progressRectForFrame:(NSRect)frame { + if ( [self estimatedProgress] == 0 || [self estimatedProgress] > 1 ) return NSZeroRect; + + frame.origin.y+=2; + frame.size.height-=3; + frame.origin.x+=1; + frame.size.width=( (frame.size.width-=2) * [self estimatedProgress] ); + return frame; +} + +#pragma mark - + +- (NSImage*) image { return _image; } + +- (void) setImage:(NSImage*)anImage { + if ( _image != anImage ) { + [_image release]; + _image = [anImage copyWithZone:[self zone]]; + } +} + +- (double) estimatedProgress { return _estimated_progress; } + +- (void) setEstimatedProgress:(double)estimate { + _estimated_progress = estimate; +} + +#pragma mark - + +- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj + delegate:(id)anObject event:(NSEvent *)theEvent +{ + [super editWithFrame:[self textRectForFrame:aRect] inView:controlView editor:textObj + delegate:anObject event:theEvent]; +} + +- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj + delegate:(id)anObject start:(int)selStart length:(int)selLength +{ + [super selectWithFrame:[self textRectForFrame:aRect] inView:controlView editor:textObj + delegate:anObject start:selStart length:selLength]; +} + + +- (void)resetCursorRect:(NSRect)cellFrame inView:(NSView *)controlView +{ + [super resetCursorRect:[self textRectForFrame:cellFrame] inView:controlView]; +} + +#pragma mark - + + +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + // disable focus ring so I can draw my own + [self setFocusRingType:NSFocusRingTypeNone]; + + [super drawWithFrame:cellFrame inView:controlView]; + + // re-enable focus ring so that mine is properly erased + [self setFocusRingType:NSFocusRingTypeDefault]; +} + +- (void)highlight:(BOOL)flag withFrame:(NSRect)cellFrame inView:(NSView *)controlView { + // disable focus ring so I can draw my own + [self setFocusRingType:NSFocusRingTypeNone]; + + [super highlight:flag withFrame:cellFrame inView:controlView]; + + // re-enable focus ring so that mine is properly erased + [self setFocusRingType:NSFocusRingTypeDefault]; +} + + +- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + + BOOL does_draw_background = [self drawsBackground]; + + // Draw the focus ring + [self drawFocusRingWithFrame:cellFrame inView:controlView]; + + // Draw Progress Bar + [self drawProgressIndicatorWithFrame:[self progressRectForFrame:cellFrame] inView:controlView]; + + // Draw the FavIcon + [self drawImageWithFrame:[self imageRectForFrame:cellFrame] inView:controlView]; + + // Draw Remaining Things + + // Disable background drawing so that the interior draw does not erase the progress bar + [self setDrawsBackground:NO]; + + [super drawInteriorWithFrame:[self textRectForFrame:cellFrame] inView:controlView]; + + // Renable background drawing so that the view otherwise properly draws itself + [self setDrawsBackground:does_draw_background]; + +} + +- (void)drawFocusRingWithFrame:(NSRect)cellFrame inView:(NSView *)controlView +{ + if ([super showsFirstResponder] && [[controlView window] isKeyWindow] ) { + + [NSGraphicsContext saveGraphicsState]; + NSSetFocusRingStyle(NSFocusRingOnly); + NSBezierPath *bezier = [NSBezierPath bezierPathWithRect:cellFrame]; + [bezier fill]; + [NSGraphicsContext restoreGraphicsState]; + + } +} + +- (void) drawProgressIndicatorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { + + NSRect top, bottom; + NSDivideRect(cellFrame, &top, &bottom, cellFrame.size.height/2, NSMinYEdge); + top.size.height++; + + [[NSBezierPath bezierPathWithRect:top] linearGradientFillWithStartColor:_progress_gradient_start endColor:_progress_gradient_end]; + [[NSBezierPath bezierPathWithRect:bottom] linearGradientFillWithStartColor:_progress_gradient_end endColor:_progress_gradient_start]; +} + +- (void)drawImageWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + + NSImage *target_image = [self image]; + if ( target_image != nil ) { + + [target_image setFlipped:[controlView isFlipped]]; + + NSSize image_size = [target_image size]; + if ( image_size.width > 20 ) [target_image setSize:NSMakeSize(20, image_size.height*20/image_size.width)]; + + NSRect source_rect = NSMakeRect( 0, 0, image_size.width, image_size.height ); + NSRect target_rect = NSMakeRect( cellFrame.size.width/2 - image_size.width/2, + cellFrame.size.height/2 - image_size.height/2, + image_size.width, image_size.height ); + + target_rect.origin.x+=cellFrame.origin.x; + target_rect.origin.y+=cellFrame.origin.y; + + [target_image drawInRect:target_rect fromRect:source_rect + operation:NSCompositeSourceOver fraction:1.0]; + + } + +} + +@end \ No newline at end of file diff --git a/PDURLTextFieldFileDefault.png b/PDURLTextFieldFileDefault.png new file mode 100644 index 0000000000000000000000000000000000000000..df17799cfdd93d19723e817ccb6f4ff9cd46ddb6 GIT binary patch literal 630 zcmV-+0*U>JP)3VDIi%ifq4c155k#ejQqr@xA|>SP!ILKmLJ&_P zEhPq0B~SvPG@%GWEbUIKJ1?_g5`Jqq%a(O`l;s8*{8hr^I0i3K&AO*9$}HeW0jk;!CWx7*b~ zAi(tnP*9~(fn2Wxnkw>Jtrk;6Dz#vw(`nk;1rdxip69`vOl)k@dh+#tXlNKCBQ_+H zNrI|=zn|*?2!g;icLBBLa=CDFa?0iurHw=)0Sz!f!9M`W&gFh!V%!Ih$Ah)CRhAP< zZYq^R-z$&;Y7{JrA}lJ8T%nAs>jIuVwZk{*XE|{=92lGft;P3tQNu(0thq5i^9a_n z@7VfU!pDtK_$DS{u~=?nOhy3FDQVL69~}L1qa==D>U;-`VoTn0Y70r}Gb z<~KHP^YmYU*Xzaemy3w3FJt=2IF3tYy#EkouR-g^rxyBMfz0W2Vmr1Ey;k&oU@aJ5 z;y%+4=>m{6`Y5t2_nc@{L9akH(gUD-$K!FfNWYCX(@92y8RVk0Ob6`jkD%p Qng9R*07*qoM6N<$f~95{(*OVf literal 0 HcmV?d00001 diff --git a/PDURLTextFieldWebDefault.tiff b/PDURLTextFieldWebDefault.tiff new file mode 100644 index 0000000000000000000000000000000000000000..42020ff866c2921e883ea1e5c18fc8381b4bcde3 GIT binary patch literal 1068 zcmYk5drVt(6vxl+w!M@-pdj=Gl-s4Oz#0Ucqni$HJCyo>ASf0lu8dbFFc8KDQuUSs zV`OaVLc@fWLI!l2kw9iPl(_N`(2&Vc5$6&wgjmLgfF@=v#CSJrLQZn>`F+p#ob&tV zq^3eN0P8pfM7mZb7Wy>k^U`k=aHT>X-=@5+OAqqrog34U(|z3alV8f$PhA*n@x1%& zPv_MauJ#ITR1uj@#vaHCYJDkXa8ue8A?HuHVYV~|*oY$W{MW{ybl+h&uHT}5Eg7=A z-W^q;Dlu-33?vu-or?<_Js}HMxGf zb2`^@D_n~}NHsY;VcR^alo^r_NBFw&Pa;nMc2WOE=_wM`%#Ukx&zo4E7r@D(`KzAs z>a=u7dOKB1aHaA3q{gO03+(uCke}%hp=mn-d$QA<@E}bD>h>5Dw&q-er10zg9jlXn z*BO5sD8?`Kbn0(9G~=G2M2*A=NB3|^qiTcgo)$wu{ld#2_dH`R4DqxBZUq8N^6zzz zK5(WC|0PnK9-FMW^dRnGVOzxJc6l2n=VDFy-_CG2OOf$>L>mA{B{zZv6xvARx~OIW zh=1><0htI46h5C#);j+DY6-%oE^bE43-8^kYi|(ktw*|z?J8{aqh>)p-5}bf!(m*1m&_B)P*dX7~l&a6m@&{ob08P3-S z(Yyi5A`ztg@S`1N0pdmI%*xgG!`*16CPNkXPUXJ-%-J%@H@=o?Y4SvY)w*antLGf0 zRu9@nLy~>#2}=xT)TH%~n&%nq-4xQQteS)u=Jp4-9-FJ^ppZRFv>Y{O7O$`3n3Zzo zNLt44nIz4-+{pqPc{#@Cis@C$NL1BwAMllI5}qcJx$L{5>@U=xHf|ZqrM<*Tl14crOJET#q9aW={4&P^!? z3Wf|?Hp}W>z*$y$B|flem+ORDFg9x>@Y?C;eE=#HY(P%zj^gySud_Su%dX|gJi3Uo08H8b4FJV1hTthqlHtZsDFAL z#n!vkAunEWm4)`=t=>Kw*{dl_Rm0GK+{3&2HzUY&WNU@tROB>s=NkByT5{j4Gsy2F3a%a3Pf W?9elx@Z&$In0981HxRRviGKmaR$3DP literal 0 HcmV?d00001 diff --git a/PolishedWindow.h b/PolishedWindow.h new file mode 100644 index 0000000..7e89098 --- /dev/null +++ b/PolishedWindow.h @@ -0,0 +1,42 @@ +// +// PolishedWindow.h +// TunesWindow +// +// Created by Matt Gemmell on 12/02/2006. +// Copyright 2006 Magic Aubergine. All rights reserved. +// + +#import + +// offers the 10.5 window look in 10.4 + +@interface PolishedWindow : NSWindow { + BOOL _flat; + BOOL forceDisplay; + + // PD Modifications to improve rendering during drag + NSImage *bottomLeft; + NSImage *bottomMiddle; + NSColor *bottomMiddlePattern; + NSImage *bottomRight; + NSImage *topLeft; + NSImage *topMiddle; + NSColor *topMiddlePattern; + NSImage *topRight; + NSImage *middleLeft; + NSImage *middleRight; + // End modifications +} + +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(unsigned int)styleMask + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag + flat:(BOOL)flat; + +- (NSColor *)sizedPolishedBackground; + +- (BOOL)flat; +- (void)setFlat:(BOOL)newFlat; + +@end \ No newline at end of file diff --git a/PolishedWindow.m b/PolishedWindow.m new file mode 100644 index 0000000..c572fd3 --- /dev/null +++ b/PolishedWindow.m @@ -0,0 +1,250 @@ +// +// PolishedWindow.m +// TunesWindow +// +// Created by Matt Gemmell on 12/02/2006. +// Copyright 2006 Magic Aubergine. All rights reserved. +// + +#import +#import + +@implementation PolishedWindow + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag +{ + return [self initWithContentRect:contentRect styleMask:styleMask backing:bufferingType defer:flag flat:NO]; +} + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag flat:(BOOL)flat +{ + + if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + { + // Conditionally add textured window flag to stylemask + unsigned int newStyle; + if (styleMask & NSTexturedBackgroundWindowMask){ + newStyle = styleMask; + } else { + newStyle = (NSTexturedBackgroundWindowMask | styleMask); + } + + if (self = [super initWithContentRect:contentRect styleMask:newStyle backing:bufferingType defer:flag] ) + { + // PD Modifications + _flat = YES; + forceDisplay = NO; + + bottomLeft = [BundledImageWithName(@"flat_bottom_left.png", @"com.sprouted.interface") retain]; + bottomMiddle = [BundledImageWithName(@"flat_bottom_middle.png", @"com.sprouted.interface") retain]; + bottomMiddlePattern = [[NSColor colorWithPatternImage:bottomMiddle] retain]; + + bottomRight = [BundledImageWithName(@"flat_bottom_right.png", @"com.sprouted.interface") retain]; + topLeft = [BundledImageWithName(@"flat_top_left.png", @"com.sprouted.interface") retain]; + topMiddle = [BundledImageWithName(@"flat_top_middle.png", @"com.sprouted.interface")retain]; + topMiddlePattern = [[NSColor colorWithPatternImage:topMiddle] retain]; + + topRight = [BundledImageWithName(@"flat_top_right.png", @"com.sprouted.interface") retain]; + middleLeft = [BundledImageWithName(@"middle_left.png", @"com.sprouted.interface") retain]; + middleRight = [BundledImageWithName(@"middle_right.png", @"com.sprouted.interface") retain]; + + [self setBackgroundColor:[self sizedPolishedBackground]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) + name:NSWindowDidResizeNotification object:self]; + } + } + else + { + if ( self = [super initWithContentRect:contentRect styleMask:styleMask backing:bufferingType defer:flag] ) + { + //[self setContentBorderThickness:20.0 forEdge:NSMinYEdge]; + //[self setAutorecalculatesContentBorderThickness:YES forEdge:NSMinYEdge]; + } + } + + return self; +} + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 +- (void)setToolbar:(NSToolbar *)toolbar +{ + //if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + //{ + // Only actually call this if we respond to it on this machine + if ([toolbar respondsToSelector:@selector(setShowsBaselineSeparator:)]) { + [toolbar setShowsBaselineSeparator:NO]; + } + //} + [super setToolbar:toolbar]; +} +#endif + +- (void)dealloc +{ + if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + { + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:self]; + + [bottomLeft release]; + [bottomMiddle release]; + [bottomMiddlePattern release]; + [bottomRight release]; + [topLeft release]; + [topMiddle release]; + [topMiddlePattern release]; + [topRight release]; + [middleLeft release]; + [middleRight release]; + } + + [super dealloc]; +} + +- (void)windowDidResize:(NSNotification *)aNotification +{ + if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + { + [self setBackgroundColor:[self sizedPolishedBackground]]; + if (forceDisplay) { + [self display]; + } + } +} + +- (void)setMinSize:(NSSize)aSize +{ + if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + [super setMinSize:NSMakeSize(MAX(aSize.width, 150.0), MAX(aSize.height, 150.0))]; + else + [super setMinSize:aSize]; +} + +- (void)setFrame:(NSRect)frameRect display:(BOOL)displayFlag animate:(BOOL)animationFlag +{ + if ( ![self respondsToSelector:@selector(contentBorderThicknessForEdge:)] ) + { + forceDisplay = YES; + [super setFrame:frameRect display:displayFlag animate:animationFlag]; + forceDisplay = NO; + } + else + [super setFrame:frameRect display:displayFlag animate:animationFlag]; +} + +- (NSColor *)sizedPolishedBackground +{ + NSImage *bg = [[NSImage alloc] initWithSize:[self frame].size]; + + // Find background color to draw into window + [topMiddle lockFocus]; + NSColor *bgColor = NSReadPixel(NSMakePoint(0, 0)); + [topMiddle unlockFocus]; + //NSColor *bgColor = [NSColor colorWithCalibratedWhite:235.0/255.0 alpha:1.0]; + + // Set min width of temporary pattern image to prevent flickering at small widths + float minWidth = 300.0; + + // Create temporary image for top-middle pattern + NSImage *topMiddleImg = [[NSImage alloc] initWithSize:NSMakeSize(MAX(minWidth, [self frame].size.width), [topMiddle size].height)]; + [topMiddleImg lockFocus]; + [topMiddlePattern set]; + NSRectFillUsingOperation(NSMakeRect(0, 0, [topMiddleImg size].width, [topMiddleImg size].height), NSCompositeSourceOver); + [topMiddleImg unlockFocus]; + + // Create temporary image for bottom-middle pattern + NSImage *bottomMiddleImg = [[NSImage alloc] initWithSize:NSMakeSize(MAX(minWidth, [self frame].size.width), [bottomMiddle size].height)]; + [bottomMiddleImg lockFocus]; + [bottomMiddlePattern set]; + NSRectFillUsingOperation(NSMakeRect(0, 0, [bottomMiddleImg size].width, [bottomMiddleImg size].height), NSCompositeSourceOver); + [bottomMiddleImg unlockFocus]; + + // Begin drawing into our main image + [bg lockFocus]; + + // Composite current background color into bg + [bgColor set]; + NSRectFillUsingOperation(NSMakeRect(0, 0, [bg size].width, [bg size].height), NSCompositeSourceOver); + + if ([self flat]) { + // Composite middle left/right images + + //[middleLeft setFlipped:NO]; + [middleLeft drawInRect:NSMakeRect(0, 0, + [middleLeft size].width, + [self frame].size.height) + fromRect:NSMakeRect(0, 0, + [middleLeft size].width, + [middleLeft size].height) + operation:NSCompositeSourceOver + fraction:1.0]; + + //[middleRight setFlipped:NO]; + [middleRight drawInRect:NSMakeRect([self frame].size.width - [middleRight size].width + 1.0, 0, + [middleRight size].width, + [self frame].size.height) + fromRect:NSMakeRect(0, 0, + [middleRight size].width, + [middleRight size].height) + operation:NSCompositeSourceOver + fraction:1.0]; + } + + // Composite bottom-middle image + //[bottomMiddleImg setFlipped:NO]; + [bottomMiddleImg drawInRect:NSMakeRect([bottomLeft size].width, 0, + [bg size].width - [bottomLeft size].width - [bottomRight size].width, + [bottomLeft size].height) + fromRect:NSMakeRect(0, 0, + [bg size].width - [bottomLeft size].width - [bottomRight size].width, + [bottomLeft size].height) + operation:NSCompositeSourceOver + fraction:1.0]; + [bottomMiddleImg release]; + + // Composite bottom-left and bottom-right images + //[bottomLeft setFlipped:NO]; + [bottomLeft compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver]; + + //[bottomRight setFlipped:NO]; + [bottomRight compositeToPoint:NSMakePoint([bg size].width - [bottomRight size].width, 0) operation:NSCompositeSourceOver]; + + // Composite top-middle image + //[topMiddleImg setFlipped:NO]; + [topMiddleImg drawInRect:NSMakeRect([topLeft size].width, + [bg size].height - [topLeft size].height, + [bg size].width - [topLeft size].width - [topRight size].width, + [topLeft size].height) + fromRect:NSMakeRect(0, 0, + [bg size].width - [topLeft size].width - [topRight size].width, + [topLeft size].height) + operation:NSCompositeSourceOver + fraction:1.0]; + [topMiddleImg release]; + + // Composite top-left and top-right images + //[topLeft setFlipped:NO]; + [topLeft compositeToPoint:NSMakePoint(0, [bg size].height - [topLeft size].height) operation:NSCompositeSourceOver]; + + //[topRight setFlipped:NO]; + [topRight compositeToPoint:NSMakePoint([bg size].width - [topRight size].width, + [bg size].height - [topRight size].height) operation:NSCompositeSourceOver]; + + [bg unlockFocus]; + + return [NSColor colorWithPatternImage:[bg autorelease]]; +} + +- (BOOL)flat +{ + return _flat; +} + +- (void)setFlat:(BOOL)newFlat +{ + _flat = newFlat; + forceDisplay = YES; + [self windowDidResize:nil]; + forceDisplay = NO; +} + +@end diff --git a/PreviewBarSmall.png b/PreviewBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..945b162d7b4cd2ee59a6151153b6e772f3a1adfa GIT binary patch literal 1745 zcmV;?1}^!DP)vTGeMype6b$b2g>ME;_1O4qf{=H}+Bk21i}>-D9ZELCQ+xw4!T>a;qo(OgkcsZ}e= z3dDudbS#XOc{i35NpQJY=rx7NfPuGv_iM;sQUAM-?D=i)FJN}x5{V5xr|zEuhS zayJ$)DL&dS-9RJ(NM#bRazG{nB-3=xd&gzM zJL|+dZ@xt|%J5iqIj_CF{o}bgO5WNCj5<}3uDlvTofZFZ0xqhBfeXJxaQGuM)b9f0 zv6qn$n2{nQY(CMtxCr}DKR&(Lh1IYF@4goXKkG+nX=(l7;9$>#2&ycWnh!}@o;&f< z^}9@Te*uJ|KsL6B_A{@*q>|x#kC%fR9Y;h|g;nx?tiKoG=}{OpEHIbssNbfAM#{qc z{5Ksg=mC zOya`(=TNSVwcqs z>2|vrKR(gAXLve`*%=SIKDh|D<2G`$onREmab)jKSSn4p)IUMqi_mqs1LKZy1VSO$ zhlf#ED8XXbk3YS44nsqOXl&fO+}76C@t{l{j*0QwT~9Q~B_ho)-uwU@u>i$-5yE4C zN0c(llquk~_hSEn-N=a5@caEVV%Ts@PEm5bxOlMxq!4|5*C7%Kf>Nn;f@r$TdZ_7E z2S59K;fn_Ca@}0;v2PfxMlww4Gnu?s@R0l zTf>OOVuT1(DrKakq-01Ukz^(&CO&)E00M!)l&VN!{n3f%H%1bC?6GZtFcZS$m>ro! z4Dn0~(RcA63VNQ7ByhZ8;Y27^Im%aKFdJFf*%Af-8T^f)r9Wl}7}xwa3H zB#%#@KHcl{`8XbrCon!fKIL>eUD0SXWVKq?(>yYgp_?>BXBhu&7h|(ICA~e}-6r$) zGM_(zLNOmoIpFs>qrW+GrtObs&;Fj4xlAV0b4^W6-_B;UadK*b$z*0+E|;gjzyH(w zliKmftxwas0pKUjhsOzc;7246)r700000NkvXXu0mjfE*n8x literal 0 HcmV?d00001 diff --git a/QTBarSmall.png b/QTBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..637642d5fbf0d7a6dece60a76931838313f411c5 GIT binary patch literal 1516 zcmV3PmOR+RoYJ8+BSS{8@>&WFqVLoQpBa-HYP7w zJjD_8fEQDwj}t*}7J=0dZ&757O}`ubcV$R5Fu*G!bRGNhhrsXKE3^oXL!eJ!79BXH zn_pTGVf|o~V!)7MfpDKw4PE}JMeXnIW;l*xC*@?Sx%0B-h+*c70)U<8LvXZN2T=dn zVQBe$Edr?{1n`K8^4{48m2S%I>7thJ`e}SUrNV}NO^jqK#Z?QM!Q<5YFpD!QzN)?I z#p6L5QNpz3u${st2ZaeQt$Emk2L!^TT-ewaCVP5lY_)^N)~J*%`=AB^C88yqkm%Hg z6rc6Nn^l*4a`(IF-nKApb;&g2n@$S5T@+TH=saeCqbFqmQJ%=cH| z#K&)A_&gZHD6)#fGBJ1lvTes}TTMxlgEc~B-G!bIm`t+SX5w`+gr*dxL0on*xZ6%e zl{lg%$Xr;)3M%M00s(Ib=#N!j<8#-;;8J{c$#mAP(k-0{ID50*@!^89fri6% zgf{?BFrQ{4K=O-A?o0h%y-AQVEsZ4#KH)&=?esCdEvJDQi6w$tGmBo{T33J7I8p4> zn}F%O*zMf0WCatJFEj0D8$v^VAZQEA;{n@@X^#>Ry#Yi~V9^3i>D2G_K_oo*AXxyh z(-&3T%AOkAW0HV$U+Qt~T)LWi`_D&h2zni=92kbu5Dk*ykyZgTT0t}_S2Z$BNOUov z1hwErW!&4^&=C6P;v00p-q*K#%~~pZE;58L7(2|Q!2%4cRR~`28ukZ95d;PS4?<3= znFNM_m?w%#!i>4Z@!O$$y^2I!?WdjZ&YF#XW#qIoBa+e_Or2Ls1U=fKpp^*eY;7Nv z1CZg`$tIOEg64$DtOruGZi5;%K#dj+0%}AzaN6(dRm(gvWw1rBFBjM#f)h}KVSwAe z{ydrh;95hi;_-sY>me357nCk9<_kCNM|dp^>af-rGOQ}9QVksR6D;M`$J6t(%shla z#|uEN|IrPuwsT_%2L3*yoIBDKF~x%qlWMi7uwu)OwHb?d)u>!j0m4NwhX)2CE^pCu z8;&&2ttg+VBQhwM3Y#cE{9pBF(T(26cT*w0kbUoTgDEfHD!BU~FOG%j@v-2)-Kn^* zU$}6mr^l|-acn|zMy4_Q`FzD56|+7|I|mT*Z1FSI`;T(nvlIh z*naY$n4T^Ic1$x>AVbnYqEUbtRETEjU5sqeX+AkCNrp1)#Jw|jIAEkOf}iEm~}ojg%gcl8ktr8ma%-@t3pn34reuMMLsMZ + +@class RBSplitView; + +// These values are used to inquire about the status of a subview. +typedef enum { + RBSSubviewExpanding=-2, + RBSSubviewCollapsing=-1, + RBSSubviewNormal=0, + RBSSubviewCollapsed=1 +} RBSSubviewStatus; + +@interface RBSplitSubview : NSView { +// Subclasses normally should use setter methods instead of changing instance variables by assignment. +// Most getter methods simply return the corresponding instance variable, so with some care, subclasses +// could reference them directly. + NSString* identifier; // An identifier string for the subview, default is @"". + int tag; // A tag integer for the subview, default is 0. + float minDimension; // The minimum dimension. Must be 1.0 or any larger integer. + float maxDimension; // The maximum dimension. Must be at least equal to the minDimension. + // Set to a large number if there's no maximum. + double fraction; // A fractional part of the dimension, used for proportional resizing. + // Normally varies between -0.999... and 0.999... + // When collapsed, holds the proportion of the RBSplitView's dimension + // the view was occupying before collapsing. + NSRect previous; // Holds the frame rect for the last delegate notification. + NSSize savedSize; // This holds the size the subview had before it was resized beyond + // its minimum or maximum limits. Valid if notInLimits is YES. + unsigned int actDivider; // This is set temporarily while an alternate drag view is being dragged. + BOOL canDragWindow; // This is set temporarily during a mouseDown on a non-opaque subview. + BOOL canCollapse; // YES if the subview can be collapsed. + BOOL notInLimits; // YES if the subview's dimensions are outside the set limits. +} + +// This class method returns YES if some RBSplitSubview is being animated. ++ (BOOL)animating; + +// This is the designated initializer for creating extra subviews programmatically. +- (id)initWithFrame:(NSRect)frame; + +// Returns the immediately containing RBSplitView, or nil if there is none. +// couplingSplitView returns nil if we're a non-coupled RBSplitView. +// outermostSplitView returns the outermost RBSplitView. +- (RBSplitView*)splitView; +- (RBSplitView*)couplingSplitView; +- (RBSplitView*)outermostSplitView; + +// Returns self if we're a RBSplitView, nil otherwise. Convenient for testing or calling methods. +// coupledSplitView returns nil if we're a non-coupled RBSplitView. +- (RBSplitView*)asSplitView; +- (RBSplitView*)coupledSplitView; + +// Sets and gets the coupling between the view and its containing RBSplitView (if any). Coupled +// RBSplitViews take some parameters, such as divider images, from the containing view. The default +// for RBSplitView is YES. However, calling setCoupled: on a RBSplitSubview will have no effect, +// and isCoupled will always return false. +- (void)setCoupled:(BOOL)flag; +- (BOOL)isCoupled; + +// Returns YES if the containing RBSplitView is horizontal. +- (BOOL)splitViewIsHorizontal; + +// Returns the number of subviews. Just a convenience method. +- (unsigned)numberOfSubviews; + +// Sets and gets the tag. +- (void)setTag:(int)theTag; +- (int)tag; + +// Sets and gets the identifier string. Will never be nil. +- (void)setIdentifier:(NSString*)aString; +- (NSString*)identifier; + +// Position means the subview's position within the RBSplitView - counts from zero left to right +// or top to bottom. Setting it will move the subview to another position without changing its size, +// status or attributes. Set position to 0 to move it to the start, or to some large number to move it +// to the end of the RBSplitView. +- (unsigned)position; +- (void)setPosition:(unsigned)newPosition; + +// Returns YES if the subview is collapsed. Collapsed subviews are squashed down to zero but never +// made smaller than the minimum dimension as far as their own subviews are concerned. If the +// subview is being animated this will return NO. +- (BOOL)isCollapsed; + +// This will return the current status of the subview. Negative values mean the subview is +// being animated. +- (RBSSubviewStatus)status; + +// Sets and gets the ability to collapse the subview. However, this can be overridden by the delegate. +- (BOOL)canCollapse; +- (void)setCanCollapse:(BOOL)flag; + +// Tests whether the subview can shrink or expand further. +- (BOOL)canShrink; +- (BOOL)canExpand; + +// Sets and gets the minimum and maximum dimensions. They're set at the same time to make sure values +// are consistent. Despite being floats, they'll always have integer values. The minimum value for the +// minimum is 1.0. Pass 0.0 for the maximum to set it to some huge number. +- (float)minDimension; +- (float)maxDimension; +- (void)setMinDimension:(float)newMinDimension andMaxDimension:(float)newMaxDimension; + +// Call this to expand a subview programmatically. It will return the subview's dimension after +// expansion. +- (float)expand; + +// Call this to collapse a subview programmatically. It will return the negative +// of the subview's dimension _before_ collapsing, or 0.0 if the subview can't be collapsed. +- (float)collapse; + +// These calls collapse and expand subviews with animation. They return YES if animation +// startup was successful. +- (BOOL)collapseWithAnimation; +- (BOOL)expandWithAnimation; + +// These methods collapse and expand subviews with animation, depending on the parameters. +// They return YES if animation startup was successful. If resize is NO, the subview is +// collapsed/expanded without resizing it during animation. +- (BOOL)collapseWithAnimation:(BOOL)animate withResize:(BOOL)resize; +- (BOOL)expandWithAnimation:(BOOL)animate withResize:(BOOL)resize; + +// Returns the current dimension of the subview. +- (float)dimension; + +// Sets the current dimension of the subview, subject to the current maximum and minimum. +// If the subview is collapsed, this has no immediate effect. +- (void)setDimension:(float)value; + +// This method is used internally when a divider is dragged. It tries to change the subview's dimension +// and returns the actual change, collapsing or expanding whenever possible. You usually won't need +// to call this directly. +- (float)changeDimensionBy:(float)increment mayCollapse:(BOOL)mayCollapse move:(BOOL)move; + +@end + diff --git a/RBSplitSubview.m b/RBSplitSubview.m new file mode 100644 index 0000000..31dc9bf --- /dev/null +++ b/RBSplitSubview.m @@ -0,0 +1,927 @@ +// +// RBSplitSubview.m version 1.1.4 +// RBSplitView +// +// Created by Rainer Brockerhoff on 19/11/2004. +// Copyright 2004-2006 Rainer Brockerhoff. +// Some Rights Reserved under the Creative Commons Attribution License, version 2.5, and/or the MIT License. +// + +#import +#import + +// This variable points to the animation data structure while an animation is in +// progress; if there's none, it will be NULL. Animating may be very CPU-intensive so +// we allow only one animation to take place at a time. +static animationData* currentAnimation = NULL; + +@implementation RBSplitSubview + +// This class method returns YES if an animation is in progress. ++ (BOOL)animating { + return currentAnimation!=NULL; +} + +// This is the designated initializer for RBSplitSubview. It sets some reasonable defaults. However, you +// can't rely on anything working until you insert it into a RBSplitView. +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + fraction = 0.0; + canCollapse = NO; + notInLimits = NO; + minDimension = 1.0; + maxDimension = WAYOUT; + identifier = @""; + previous = NSZeroRect; + savedSize = frame.size; + actDivider = NSNotFound; + canDragWindow = NO; + } + return self; +} + +// Just releases our stuff when going away. +- (void)dealloc { + [identifier release]; + [super dealloc]; +} + +// These return nil since we're not a RBSplitView (they're overridden there). +- (RBSplitView*)asSplitView { + return nil; +} + +- (RBSplitView*)coupledSplitView { + return nil; +} + +// Sets and gets the coupling between a RBSplitView and its containing RBSplitView (if any). +// For convenience, these methods are also implemented here. +- (void)setCoupled:(BOOL)flag { +} + +- (BOOL)isCoupled { + return NO; +} + +// RBSplitSubviews are never flipped, unless they're RBSplitViews. +- (BOOL)isFlipped { + return NO; +} + +// We copy the opacity of the owning split view. +- (BOOL)isOpaque { + return [[self couplingSplitView] isOpaque]; +} + +// A hidden RBSplitSubview is not redrawn and is not considered for drawing dividers. +// This won't work before 10.3, though. +- (void)setHidden:(BOOL)flag { + if ([self isHidden]!=flag) { + RBSplitView* sv = [self splitView]; + [self RB___setHidden:flag]; + if (flag) { + [sv adjustSubviews]; + } else { + [sv adjustSubviewsExcepting:self]; + } + } +} + +// RBSplitSubviews can't be in the responder chain. +- (BOOL)acceptsFirstResponder { + return NO; +} + +// Mousing down should move the window only for a completely transparent background. This might have +// unintended side effects in metal windows, so for those you might want to use a background color +// with a very low alpha (0.01 for instance). +// This is commented out as I'm still experimenting with it. +/*- (BOOL)mouseDownCanMoveWindow { + RBSplitView* sv = [self asSplitView]; + if (!sv) { + sv = [self couplingSplitView]; + } + return [sv background]==nil; + return YES; +}*/ + +// This returns the owning splitview. It's guaranteed to return a RBSplitView or nil. +// You should avoid having "orphan" RBSplitSubviews, or at least manipulating +// them while they're not inserted in a RBSplitView. +- (RBSplitView*)splitView { + id result = [self superview]; + if ([result isKindOfClass:[RBSplitView class]]) { + return (RBSplitView*)result; + } + return nil; +} + +// This also returns the owning splitview. It's overridden for nested RBSplitViews. +- (RBSplitView*)couplingSplitView { + id result = [self superview]; + if ([result isKindOfClass:[RBSplitView class]]) { + return (RBSplitView*)result; + } + return nil; +} + +// This returns the outermost directly containing RBSplitView, or nil. +- (RBSplitView*)outermostSplitView { + id result = nil; + id sv = self; + while ((sv = [sv superview])&&[sv isKindOfClass:[RBSplitView class]]) { + result = sv; + } + return result; +} + +// This convenience method returns YES if the containing RBSplitView is horizontal. +- (BOOL)splitViewIsHorizontal { + return [[self splitView] isHorizontal]; +} + +// You can use either tags (ints) or identifiers (NSStrings) to identify individual subviews. +// We take care not to have nil identifiers. +- (void)setTag:(int)theTag { + tag = theTag; +} + +- (int)tag { + return tag; +} + +- (void)setIdentifier:(NSString*)aString { + [identifier autorelease]; + identifier = aString?[aString retain]:@""; +} + +- (NSString*)identifier { + return identifier; +} + +// If we have an identifier, this will make debugging a little easier by appending it to the +// default description. +- (NSString*)description { + return [identifier length]>0?[NSString stringWithFormat:@"%@(%@)",[super description],identifier]:[super description]; +} + +// This pair of methods allows you to get and change the position of a subview (within the split view); +// this counts from zero from the left or top of the split view. +- (unsigned)position { + RBSplitView* sv = [self splitView]; + return sv?[[sv subviews] indexOfObjectIdenticalTo:self]:0; +} + +- (void)setPosition:(unsigned)newPosition { + RBSplitView* sv = [self splitView]; + if (sv) { + [self retain]; + [self removeFromSuperviewWithoutNeedingDisplay]; + NSArray* subviews = [sv subviews]; + if (newPosition>=[subviews count]) { + [sv addSubview:self positioned:NSWindowAbove relativeTo:nil]; + } else { + [sv addSubview:self positioned:NSWindowBelow relativeTo:[subviews objectAtIndex:newPosition]]; + } + [self release]; + } +} + +// Tests whether the subview is collapsed. +- (BOOL)isCollapsed { + return [self RB___visibleDimension]<=0.0; +} + +// Tests whether the subview can shrink further. +- (BOOL)canShrink { + return [self RB___visibleDimension]>([self canCollapse]?0.0:minDimension); +} + +// Tests whether the subview can expand further. +- (BOOL)canExpand { + return [self RB___visibleDimension]collapsing?RBSSubviewCollapsing:RBSSubviewExpanding; + } + return [self RB___visibleDimension]<=0.0?RBSSubviewCollapsed:RBSSubviewNormal; +} + +// Tests whether the subview can be collapsed. The local instance variable will be overridden by the +// delegate method if it's implemented. +- (BOOL)canCollapse { + BOOL result = canCollapse; + RBSplitView* sv = [self splitView]; + if ([sv RB___numberOfSubviews]<2) { + return NO; + } + id delegate = [sv delegate]; + if ([delegate respondsToSelector:@selector(splitView:canCollapse:)]) { + result = [delegate splitView:sv canCollapse:self]; + } + return result; +} + +// This sets the subview's "canCollapse" flag. Ignored if the delegate's splitView:canCollapse: +// method is implemented. +- (void)setCanCollapse:(BOOL)flag { + canCollapse = flag; +} + +// This expands a collapsed subview and calls the delegate's splitView:didExpand: method, if it exists. +// This is not called internally by other methods; call this to expand a subview programmatically. +// As a convenience to other methods, it returns the subview's dimension after expanding (this may be +// off by 1 pixel due to rounding) or 0.0 if it couldn't be expanded. +// The delegate should not change the subview's frame. +- (float)expand { + return [self RB___expandAndSetToMinimum:NO]; +} + +// This collapses an expanded subview and calls the delegate's splitView:didCollapse: method, if it exists. +// This is not called internally by other methods; call this to expand a subview programmatically. +// As a convenience to other methods, it returns the negative of the subview's dimension before +// collapsing (or 0.0 if it couldn't be collapsed). +// The delegate should not change the subview's frame. +- (float)collapse { + return [self RB___collapse]; +} + +// This tries to collapse the subview with animation, and collapses it instantly if some other +// subview is animating. Returns YES if animation was started successfully. +- (BOOL)collapseWithAnimation { + return [self collapseWithAnimation:YES withResize:YES]; +} + +// This tries to expand the subview with animation, and expands it instantly if some other +// subview is animating. Returns YES if animation was started successfully. +- (BOOL)expandWithAnimation { + return [self expandWithAnimation:YES withResize:YES]; +} + +// These methods collapse and expand subviews with animation, depending on the parameters. +// They return YES if animation startup was successful. If resize is NO, the subview is +// collapsed/expanded without resizing it during animation. +- (BOOL)collapseWithAnimation:(BOOL)animate withResize:(BOOL)resize { + if ([self status]==RBSSubviewNormal) { + if ([self canCollapse]) { + if (animate&&[self RB___animationData:YES resize:resize]) { + [self RB___clearResponder]; + [self RB___stepAnimation]; + return YES; + } else { + [self RB___collapse]; + } + } + } + return NO; +} + +- (BOOL)expandWithAnimation:(BOOL)animate withResize:(BOOL)resize { + if ([self status]==RBSSubviewCollapsed) { + if (animate&&[self RB___animationData:YES resize:resize]) { + [self RB___stepAnimation]; + return YES; + } else { + [self RB___expandAndSetToMinimum:NO]; + } + } + return NO; +} + + +// These 3 methods get and set the view's minimum and maximum dimensions. +// The minimum dimension ought to be an integer at least equal to 1.0 but we make sure. +// The maximum dimension ought to be an integer at least equal to the minimum. As a convenience, +// pass in zero to set it to some huge number. +- (float)minDimension { + return minDimension; +} + +- (float)maxDimension { + return maxDimension; +} + +- (void)setMinDimension:(float)newMinDimension andMaxDimension:(float)newMaxDimension { + minDimension = MAX(1.0,floorf(newMinDimension)); + if (newMaxDimension<1.0) { + newMaxDimension = WAYOUT; + } + maxDimension = MAX(minDimension,floorf(newMaxDimension)); + float dim = [self dimension]; + if ((dimmaxDimension)) { + [[self splitView] setMustAdjust]; + } +} + +// This returns the subview's dimension. If it's collapsed, it returns the dimension it would have +// after expanding. +- (float)dimension { + float dim = [self RB___visibleDimension]; + if (dim<=0.0) { + dim = [[self splitView] RB___dimensionWithoutDividers]*fraction; + if (dimmaxDimension) { + dim = maxDimension; + } + } + return dim; +} + +// Sets the current dimension of the subview, subject to the current maximum and minimum. +// If the subview is collapsed, this will have an effect only after reexpanding. +- (void)setDimension:(float)value { + RBSplitView* sv = [self splitView]; + NSSize size = [self frame].size; + BOOL ishor = [sv isHorizontal]; + if (DIM(size)>0.0) { +// We're not collapsed, set the size and adjust other subviews. + DIM(size) = value; + [self setFrameSize:size]; + [sv adjustSubviewsExcepting:self]; + } else { +// We're collapsed, adjust the fraction so that we'll have the (approximately) correct +// dimension after expanding. + fraction = value/[sv RB___dimensionWithoutDividers]; + } +} + +// This just draws the background of a subview, then tells the delegate, if any. +// The delegate would usually draw a frame inside the subview. +- (void)drawRect:(NSRect)rect { + RBSplitView* sv = [self splitView]; + NSColor* bg = [sv background]; + if (bg) { + [bg set]; + NSRectFillUsingOperation(rect,NSCompositeSourceOver); + } + id del = [sv delegate]; + if ([del respondsToSelector:@selector(splitView:willDrawSubview:inRect:)]) { + [del splitView:sv willDrawSubview:self inRect:rect]; + } +} + +// We check if the RBSplitView must be adjusted before redisplaying programmatically. +// if so, we adjust and display the whole RBSplitView. +- (void)display { + RBSplitView* sv = [self splitView]; + if (sv) { + if ([sv mustAdjust]) { + [sv display]; + } else { + [super display]; + } + } +} + +// RBSplitSubviews will always resize their own subviews. +- (BOOL)autoresizesSubviews { + return YES; +} + +// This is method is called automatically when the subview is resized; don't call it yourself. +- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize { + RBSplitView* sv = [self splitView]; + if (sv) { + BOOL ishor = [sv isHorizontal]; + NSRect frame = [self frame]; + float dim = DIM(frame.size); + float other = OTHER(frame.size); +// We resize subviews only when we're inside the subview's limits and the containing splitview's limits. + animationData* anim = [self RB___animationData:NO resize:NO]; + if ((dim>=(anim&&!anim->resizing?anim->dimension:minDimension))&&(dim<=maxDimension)&&(other>=[sv minDimension])&&(other<=[sv maxDimension])) { + if (notInLimits) { +// The subviews can be resized, so we restore the saved size. + oldBoundsSize = savedSize; + } +// We save the size every time the subview's subviews are resized within the limits. + notInLimits = NO; + savedSize = frame.size; + [super resizeSubviewsWithOldSize:oldBoundsSize]; + } else { + notInLimits = YES; + } + } +} + +// This method is used internally when a divider is dragged. It tries to change the subview's dimension +// and returns the actual change, collapsing or expanding whenever possible. You usually won't need +// to call this directly. +- (float)changeDimensionBy:(float)increment mayCollapse:(BOOL)mayCollapse move:(BOOL)move { + RBSplitView* sv = [self splitView]; + if (!sv||(fabsf(increment)<1.0)) { + return 0.0; + } + BOOL ishor = [sv isHorizontal]; + NSRect frame = [self frame]; + float olddim = DIM(frame.size); + float newdim = MAX(0.0,olddim+increment); + if (newdimolddim) { + if (olddim<1.0) { +// Expand if needed. + if (newdim>(minDimension*(0.5+HYSTERESIS))) { + newdim = MAX(newdim,[self RB___expandAndSetToMinimum:YES]); + } else { + return 0.0; + } + } + if (newdim>maxDimension) { + newdim = maxDimension; + } + } + if ((int)newdim!=(int)olddim) { +// The dimension has changed. + increment = newdim-olddim; + DIM(frame.size) = newdim; + if (move) { + DIM(frame.origin) -= increment; + } +// We call super instead of self here to postpone adjusting subviews for nested splitviews. +// [super setFrameSize:frame.size]; + [super setFrame:frame]; + [sv RB___setMustClearFractions]; + [sv setMustAdjust]; + } + return newdim-olddim; +} + +// This convenience method returns the number of subviews (surprise!) +- (unsigned)numberOfSubviews { + return [[self subviews] count]; +} + +// We return the deepest subview that's hit by aPoint. We also check with the delegate if aPoint is +// within an alternate drag view. +- (NSView*)hitTest:(NSPoint)aPoint { + RBSplitView* sv = [self splitView]; + if ([self mouse:aPoint inRect:[self frame]]) { + id delegate = [sv delegate]; + if ([delegate respondsToSelector:@selector(splitView:dividerForPoint:inSubview:)]) { + actDivider = [delegate splitView:sv dividerForPoint:aPoint inSubview:self]; + if ((int)actDivider<(int)([sv RB___numberOfSubviews]-1)) { + return self; + } + } + actDivider = NSNotFound; + NSView* result = [super hitTest:aPoint]; + canDragWindow = ![result isOpaque]; + return result; + } + return nil; +} + +// This method handles clicking and dragging in an empty portion of the subview, or in an alternate +// drag view as designated by the delegate. +- (void)mouseDown:(NSEvent*)theEvent { + NSWindow* window = [self window]; + NSPoint where = [theEvent locationInWindow]; + if (actDivider=WAYOUT) { +// The subview was collapsed when encoded, so we correct the origin and collapse it. + BOOL ishor = [self splitViewIsHorizontal]; + previous.origin.x -= WAYOUT; + DIM(previous.size) = 0.0; + [self setFrameOrigin:previous.origin]; + [self setFrameSize:previous.size]; + } + previous = NSZeroRect; + if ([coder allowsKeyedCoding]) { + [self setIdentifier:[coder decodeObjectForKey:@"identifier"]]; + tag = [coder decodeIntForKey:@"tag"]; + minDimension = [coder decodeFloatForKey:@"minDimension"]; + maxDimension = [coder decodeFloatForKey:@"maxDimension"]; + fraction = [coder decodeDoubleForKey:@"fraction"]; + canCollapse = [coder decodeBoolForKey:@"canCollapse"]; + } else { + [self setIdentifier:[coder decodeObject]]; + [coder decodeValueOfObjCType:@encode(typeof(tag)) at:&tag]; + [coder decodeValueOfObjCType:@encode(typeof(minDimension)) at:&minDimension]; + [coder decodeValueOfObjCType:@encode(typeof(maxDimension)) at:&maxDimension]; + [coder decodeValueOfObjCType:@encode(typeof(fraction)) at:&fraction]; + [coder decodeValueOfObjCType:@encode(typeof(canCollapse)) at:&canCollapse]; + } + } + return self; +} + +@end + +@implementation RBSplitSubview (RB___SubviewAdditions) + +// This hides/shows the subview without calling adjustSubview. +- (void)RB___setHidden:(BOOL)flag { + [super setHidden:flag]; +} + +// This internal method returns the current animationData. It will always return nil if +// the receiver isn't the current owner and some other subview is already being animated. +// Otherwise, if the parameter is YES, a new animation will be started (or the current +// one will be restarted). +- (animationData*)RB___animationData:(BOOL)start resize:(BOOL)resize { + if (currentAnimation&&(currentAnimation->owner!=self)) { +// There already is an animation in progress on some other subview. + return nil; + } + if (start) { +// We want to start (or restart) an animation. + RBSplitView* sv = [self splitView]; + if (sv) { + float dim = [self dimension]; +// First assume the default time, then ask the delegate. + NSTimeInterval total = dim*(0.2/150.0); + id delegate = [sv delegate]; + if ([delegate respondsToSelector:@selector(splitView:willAnimateSubview:withDimension:)]) { + total = [delegate splitView:sv willAnimateSubview:self withDimension:dim]; + } +// No use animating anything shorter than the frametime. + if (total>FRAMETIME) { + if (!currentAnimation) { + currentAnimation = (animationData*)malloc(sizeof(animationData)); + } + if (currentAnimation) { + currentAnimation->owner = self; + currentAnimation->stepsDone = 0; + currentAnimation->elapsedTime = 0.0; + currentAnimation->dimension = dim; + currentAnimation->collapsing = ![self isCollapsed]; + currentAnimation->totalTime = total; + currentAnimation->finishTime = [NSDate timeIntervalSinceReferenceDate]+total; + currentAnimation->resizing = resize; + [sv RB___setDragging:YES]; + } + } else if (currentAnimation) { + free(currentAnimation); + currentAnimation = NULL; + } + } + } + return currentAnimation; +} + +// This internal method steps the animation to the next frame. +- (void)RB___stepAnimation { + NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; + animationData* anim = [self RB___animationData:NO resize:NO]; + if (anim) { + RBSplitView* sv = [self splitView]; + NSTimeInterval remain = anim->finishTime-now; + NSRect frame = [self frame]; + BOOL ishor = [sv isHorizontal]; +// Continuing animation only makes sense if we still have at least FRAMETIME available. + if (remain>=FRAMETIME) { + float dim = DIM(frame.size); + float avg = anim->elapsedTime; +// We try to keep a record of how long it takes, on the average, to resize and adjust +// one animation frame. + if (anim->stepsDone) { + avg /= anim->stepsDone; + } + NSTimeInterval delay = MIN(0.0,FRAMETIME-avg); +// We adjust the new dimension proportionally to how much of the designated time has passed. + dim = floorf(anim->dimension*(remain-avg)/anim->totalTime); + if (dim>4.0) { + if (!anim->collapsing) { + dim = anim->dimension-dim; + } + DIM(frame.size) = dim; + [self RB___setFrame:frame withFraction:0.0 notify:NO]; + [sv adjustSubviews]; + [self display]; + anim->elapsedTime += [NSDate timeIntervalSinceReferenceDate]-now; + ++anim->stepsDone; +// Schedule a timer to do the next animation step. + [self performSelector:@selector(RB___stepAnimation) withObject:nil afterDelay:delay inModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode,NSModalPanelRunLoopMode, + NSEventTrackingRunLoopMode,nil]]; + return; + } + } +// We're finished, either collapse or expand entirely now. + if (anim->collapsing) { + DIM(frame.size) = 0.0; + [self RB___finishCollapse:frame withFraction:anim->dimension/[sv RB___dimensionWithoutDividers]]; + } else { + float savemin,savemax; + float dim = [self RB___setMinAndMaxTo:anim->dimension savingMin:&savemin andMax:&savemax]; + DIM(frame.size) = dim; + [self RB___finishExpand:frame withFraction:0.0]; + minDimension = savemin; + maxDimension = savemax; + } + } +} + +// This internal method stops the animation, if the receiver is being animated. It will +// return YES if the animation was stopped. +- (BOOL)RB___stopAnimation { + if (currentAnimation&&(currentAnimation->owner==self)) { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(RB___stepAnimation) object:nil]; + free(currentAnimation); + currentAnimation = NULL; + [[self splitView] RB___setDragging:NO]; + return YES; + } + return NO; +} + +// This internal method returns the actual visible dimension of the subview. Differs from -dimension in +// that it returns 0.0 if the subview is collapsed. +- (float)RB___visibleDimension { + BOOL ishor = [self splitViewIsHorizontal]; + NSRect frame = [self frame]; + return MAX(0.0,DIM(frame.size)); +} + +// This pair of internal methods is used only inside -[RBSplitView adjustSubviews] to copy subview data +// from and to that method's internal cache. +- (void)RB___copyIntoCache:(subviewCache*)cache { + cache->sub = self; + cache->rect = [self frame]; + cache->size = [self RB___visibleDimension]; + cache->fraction = fraction; + cache->constrain = NO; +} + +- (void)RB___updateFromCache:(subviewCache*)cache withTotalDimension:(float)value { + float dim = [self RB___visibleDimension]; + if (cache->size>=1.0) { +// New state is not collapsed. + if (dim>=1.0) { +// Old state was not collapsed, so we just change the frame. + [self RB___setFrame:cache->rect withFraction:cache->fraction notify:YES]; + } else { +// Old state was collapsed, so we expand it. + [self RB___finishExpand:cache->rect withFraction:cache->fraction]; + } + } else { +// New state is collapsed. + if (dim>=1.0) { +// Old state was not collapsed, so we clear first responder and change the frame. + [self RB___clearResponder]; + [self RB___finishCollapse:cache->rect withFraction:dim/value]; + } else { +// It was collapsed already, but the frame may have changed, so we set it. + [self RB___setFrame:cache->rect withFraction:cache->fraction notify:YES]; + } + } +} + +// This internal method sets minimum and maximum values to the same value, saves the old values, +// and returns the new value (which will be limited to the old values). +- (float)RB___setMinAndMaxTo:(float)value savingMin:(float*)oldmin andMax:(float*)oldmax { + *oldmin = [self minDimension]; + *oldmax = [self maxDimension]; + if (value<*oldmin) { + value = *oldmin; + } + if (value>*oldmax) { + value = *oldmax; + } + minDimension = maxDimension = value; + return value; +} + +// This internal method tries to clear the first responder, if the current responder is a descendant of +// the receiving subview. If so, it will set first responder to nil, redisplay the former responder and +// return YES. Returns NO otherwise. +- (BOOL)RB___clearResponder { + NSWindow* window = [self window]; + if (window) { + NSView* responder = (NSView*)[window firstResponder]; + if (responder&&[responder respondsToSelector:@selector(isDescendantOf:)]) { + if ([responder isDescendantOf:self]) { + if ([window makeFirstResponder:nil]) { + [responder display]; + return YES; + } + } + } + } + return NO; +} + +// This internal method collapses a subview. +// It returns the negative of the size of the subview before collapsing, or 0.0 if it wasn't collapsed. +- (float)RB___collapse { + float result = 0.0; + if (![self isCollapsed]) { + RBSplitView* sv = [self splitView]; + if (sv&&[self canCollapse]) { + [self RB___clearResponder]; + NSRect frame = [self frame]; + BOOL ishor = [sv isHorizontal]; + result = DIM(frame.size); +// For collapsed views, fraction will contain the fraction of the dimension previously occupied + DIM(frame.size) = 0.0; + [self RB___finishCollapse:frame withFraction:result/[sv RB___dimensionWithoutDividers]]; + } + } + return -result; +} + +// This internal method finishes the collapse of a subview, stopping the animation if +// there is one, and calling the delegate method if there is one. +- (void)RB___finishCollapse:(NSRect)rect withFraction:(double)value { + RBSplitView* sv = [self splitView]; + BOOL finish = [self RB___stopAnimation]; + [self RB___setFrame:rect withFraction:value notify:YES]; + [sv RB___setMustClearFractions]; + if (finish) { + [self display]; + } + id delegate = [sv delegate]; + if ([delegate respondsToSelector:@selector(splitView:didCollapse:)]) { + [delegate splitView:sv didCollapse:self]; + } +} + +// This internal method expands a subview. setToMinimum will usually be YES during a divider drag. +// It returns the size of the subview after expanding, or 0.0 if it wasn't expanded. +- (float)RB___expandAndSetToMinimum:(BOOL)setToMinimum { + float result = 0.0; + RBSplitView* sv = [self splitView]; + if (sv&&[self isCollapsed]) { + NSRect frame = [super frame]; + double frac = fraction; + BOOL ishor = [sv isHorizontal]; + if (setToMinimum) { + result = DIM(frame.size) = minDimension; + } else { + result = [sv RB___dimensionWithoutDividers]*frac; +// We need to apply a compensation factor for proportional resizing in adjustSubviews. + float newdim = floorf((frac>=1.0)?result:result/(1.0-frac)); + DIM(frame.size) = newdim; + result = floorf(result); + } + [self RB___finishExpand:frame withFraction:0.0]; + } + return result; +} + +// This internal method finishes the the expansion of a subview, stopping the animation if +// there is one, and calling the delegate method if there is one. +- (void)RB___finishExpand:(NSRect)rect withFraction:(double)value { + RBSplitView* sv = [self splitView]; + BOOL finish = [self RB___stopAnimation]; + [self RB___setFrame:rect withFraction:value notify:YES]; + [sv RB___setMustClearFractions]; + if (finish) { + [self display]; + } + id delegate = [sv delegate]; + if ([delegate respondsToSelector:@selector(splitView:didExpand:)]) { + [delegate splitView:sv didExpand:self]; + } +} + +// These internal methods set the subview's frame or size, and also store a fraction value +// which is used to ensure repeatability when the whole split view is resized. +- (void)RB___setFrame:(NSRect)rect withFraction:(double)value notify:(BOOL)notify { + RBSplitView* sv = [self splitView]; + id delegate = nil; + if (notify) { + delegate = [sv delegate]; +// If the delegate method isn't implemented, we ignore the delegate altogether. + if ([delegate respondsToSelector:@selector(splitView:changedFrameOfSubview:from:to:)]) { +// If the rects are equal, the delegate isn't called. + if (NSEqualRects(previous,rect)) { + delegate = nil; + } + } else { + delegate = nil; + } + } + [sv setMustAdjust]; + [self setFrame:rect]; + fraction = value; + [delegate splitView:sv changedFrameOfSubview:self from:previous to:rect]; + previous = delegate?rect:NSZeroRect; +} + +- (void)RB___setFrameSize:(NSSize)size withFraction:(double)value { + [[self splitView] setMustAdjust]; + [self setFrameSize:size]; + fraction = value; +} + +// This internal method gets the fraction value. +- (double)RB___fraction { + return fraction; +} + +@end + diff --git a/RBSplitView.h b/RBSplitView.h new file mode 100644 index 0000000..0c786c2 --- /dev/null +++ b/RBSplitView.h @@ -0,0 +1,225 @@ +// +// RBSplitView.h version 1.1.4 +// RBSplitView +// +// Created by Rainer Brockerhoff on 24/09/2004. +// Copyright 2004-2006 Rainer Brockerhoff. +// Some Rights Reserved under the Creative Commons Attribution License, version 2.5, and/or the MIT License. +// + +#import "RBSplitSubview.h" + +// These values are used to handle the various cursor types. +typedef enum { + RBSVHorizontalCursor=0, // appears over horizontal dividers + RBSVVerticalCursor, // appears over vertical dividers + RBSV2WayCursor, // appears over two-way thumbs + RBSVDragCursor, // appears while dragging + RBSVCursorTypeCount +} RBSVCursorType; + +@interface RBSplitView : RBSplitSubview { +// Subclasses normally should use setter methods instead of changing instance variables by assignment. +// Most getter methods simply return the corresponding instance variable, so with some care, subclasses +// could reference them directly. + IBOutlet id delegate; // The delegate (may be nil). + NSString* autosaveName; // This name is used for storing subview proportions in user defaults. + NSColor* background; // The color used to paint the view's background (may be nil). + NSImage* divider; // The image used for the divider "dimple". + NSRect* dividers; // A C array of NSRects, one for each divider. + float dividerThickness; // Actual divider width; should be an integer and at least 1.0. + BOOL mustAdjust; // Set internally if the subviews need to be adjusted. + BOOL mustClearFractions; // Set internally if fractions should be cleared before adjusting. + BOOL isHorizontal; // The divider's orientation; default is vertical. + BOOL canSaveState; // Set internally to allow saving subview state. + BOOL isCoupled; // If YES, take some parameters from the containing RBSplitView, if any. + BOOL isAdjusting; // Set internally while the subviews are being adjusted. + BOOL isDragging; // Set internally while in a drag loop. + BOOL isInScrollView; // Set internally if directly contained in an NSScrollView. +} + +// These class methods get and set the cursor used for each type. +// Pass in nil to reset to the default cursor for that type. ++ (NSCursor*)cursor:(RBSVCursorType)type; ++ (void)setCursor:(RBSVCursorType)type toCursor:(NSCursor*)cursor; + +// This class method clears the saved state for a given autosave name from the defaults. ++ (void)removeStateUsingName:(NSString*)name; + +// This class method returns the actual key used to store autosave data in the defaults. ++ (NSString*)defaultsKeyForName:(NSString*)name isHorizontal:(BOOL)orientation; + +// Sets and gets the autosaveName; this will be the key used to store the subviews' proportions +// in the user defaults. Default is @"", which doesn't save anything. Set flag to YES to set +// unique names for nested subviews. You are responsible for avoiding duplicates. +- (void)setAutosaveName:(NSString*)aString recursively:(BOOL)flag; +- (NSString*)autosaveName; + +// Saves the current state of the subviews if there's a valid autosave name set. If the argument +// is YES, it's then also called recursively for nested RBSplitViews. Returns YES if successful. +- (BOOL)saveState:(BOOL)recurse; + +// Restores the saved state of the subviews if there's a valid autosave name set. If the argument +// is YES, it's first called recursively for nested RBSplitViews. Returns YES if successful. +// You need to call adjustSubviews after calling this. +- (BOOL)restoreState:(BOOL)recurse; + +// Returns a string encoding the current state of all direct subviews. Does not check for nesting. +- (NSString*)stringWithSavedState; + +// Readjusts all direct subviews according to the encoded string parameter. The number of subviews +// must match. Returns YES if successful. Does not check for nesting. +- (BOOL)setStateFromString:(NSString*)aString; + +// Returns an array with complete state information for the receiver and all subviews, taking +// nesting into account. Don't store this array in a file, as its format might change in the +// future; this is for taking a state snapshot and later restoring it with setStatesFromArray. +- (NSArray*)arrayWithStates; + +// Restores the state of the receiver and all subviews. The array must have been produced by a +// previous call to arrayWithStates. Returns YES if successful. This will fail if you have +// added or removed subviews in the meantime! +// You need to call adjustSubviews after calling this. +- (BOOL)setStatesFromArray:(NSArray*)array; + +// This is the designated initializer for creating RBSplitViews programmatically. +- (id)initWithFrame:(NSRect)frame; + +// This convenience initializer adds any number of subviews and adjusts them proportionally. +- (id)initWithFrame:(NSRect)frame andSubviews:(unsigned)count; + +// Sets and gets the delegate. (Delegates aren't retained.) See further down for delegate methods. +- (void)setDelegate:(id)anObject; +- (id)delegate; + +// Returns a subview which has a certain identifier string, or nil if there's none +- (RBSplitSubview*)subviewWithIdentifier:(NSString*)anIdentifier; + +// Returns the subview at a certain position. Returns nil if the position is invalid. +- (RBSplitSubview*)subviewAtPosition:(unsigned)position; + +// Adds a subview at a certain position. +- (void)addSubview:(NSView*)aView atPosition:(unsigned)position; + +// Sets and gets the divider thickness, which should be a positive integer or zero. +// Setting the divider image also resets this automatically, so you would call this +// only if you want the divider to be larger or smaller than the image. Zero means that +// the image dimensions will be used. +- (void)setDividerThickness:(float)thickness; +- (float)dividerThickness; + +// Sets and gets the divider image. The default image can also be set in Interface Builder, so usually +// there's no need to call this. Passing in nil means that the default divider thickness will be zero, +// and no mouse events will be processed, so that the dividers can be moved only programmatically. +- (void)setDivider:(NSImage*)image; +- (NSImage*)divider; + +// Sets and gets the view background. The default is nil, meaning no background is +// drawn and the view and its subviews are considered transparent. +- (void)setBackground:(NSColor*)color; +- (NSColor*)background; + +// Sets and gets the orientation. This uses the same convention as NSSplitView: vertical means the +// dividers are vertical, but the subviews are in a horizontal row. Sort of counter-intuitive, yes. +- (void)setVertical:(BOOL)flag; +- (BOOL)isVertical; +- (BOOL)isHorizontal; + +// Call this to force adjusting the subviews before display. Called automatically if anything +// relevant is changed. +- (void)setMustAdjust; + +// Returns YES if there's a pending adjustment. +- (BOOL)mustAdjust; + +// Returns YES if we're in a dragging loop. +- (BOOL)isDragging; + +// Returns YES if the view is directly contained in an NSScrollView. +- (BOOL)isInScrollView; + +// Call this to recalculate all subview dimensions. Normally this is done automatically whenever +// something relevant is changed, so you rarely will need to call this explicitly. +- (void)adjustSubviews; + +// This method should be called only from within the splitView:wasResizedFrom:to: delegate method +// to keep some specific subview the same size. +- (void)adjustSubviewsExcepting:(RBSplitSubview*)excepting; + +// This method draws dividers. You should never call it directly but you can override it when +// subclassing, if you need custom dividers. +- (void)drawDivider:(NSImage*)anImage inRect:(NSRect)rect betweenView:(RBSplitSubview*)leading andView:(RBSplitSubview*)trailing; + +@end + +// The following methods are optionally implemented by the delegate. + +@interface NSObject(RBSplitViewDelegate) + +// The delegate can override a subview's ability to collapse by implementing this method. +// Return YES to allow collapsing. If this is implemented, the subviews' built-in +// 'collapsed' flags are ignored. +- (BOOL)splitView:(RBSplitView*)sender canCollapse:(RBSplitSubview*)subview; + +// The delegate can alter the divider's appearance by implementing this method. +// Before calling this, the divider is filled with the background, and afterwards +// the divider image is drawn into the returned rect. If imageRect is empty, no +// divider image will be drawn, because there are nested RBSplitViews. Return +// NSZeroRect to suppress the divider image. Return imageRect to use the default +// location for the image, or change its origin to place the image elsewhere. +// You could also draw the divider yourself at this point and return NSZeroRect. +- (NSRect)splitView:(RBSplitView*)sender willDrawDividerInRect:(NSRect)dividerRect betweenView:(RBSplitSubview*)leading andView:(RBSplitSubview*)trailing withProposedRect:(NSRect)imageRect; + +// These methods are called after a subview is completely collapsed or expanded. adjustSubviews may or may not +// have been called, however. +- (void)splitView:(RBSplitView*)sender didCollapse:(RBSplitSubview*)subview; +- (void)splitView:(RBSplitView*)sender didExpand:(RBSplitSubview*)subview; + +// These methods are called just before and after adjusting subviews. +- (void)willAdjustSubviews:(RBSplitView*)sender; +- (void)didAdjustSubviews:(RBSplitView*)sender; + +// This method will be called after a RBSplitView is resized with setFrameSize: but before +// adjustSubviews is called on it. +- (void)splitView:(RBSplitView*)sender wasResizedFrom:(float)oldDimension to:(float)newDimension; + +// This method will be called when a divider is double-clicked and both leading and trailing +// subviews can be collapsed. Return either of the parameters to collapse that subview, or nil +// to collapse neither. If not implemented, the smaller subview will be collapsed. +- (RBSplitSubview*)splitView:(RBSplitView*)sender collapseLeading:(RBSplitSubview*)leading orTrailing:(RBSplitSubview*)trailing; + +// This method will be called when a cursor rect is being set (inside resetCursorRects). The +// proposed rect is passed in. Return the actual rect, or NSZeroRect to suppress cursor setting +// for this divider. This won't be called for two-axis thumbs, however. The rects are in +// sender's local coordinates. +- (NSRect)splitView:(RBSplitView*)sender cursorRect:(NSRect)rect forDivider:(unsigned int)divider; + +// This method will be called whenever a mouse-down event is received in a divider. Return YES to have +// the event handled by the split view, NO if you wish to ignore it or handle it in the delegate. +- (BOOL)splitView:(RBSplitView*)sender shouldHandleEvent:(NSEvent*)theEvent inDivider:(unsigned int)divider betweenView:(RBSplitSubview*)leading andView:(RBSplitSubview*)trailing; + +// This method will be called just before a subview will be collapsed or expanded with animation. +// Return the approximate time the animation should take, or 0.0 to disallow animation. +// If not implemented, it will use the default of 0.2 seconds per 150 pixels. +- (NSTimeInterval)splitView:(RBSplitView*)sender willAnimateSubview:(RBSplitSubview*)subview withDimension:(float)dimension; + +// This method will be called whenever a subview's frame is changed, usually from inside adjustSubviews' final loop. +// You'd normally use this to move some auxiliary view to keep it aligned with the subview. +- (void)splitView:(RBSplitView*)sender changedFrameOfSubview:(RBSplitSubview*)subview from:(NSRect)fromRect to:(NSRect)toRect; + +// This method is called whenever the event handlers want to check if some point within the RBSplitSubview +// should act as an alternate drag view. Usually, the delegate will check the point (which is in sender's +// local coordinates) against the frame of one or several auxiliary views, and return a valid divider number. +// Returning NSNotFound means the point is not valid. +- (unsigned int)splitView:(RBSplitView*)sender dividerForPoint:(NSPoint)point inSubview:(RBSplitSubview*)subview; + +// This method is called continuously while a divider is dragged, just before the leading subview is resized. +// Return NO to resize the trailing view by the same amount, YES to resize the containing window by the same amount. +- (BOOL)splitView:(RBSplitView*)sender shouldResizeWindowForDivider:(unsigned int)divider betweenView:(RBSplitSubview*)leading andView:(RBSplitSubview*)trailing willGrow:(BOOL)grow; + +// This method is called by each subview's drawRect: method, just after filling it with the background color but +// before the contained subviews are drawn. Usually you would use this to draw a frame inside the subview. +- (void)splitView:(RBSplitView*)sender willDrawSubview:(RBSplitSubview*)subview inRect:(NSRect)rect; + +@end + diff --git a/RBSplitView.m b/RBSplitView.m new file mode 100644 index 0000000..d5de6f2 --- /dev/null +++ b/RBSplitView.m @@ -0,0 +1,1734 @@ +// +// RBSplitView.m version 1.1.4 +// RBSplitView +// +// Created by Rainer Brockerhoff on 24/09/2004. +// Copyright 2004-2006 Rainer Brockerhoff. +// Some Rights Reserved under the Creative Commons Attribution License, version 2.5, and/or the MIT License. +// + +#import +#import + +// Please don't remove this copyright notice! +static const unsigned char RBSplitView_Copyright[] __attribute__ ((used)) = + "RBSplitView 1.1.4 Copyright(c)2004-2006 by Rainer Brockerhoff ."; + +// This vector keeps currently used cursors. nil means the default cursor. +static NSCursor* cursors[RBSVCursorTypeCount] = {nil}; + +// Our own fMIN and fMAX +static inline float fMIN(float a,float b) { + return ab?a:b; +} + +@implementation RBSplitView + +// These class methods get and set the cursor used for each type. +// Pass in nil to reset to the default cursor for that type. ++ (NSCursor*)cursor:(RBSVCursorType)type { + if ((type>=0)&&(type=0)&&(type1)&&([[parts objectAtIndex:0] intValue]==subcount)&&(k==subcount)) { + int i; + NSRect frame = [self frame]; + BOOL ishor = [self isHorizontal]; + for (i=0;i;U;MRrWiN$mcqgV(M^mhRcW(5y$6;?m#k2&}#>+mJfefg&h^PWn`9;h&i zFOOzo23TXlb{_#I)(0q)ri7EkX*&x&a}d(Og83NoVo+oHp$Vv|Qhh$?pXC{Im+xd% zzh5sNe>`ws-J2hL9?^XIixXc22wsla ztZh6HT73E9SJ^}Igd5sQUkm*E7Z=~(^>cg14bF|Xs|vH5&FIQEX7qIW&1s^lw&l}5 zjW5+6FHM}d{`}nN7e24!Za5w^oiTmvrcXAl%2B?=a+8pmR$c^Mu7P%%TpLc8Cf>m;YmcOABuxT zO^5Pfabv?$R|I7eK1Qkpi##j^&N0|10a4_T39&OHeV2HRAK7o>zHL%*jn^XASOMRw zKPO;Wvf{yazP&9qSEM|mS@jt)XZOm{Lyx=_s;uV4E!!|LF^J?6%I^WeYFT$?-L zMVe_{9t!kfR*E*Iw780Ih+Z8UlyFs_7CMxEbUquUgbt0Z%TYhLaM#fmH2dA!W|rcW zhMV%b=RyXgA6+-J-{PcGhkak%Usa!{@Lsh!5w({@9vgF9aVAGJqPjZv<6Bc*%m>iO zOVUq@qn@o!ygFpq$;yPlMwJnHwe@>oNaOjdnzz2K^f{}JS@!kYKcT0xm#Nhcoftm< zv5lvSPro-;PrLDR6&kX2&5nQWsX4KF?HQr!;ar!aEm!7zGQD#D>rIz-1hHlA$FD8@ z{-+VD+lx?Z$*y|ua|2eQ%3=HJP}|zmk?TU=;UvU7KI))nL(9{Ni+vIE(w4C!-I{5a zYB#n&9aFiM)qr%h59GE~e88&ST@PV zhUGuCU1ysTS0axeijeC()AvhS_SMsVX4V#pA1zt4acK$~KIZVVgLcK2)$!NQdM)%c zyXL1Y1t!-yXTA_mJky3!W8=k)Pfh5{2_{yP+Z#JSxwZ9gADqiQk$AXhXWh(K>ew4N z%eHU+$mQcAzt-8qVriTV6M8%mxrL2I0Ze%VieJGv5;|lmLKVS_TX#M2LWr*Mz1eHd zJ$-uV3pKOm3P+xP=L7Mf&yA4>;&!a(9(k5norMOkdKHZWS3f!6s7xT4y~r}5geMm) zLUY!xJgBbT+rA)n?uVBdx999lUpi??)LX^Eg6CWxU&QxjEU7ph<+5ICMFVT9&ptJCaLt&H z^8-s4fAg4ELf}3`t8dPB&3w0VF>}?~X>oM#`5OwB{V>$~-1bQqmmYXvN5Mxcr<+{Y zZj}VTUR8SlO>fg4T>POM@~_!F>V;QT7jOQndeG=`y!?VQbWX$GX~t8D(_7#8^6I*Y zx$nwr@(vC*A#H3{s5?6rF=y`eq_gw3&p7sapYb;GPo_O+C5WM-oyFGn+55>CMxh(SMX~V zNuP?_60{(8$*B6)QLf0pKi!mr&msX^FiySQI+Zb6oAnlm_nev2FJs%xv01TNf{j zOZy^9pO-%I=4&F?OIy~&%T$w(JQUl2e`_$-S^s|*{QGVlor-0s*kv8V JUbg-Y_%F!Y(gy$l literal 0 HcmV?d00001 diff --git a/RevealInFinderBarSmall.png b/RevealInFinderBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..aabe8b4e160fe52a5d7fa4cce91f99f62d336543 GIT binary patch literal 1410 zcmV-|1%3L7P)Yb)89Fb@XPXBZqS1zALV~mW9^v})B6*%&)>*DQq z-i2wJu*?vqrlxT8=+}S*bUeWDXh1o)!ja%P9*?hWZ*MrVCUTeEg>(5-u3!?2>LK@+4zba=gYY0T*FiibvrhSx7x;qXCHtb&v-sU;&YLq^DP z+)4hqpZ`ke2ES{e$le1#jQ@69%F}5nf8{(gE#-w-DbHs(XQUkG`s5!ux%-W`eY;p4ze z*@dC?Phoz+!_3WT<|T||GDV8~06{z+M!ry~3Lyge^&r)ddaew8dfvgzd>ylSU}Ew* zzW8J>rmo$>-I9gz%TqXa>KI11y-WiFj;rCo$NTZsmq(zHg^DduXxC{~aw)G(I?3I*nX zd5YOYQ1Z~w$UPO+t1j|68@g~wiD0&p7#`gR&FtXMdCXk>1v__aCw&&xVxv}b@Y?P@ z2!~sUsEm4DKnSv7cyQ|SpE6Z)aXcoSn*@BKXhB=*Y5t%gH=lv-K7^!3+ zs|QBtOu(kR12G0-lTFfVcEHbdS3s8@S4QwGr9hNbyfB|eXIl&_dLC16p=$;_;ls9T zO1*T(pm_Iv$z)4tSPnrDl~RJ>T|MfH(eO>Ba0{`h38z{{wNeDP!DJ2$!whKgg$x|| z!CDoYSRTQmWf9Oqor1n-z(d#yVdDG*-rute9xGnBHa__9AO_cNK($t-LxoG@Ua>gk zG6)nMg1iRdSuB4hQ)+c`UP1Sx8_|(m13hG7VJ?l##m~^%+D2zSV=-VxEGD^5irpZ9 zWf2G(RuC0}^w=T#u#g(qig-s4^U#J^>k3$r7%HU#5?u+jcO;mDD*l|ghEqR&Pvtmx zb=P}=@#e$tJ^}?z9dx87mRN`EwPVQM{Fz2u5p7Mvinb%nbul{)w|D~wKiZ32_6|zr z0=l|-uzAZ4xIFMQIudd@1oWy7EJNCer=CS;??$+lSvZ9>?D8$RwLFjQ9BS1fEEZ{B z{~$JQ+K!&S)kt*r26C-Z1ge02-&+O&zo-N$it2V5GNd!=1fyRCgNGLT5*tbcv*|Io znIqW#!cJCmoJLEiR7yc|{Xi7*Z+)iWKr#YL^#otlff9kBDpZd!s-S&Vh6ck7a}mKp zzRV+J65T7GfWwBfr1HSH=X#26YpL$;^^}&D#PFMDq+^|GJ^H%hh5K2k(Jj~ zM{S%EjqgkEw59w18i8}eFt)NU|4xJhcnCv97NhYEyth3p2ik*f{!4%X0Aw86&i1rH QRsaA107*qoM6N<$f}lR3C;$Ke literal 0 HcmV?d00001 diff --git a/RoundedView.h b/RoundedView.h new file mode 100644 index 0000000..88f7b37 --- /dev/null +++ b/RoundedView.h @@ -0,0 +1,15 @@ +// +// RoundedView.h +// RoundedFloatingPanel +// +// Created by Matt Gemmell on Thu Jan 08 2004. +// +// + + +#import + +@interface RoundedView : NSView +{ +} +@end diff --git a/RoundedView.m b/RoundedView.m new file mode 100644 index 0000000..69b582c --- /dev/null +++ b/RoundedView.m @@ -0,0 +1,55 @@ +// +// RoundedView.m +// RoundedFloatingPanel +// +// Created by Matt Gemmell on Thu Jan 08 2004. +// +// + + +#import + +@implementation RoundedView + + +- (void)drawRect:(NSRect)rect +{ + + NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.35]; + NSRect bgRect = rect; + int minX = NSMinX(bgRect); + int midX = NSMidX(bgRect); + int maxX = NSMaxX(bgRect); + int minY = NSMinY(bgRect); + int midY = NSMidY(bgRect); + int maxY = NSMaxY(bgRect); + float radius = 25.0; // correct value to duplicate Panther's App Switcher + NSBezierPath *bgPath = [NSBezierPath bezierPath]; + + // Bottom edge and bottom-right curve + [bgPath moveToPoint:NSMakePoint(midX, minY)]; + [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY) + toPoint:NSMakePoint(maxX, midY) + radius:radius]; + + // Right edge and top-right curve + [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, maxY) + toPoint:NSMakePoint(midX, maxY) + radius:radius]; + + // Top edge and top-left curve + [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY) + toPoint:NSMakePoint(minX, midY) + radius:radius]; + + // Left edge and bottom-left curve + [bgPath appendBezierPathWithArcFromPoint:bgRect.origin + toPoint:NSMakePoint(midX, minY) + radius:radius]; + [bgPath closePath]; + + [bgColor set]; + [bgPath fill]; +} + +@end diff --git a/RoundedViewWhiteText.h b/RoundedViewWhiteText.h new file mode 100644 index 0000000..a709bdc --- /dev/null +++ b/RoundedViewWhiteText.h @@ -0,0 +1,26 @@ +// +// RoundedViewWhiteText.h +// SproutedInterface +// +// Created by Philip Dow on 6/12/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#import + +@interface RoundedViewWhiteText : RoundedView { + + NSColor *_color; + NSString *_title; +} + +- (NSColor*) color; +- (void) setColor:(NSColor*)aColor; + +- (NSString*) title; +- (void) setTitle:(NSString*)text; + +@end diff --git a/RoundedViewWhiteText.m b/RoundedViewWhiteText.m new file mode 100644 index 0000000..72f45a1 --- /dev/null +++ b/RoundedViewWhiteText.m @@ -0,0 +1,84 @@ +// +// RoundedViewWhiteText.m +// SproutedInterface +// +// Created by Philip Dow on 6/12/06. +// Copyright 2006 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +#define kInset 10 + +@implementation RoundedViewWhiteText + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Initialization code here. + _title = [[NSString alloc] init]; + _color = [[NSColor colorWithCalibratedWhite:1.0 alpha:1.0] retain]; + } + return self; +} + +- (void) dealloc { + [_title release]; + [_color release]; + [super dealloc]; +} + +#pragma mark - + +- (void)drawRect:(NSRect)rect { + [super drawRect:rect]; + + float font_size = 160.0; + NSString *string = [self title]; + NSFont *font = [NSFont labelFontOfSize:font_size]; + + NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + font, NSFontAttributeName, [self color], NSForegroundColorAttributeName, nil]; + + NSSize bds_size = [self bounds].size; + + NSSize string_size = [string sizeWithAttributes:attrs]; + NSPoint origin = NSMakePoint(bds_size.width/2 - string_size.width/2, bds_size.height/2 - string_size.height/2); + + while ( origin.x < kInset ) { + + font_size-=4; + font = [NSFont labelFontOfSize:font_size]; + [attrs setObject:font forKey:NSFontAttributeName]; + + string_size = [string sizeWithAttributes:attrs]; + origin = NSMakePoint(bds_size.width/2 - string_size.width/2, bds_size.height/2 - string_size.height/2); + + } + + [string drawAtPoint:origin withAttributes:attrs]; + +} + +#pragma mark - + +- (NSColor*) color { return _color; } + +- (void) setColor:(NSColor*)aColor { + if ( _color != aColor ) { + [_color release]; + _color = [aColor copyWithZone:[self zone]]; + } +} + +- (NSString*) title { return _title; } + +- (void) setTitle:(NSString*)text { + if ( _title != text ) { + [_title release]; + _title = [text copyWithZone:[self zone]]; + } +} + +@end diff --git a/SafariBarSmall.png b/SafariBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..d028cefc5babaec8a1db4bc90326bf0e0dc9170c GIT binary patch literal 1625 zcmV-f2B!ImP)q$gGRCwBq zR%>iiWf*>XPJ7yO+Maf6>1B6zVUt^&&T)&#W@7OA$4Lx7M8!m+iNP2Q!~h|v1Q3nJ zH4<+@5CjZS2;eZ$333apjBRDIjk0xXy9@2wwLRVGIc@z8!DVtAZ*tO{b9$cl`=0lC zpZBA(*(~lCR;#tDva+%vFE4Kaxm798SeAuat;STLU{h25iKgkYL?V$SptaZyS1a~MAKg$kLSq!zE>&RP^naR zyqGh0&I{|-u6wV(zJ9UK=Y!AJhj=Uoil$+=+fh_l1chCaq}kYbL?&u-7NvN zV#SIbBvyBKb>aB&V@MG;Sk3^AhCzmaro-2*OXI;@s_l$RDGAxO~aGz1}wzTN={qXBrXbRv_M(a_Ma zP83CTb93|i_oS${ws!ST`}Tcy;`b(adjnw1l_)E(fL6!AX*D7iPhm8Ygx;tnE29t_ zmvQ~72PP(jK)?qr%i-XG1FJeaJ9pkekyfiM*}Z#rTQ-|9ws%}XR8@@P(h8_))ybm#q68t(LsxMjZAX(Dr$8qNJ z^754v1-q5(I=GCy?T!tniLuXQh;9}v- zd`NN@t6XQWOgx8%E1zP!@mcg2)q$6im|bDVI88WY1r+2vk&~MK(E*5 zQxwJI=9nO4If!Zr!7!0xOu~>Tf~X&T!8D#^`%v%Sg&kuBSh#5mDg_#cPW9q!e;iUK zgF>SQxjAOU5<#9cX30bXg?o#|0^VSNe+(EP;EQKF(K;}OHA`oqz^+I0)i5?cGY|Ve zZp8_EHH2UaN8LUM<5>s^qIW{bQqnJWhJoMjR}{ogP(&&ob2^>GV-lEE!oxYll7cxf zL|z~Egi$yw!}U@be*WbMzE&;4;<{Sccr^^u46tg|7>g3g#!}F+6y&5#BpbMiIZ@z6dc$-$a5;Cez>6-qxcgR-mV4R6A%0GzG0C2P+pj(CTS}D`>}6 zwgj}6Ml{VJlF`9n=19{Spf_-sU&M;y#zBjS*GI2lc)B3yS~xfsX^jpknt?GL$AXq3w_ye+WBrF)(BbI-spSTO6};=f5d>jp+vUqe@pxjbASAKsjn}aC ziHFb~%iz2}if~$l+L%R+gNKddQOfG!cDu30^%YuLS};5`^ie96`gW>;LlZw)YqLAn z6X|LfEn0}D>Xu;k%qr3^IzX1^@s6z#LUx00009a7bBm000XU z000XU0RWnu7ytkO1ZP1_K>z^Q>-8KIssI20AY({UO#lFEVgLYiHUI$gsQ>_spa1}G zqW}Qv%m4r|9smFsn(WV1od5s=LrFwIRCwCtmd|S2KoG{iZ&tF44!*i9t42XPp21|%T68^4;}aD(A3~~JU%9QIU0@P;c$pvuh$4@ zKA$6Mx7!~FgF$?Fc!(y4h(PA^`TOB;1cE-NBuIukybJ_ucvdZF5Y~Rx3WYFWh!v%2 z+Uoavr9&+SYk`U@Yn*3+RXN)3)Jz)xO&Iy#r%_dLbaeD$z{zCtb{I*_X0un- z9Nf~O+wHyx`4RExd&{l~XI!<=)lS%%D7s4C9S&t7N*`mDXxdbb^Btwm}r zR{07dQa^&A00~tE=^6S8yD{)&i=CjD$e`h+-u@2-$)Xq(Z@G?d|pkEX$Ty zx(s5Zn5F9ae5|j6A+kb21(g0=^*T#f(4!~{FaY^#g*<;mB*quHTvGu0^!TFFTUnNi zEN7y@ub41d)(j-_JoleyWGd4ym_e*ww>5pOzf{rUc8sXg>A1VQq_w-d8`9_VT&1iv zDNtSp%T@bI2vof%16b+P9E(8q_V&Ks+cSQ&q0SyaZF$U4j&d%rC+uO^hr>A&-e;@sRztZ=Jt?h8LnQk=P&27tSvz<<- z7x(w~CrOfY7K=r5ZDuW8Utb@PJO-NkZ~Qd?(74rLOh9Zz00000NkvXXu0mjf;h{a! literal 0 HcmV?d00001 diff --git a/SmallerDisabled.png b/SmallerDisabled.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7091954589ba18b4abfe81b5ba917aa3273a96 GIT binary patch literal 696 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 WmP0ar+%XCO0000 + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXRunSessionModule + Name + Run Log + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + Description + DefaultDescriptionKey + DockingSystemVisible + + Extension + mode1 + FavBarConfig + + PBXProjectModuleGUID + E337CA260CA1AFCB00797802 + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.mode1 + MajorVersion + 31 + MinorVersion + 1 + Name + Default + Notifications + + OpenEditors + + PerspectiveWidths + + -1 + -1 + + Perspectives + + + ChosenToolbarItems + + active-target-popup + active-buildstyle-popup + action + NSToolbarFlexibleSpaceItem + buildOrClean + build-and-runOrDebug + com.apple.ide.PBXToolbarStopButton + get-info + toggle-editor + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProjectWithEditor + Identifier + perspective.project + IsVertical + + Layout + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 320 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 0867D691FE84028FC02AAC07 + 08FB77AEFE84172EC02AAC07 + E337D4020CA1E4C000797802 + 32C88DFF0371C24200C91783 + 089C1665FE841158C02AAC07 + E337CBE90CA1B2F300797802 + E337E4110CA3780000797802 + 0867D69AFE84028FC02AAC07 + 1C37FBAC04509CD000000102 + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {320, 794}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {337, 812}} + GroupTreeTableConfiguration + + MainColumn + 320 + + RubberWindowFrame + -1429 119 1389 853 -1920 -150 1920 1200 + + Module + PBXSmartGroupTreeModule + Proportion + 337pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20306471E060097A5F4 + PBXProjectModuleLabel + DocumentMakerController.m + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CE0B20406471E060097A5F4 + PBXProjectModuleLabel + DocumentMakerController.m + _historyCapacity + 0 + bookmark + E3541A510CB3657C00B51B6D + history + + E30470330CAD7125006A17BB + E30470340CAD7125006A17BB + E30470350CAD7125006A17BB + E30470370CAD7125006A17BB + E30470380CAD7125006A17BB + E3540DC20CADBFBF00B51B6D + E3540E540CADCB4800B51B6D + E3540E550CADCB4800B51B6D + E3540E560CADCB4800B51B6D + E3540F310CB1DB6F00B51B6D + E35411970CB1F7D900B51B6D + E354196C0CB30A5000B51B6D + E35419710CB30A5000B51B6D + + prevStack + + E334F8E60CAB53B600A740DF + E304703B0CAD7125006A17BB + E304703C0CAD7125006A17BB + E304703D0CAD7125006A17BB + E304703F0CAD7125006A17BB + E30470400CAD7125006A17BB + E30470440CAD7125006A17BB + E30470640CAD7125006A17BB + E3540DC50CADBFBF00B51B6D + E3540DC60CADBFBF00B51B6D + E3540E590CADCB4800B51B6D + E3540E5B0CADCB4800B51B6D + E3540F340CB1DB6F00B51B6D + + + SplitCount + 1 + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {1047, 624}} + RubberWindowFrame + -1429 119 1389 853 -1920 -150 1920 1200 + + Module + PBXNavigatorGroup + Proportion + 624pt + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CE0B20506471E060097A5F4 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{0, 629}, {1047, 183}} + RubberWindowFrame + -1429 119 1389 853 -1920 -150 1920 1200 + + Module + XCDetailModule + Proportion + 183pt + + + Proportion + 1047pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDetailModule + + TableOfContents + + E3541A520CB3657C00B51B6D + 1CE0B1FE06471DED0097A5F4 + E3541A530CB3657C00B51B6D + 1CE0B20306471E060097A5F4 + 1CE0B20506471E060097A5F4 + + ToolbarConfiguration + xcode.toolbar.config.default + + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.morph + IsVertical + 0 + Layout + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + + PBXProjectModuleGUID + 11E0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 186 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 29B97314FDCFA39411CA2CEA + 1C37FABC05509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {186, 337}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 1 + XCSharingToken + com.apple.Xcode.GFSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {203, 355}} + GroupTreeTableConfiguration + + MainColumn + 186 + + RubberWindowFrame + 373 269 690 397 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 100% + + + Name + Morph + PreferredWidth + 300 + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + + TableOfContents + + 11E0B1FE06471DED0097A5F4 + + ToolbarConfiguration + xcode.toolbar.config.default.short + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? + WindowJustification + 5 + WindowOrderList + + /Users/phildow/Code/Projects/Sprouted Interface/Sprouted Interface.xcodeproj + + WindowString + -1429 119 1389 853 -1920 -150 1920 1200 + WindowTools + + + FirstTimeWindowDisplayed + + Identifier + windowTool.build + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {1238, 361}} + RubberWindowFrame + 89 327 1238 643 0 0 1680 1028 + + Module + PBXNavigatorGroup + Proportion + 361pt + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{0, 366}, {1238, 236}} + RubberWindowFrame + 89 327 1238 643 0 0 1680 1028 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 602pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + + TableOfContents + + E337CC370CA1B42900797802 + E3540E4D0CADCB3400B51B6D + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.build + WindowString + 89 327 1238 643 0 0 1680 1028 + WindowToolGUID + E337CC370CA1B42900797802 + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debugger + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {316, 183}} + {{316, 0}, {378, 183}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 183}} + {{0, 183}, {694, 198}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 381}} + RubberWindowFrame + -1408 527 694 422 -1920 -150 1920 1200 + + Module + PBXDebugSessionModule + Proportion + 381pt + + + Proportion + 381pt + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + + TableOfContents + + 1CD10A99069EF8BA00B06720 + E3540F3F0CB1DB6F00B51B6D + 1C162984064C10D400B95A72 + E3540F400CB1DB6F00B51B6D + E3540F410CB1DB6F00B51B6D + E3540F420CB1DB6F00B51B6D + E3540F430CB1DB6F00B51B6D + E3540F440CB1DB6F00B51B6D + E3540F450CB1DB6F00B51B6D + + ToolbarConfiguration + xcode.toolbar.config.debug + WindowString + -1408 527 694 422 -1920 -150 1920 1200 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + + + + FirstTimeWindowDisplayed + + Identifier + windowTool.find + IsVertical + + Layout + + + Dock + + + Dock + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + RBSplitView.h + StatusBarVisibility + + + GeometryConfiguration + + Frame + {{0, 0}, {1187, 426}} + RubberWindowFrame + 270 141 1187 835 0 0 1680 1028 + + Module + PBXNavigatorGroup + Proportion + 1187pt + + + Proportion + 426pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{0, 431}, {1187, 363}} + RubberWindowFrame + 270 141 1187 835 0 0 1680 1028 + + Module + PBXProjectFindModule + Proportion + 363pt + + + Proportion + 794pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + + TableOfContents + + 1C530D57069F1CE1000CFCEE + E3540E510CADCB3400B51B6D + E3540E520CADCB3400B51B6D + 1CDD528C0622207200134675 + 1CD0528E0623707200166675 + + WindowString + 270 141 1187 835 0 0 1680 1028 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + MENUSEPARATOR + + + Identifier + windowTool.debuggerConsole + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {440, 358}} + RubberWindowFrame + 650 41 440 400 0 0 1280 1002 + + Module + PBXDebugCLIModule + Proportion + 358pt + + + Proportion + 358pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAAD065D492600B07095 + 1C78EAAE065D492600B07095 + 1C78EAAC065D492600B07095 + + WindowString + 650 41 440 400 0 0 1280 1002 + + + Identifier + windowTool.run + Layout + + + Dock + + + ContentConfiguration + + LauncherConfigVersion + 3 + PBXProjectModuleGUID + 1CD0528B0623707200166675 + PBXProjectModuleLabel + Run + Runner + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {493, 167}} + {{0, 176}, {493, 267}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {405, 443}} + {{414, 0}, {514, 443}} + + + + + GeometryConfiguration + + Frame + {{0, 0}, {460, 159}} + RubberWindowFrame + 316 696 459 200 0 0 1280 1002 + + Module + PBXRunSessionModule + Proportion + 159pt + + + Proportion + 159pt + + + Name + Run Log + ServiceClasses + + PBXRunSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C0AD2B3069F1EA900FABCE6 + 1C0AD2B4069F1EA900FABCE6 + 1CD0528B0623707200166675 + 1C0AD2B5069F1EA900FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.run + WindowString + 316 696 459 200 0 0 1280 1002 + WindowToolGUID + 1C0AD2B3069F1EA900FABCE6 + WindowToolIsVisible + 0 + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scm + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 2 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpoints + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimator + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 100% + + + Proportion + 100% + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {374, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {630, 331}} + MembersFrame + {{0, 105}, {374, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 97 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 385 179 630 352 0 0 1440 878 + + Module + PBXClassBrowserModule + Proportion + 332pt + + + Proportion + 332pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C0AD2AF069F1E9B00FABCE6 + 1C0AD2B0069F1E9B00FABCE6 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 385 179 630 352 0 0 1440 878 + WindowToolGUID + 1C0AD2AF069F1E9B00FABCE6 + WindowToolIsVisible + 0 + + + + diff --git a/Sprouted Interface.xcodeproj/project.pbxproj b/Sprouted Interface.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fe097fc --- /dev/null +++ b/Sprouted Interface.xcodeproj/project.pbxproj @@ -0,0 +1,1492 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 723F4F110F6F0BA400212DFE /* SproutedAboutBox.nib in Resources */ = {isa = PBXBuildFile; fileRef = 723F4F0F0F6F0BA400212DFE /* SproutedAboutBox.nib */; }; + 724BAC8E0DB9288000DDE79D /* LinkController.h in Headers */ = {isa = PBXBuildFile; fileRef = 724BAC8C0DB9288000DDE79D /* LinkController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 724BAC8F0DB9288000DDE79D /* LinkController.m in Sources */ = {isa = PBXBuildFile; fileRef = 724BAC8D0DB9288000DDE79D /* LinkController.m */; }; + 724BACA50DB928F500DDE79D /* InsertLink.nib in Resources */ = {isa = PBXBuildFile; fileRef = 724BACA30DB928F500DDE79D /* InsertLink.nib */; }; + 724BACCC0DB929E600DDE79D /* StatsController.h in Headers */ = {isa = PBXBuildFile; fileRef = 724BACCA0DB929E600DDE79D /* StatsController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 724BACCD0DB929E600DDE79D /* StatsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 724BACCB0DB929E600DDE79D /* StatsController.m */; }; + 724BAD680DB92A6200DDE79D /* Stats.nib in Resources */ = {isa = PBXBuildFile; fileRef = 724BAD660DB92A6200DDE79D /* Stats.nib */; }; + 7269D0140DD10821005AD452 /* PDTokenField.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269D0100DD10821005AD452 /* PDTokenField.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7269D0150DD10821005AD452 /* PDTokenField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269D0110DD10821005AD452 /* PDTokenField.m */; }; + 7269D0160DD10821005AD452 /* PDTokenFieldCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269D0120DD10821005AD452 /* PDTokenFieldCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7269D0170DD10821005AD452 /* PDTokenFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269D0130DD10821005AD452 /* PDTokenFieldCell.m */; }; + 7269D0A00DD10C75005AD452 /* PDTableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269D09C0DD10C75005AD452 /* PDTableView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7269D0A10DD10C75005AD452 /* PDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269D09D0DD10C75005AD452 /* PDTableView.m */; }; + 7269D0A20DD10C75005AD452 /* PDOutlineView.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269D09E0DD10C75005AD452 /* PDOutlineView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7269D0A30DD10C75005AD452 /* PDOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269D09F0DD10C75005AD452 /* PDOutlineView.m */; }; + 727F6F580F462A4E00CFCECB /* SproutedAnchoredDocumentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 727F6F560F462A4E00CFCECB /* SproutedAnchoredDocumentView.m */; }; + 727F6F590F462A4E00CFCECB /* SproutedAnchoredDocumentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 727F6F570F462A4E00CFCECB /* SproutedAnchoredDocumentView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 728868ED0CC689D700733960 /* PDRankCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 728868EB0CC689D700733960 /* PDRankCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 728868EE0CC689D700733960 /* PDRankCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 728868EC0CC689D700733960 /* PDRankCell.m */; }; + 728868F10CC689E500733960 /* PDBlueHighlightTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 728868EF0CC689E500733960 /* PDBlueHighlightTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 728868F20CC689E500733960 /* PDBlueHighlightTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 728868F00CC689E500733960 /* PDBlueHighlightTextCell.m */; }; + 72886AED0CC7C5FB00733960 /* PDFontPreview.h in Headers */ = {isa = PBXBuildFile; fileRef = 72886AE90CC7C5FB00733960 /* PDFontPreview.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72886AEE0CC7C5FB00733960 /* PDFontPreview.m in Sources */ = {isa = PBXBuildFile; fileRef = 72886AEA0CC7C5FB00733960 /* PDFontPreview.m */; }; + 72886AEF0CC7C5FB00733960 /* PDFontDisplay.h in Headers */ = {isa = PBXBuildFile; fileRef = 72886AEB0CC7C5FB00733960 /* PDFontDisplay.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72886AF00CC7C5FB00733960 /* PDFontDisplay.m in Sources */ = {isa = PBXBuildFile; fileRef = 72886AEC0CC7C5FB00733960 /* PDFontDisplay.m */; }; + 72886B4E0CC7C70100733960 /* PDColorWell.h in Headers */ = {isa = PBXBuildFile; fileRef = 72886B4C0CC7C70100733960 /* PDColorWell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72886B4F0CC7C70100733960 /* PDColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = 72886B4D0CC7C70100733960 /* PDColorWell.m */; }; + 72886B650CC7C7ED00733960 /* JRLRFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 72886B630CC7C7ED00733960 /* JRLRFooter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72886B660CC7C7ED00733960 /* JRLRFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 72886B640CC7C7ED00733960 /* JRLRFooter.m */; }; + 72886B7D0CC7C92600733960 /* DragView.h in Headers */ = {isa = PBXBuildFile; fileRef = 72886B7B0CC7C92600733960 /* DragView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72886B7E0CC7C92600733960 /* DragView.m in Sources */ = {isa = PBXBuildFile; fileRef = 72886B7C0CC7C92600733960 /* DragView.m */; }; + 72887A9E0CCC4EDB00733960 /* more.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A970CCC4EDB00733960 /* more.tif */; }; + 72887A9F0CCC4EDB00733960 /* tabcloseback.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A980CCC4EDB00733960 /* tabcloseback.tif */; }; + 72887AA00CCC4EDB00733960 /* tabclosebackdown.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A990CCC4EDB00733960 /* tabclosebackdown.tif */; }; + 72887AA10CCC4EDB00733960 /* tabclosebackroll.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A9A0CCC4EDB00733960 /* tabclosebackroll.tif */; }; + 72887AA20CCC4EDB00733960 /* tabclosefront.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A9B0CCC4EDB00733960 /* tabclosefront.tif */; }; + 72887AA30CCC4EDB00733960 /* tabclosefrontdown.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A9C0CCC4EDB00733960 /* tabclosefrontdown.tif */; }; + 72887AA40CCC4EDB00733960 /* tabclosefrontroll.tif in Resources */ = {isa = PBXBuildFile; fileRef = 72887A9D0CCC4EDB00733960 /* tabclosefrontroll.tif */; }; + 7298530D0CD27ECD00BB4A53 /* PDFontPreview.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7298530B0CD27ECD00BB4A53 /* PDFontPreview.strings */; }; + 729853310CD27FAA00BB4A53 /* PDTabsView.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7298532F0CD27FAA00BB4A53 /* PDTabsView.strings */; }; + 7298533D0CD27FF100BB4A53 /* PDFavoritesBar.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7298533B0CD27FF100BB4A53 /* PDFavoritesBar.strings */; }; + 72A7DCD20CCD0C1C009ED8AC /* EtchedPopUpButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 72A7DCCE0CCD0C1C009ED8AC /* EtchedPopUpButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72A7DCD30CCD0C1C009ED8AC /* EtchedPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A7DCCF0CCD0C1C009ED8AC /* EtchedPopUpButton.m */; }; + 72A7DCD40CCD0C1C009ED8AC /* EtchedPopUpButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 72A7DCD00CCD0C1C009ED8AC /* EtchedPopUpButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72A7DCD50CCD0C1C009ED8AC /* EtchedPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A7DCD10CCD0C1C009ED8AC /* EtchedPopUpButtonCell.m */; }; + 72A7DE650CCD1CD0009ED8AC /* EmailBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7DE640CCD1CD0009ED8AC /* EmailBarSmall.png */; }; + 72A7DE6D0CCD1D9A009ED8AC /* ABBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7DE6C0CCD1D9A009ED8AC /* ABBarSmall.png */; }; + 72A7DE710CCD1DA3009ED8AC /* ComposeMailBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7DE700CCD1DA3009ED8AC /* ComposeMailBarSmall.png */; }; + 72A7DE750CCD1DDD009ED8AC /* SafariBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7DE740CCD1DDD009ED8AC /* SafariBarSmall.png */; }; + 72A7E09F0CCD574C009ED8AC /* PolishedWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 72A7E09D0CCD574C009ED8AC /* PolishedWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72A7E0A00CCD574C009ED8AC /* PolishedWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A7E09E0CCD574C009ED8AC /* PolishedWindow.m */; }; + 72A7E0AE0CCD57DA009ED8AC /* flat_bottom_left.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0A60CCD57DA009ED8AC /* flat_bottom_left.png */; }; + 72A7E0AF0CCD57DA009ED8AC /* flat_bottom_middle.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0A70CCD57DA009ED8AC /* flat_bottom_middle.png */; }; + 72A7E0B00CCD57DA009ED8AC /* flat_bottom_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0A80CCD57DA009ED8AC /* flat_bottom_right.png */; }; + 72A7E0B10CCD57DA009ED8AC /* flat_middle_left.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0A90CCD57DA009ED8AC /* flat_middle_left.png */; }; + 72A7E0B20CCD57DA009ED8AC /* flat_middle_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0AA0CCD57DA009ED8AC /* flat_middle_right.png */; }; + 72A7E0B30CCD57DA009ED8AC /* flat_top_left.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0AB0CCD57DA009ED8AC /* flat_top_left.png */; }; + 72A7E0B40CCD57DA009ED8AC /* flat_top_middle.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0AC0CCD57DA009ED8AC /* flat_top_middle.png */; }; + 72A7E0B50CCD57DA009ED8AC /* flat_top_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 72A7E0AD0CCD57DA009ED8AC /* flat_top_right.png */; }; + 72C95BD00DBE48B3005440D5 /* PDPhotoView.h in Headers */ = {isa = PBXBuildFile; fileRef = 72C95BCC0DBE48B3005440D5 /* PDPhotoView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72C95BD10DBE48B3005440D5 /* PDPhotoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C95BCD0DBE48B3005440D5 /* PDPhotoView.m */; }; + 72C95BD20DBE48B3005440D5 /* MUPhotoCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 72C95BCE0DBE48B3005440D5 /* MUPhotoCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72C95BD30DBE48B3005440D5 /* MUPhotoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 72C95BCF0DBE48B3005440D5 /* MUPhotoCell.m */; }; + 72FB5B6A0E59E1D900BB20D7 /* SproutedAboutBoxController.h in Headers */ = {isa = PBXBuildFile; fileRef = 72FB5B680E59E1D900BB20D7 /* SproutedAboutBoxController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 72FB5B6B0E59E1D900BB20D7 /* SproutedAboutBoxController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72FB5B690E59E1D900BB20D7 /* SproutedAboutBoxController.m */; }; + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; + E3046CF80CACE76E006A17BB /* DocumentMakerController.h in Headers */ = {isa = PBXBuildFile; fileRef = E3046CF60CACE76E006A17BB /* DocumentMakerController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3046CF90CACE76E006A17BB /* DocumentMakerController.m in Sources */ = {isa = PBXBuildFile; fileRef = E3046CF70CACE76E006A17BB /* DocumentMakerController.m */; }; + E337CA370CA1B05100797802 /* SproutedInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA330CA1B05100797802 /* SproutedInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA380CA1B05100797802 /* PDPredicateBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA340CA1B05100797802 /* PDPredicateBuilder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA390CA1B05100797802 /* MediaContentController.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA350CA1B05100797802 /* MediaContentController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA3A0CA1B05100797802 /* MediaContentController.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA360CA1B05100797802 /* MediaContentController.m */; }; + E337CA410CA1B05800797802 /* TransparentWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA3B0CA1B05800797802 /* TransparentWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA420CA1B05800797802 /* TransparentWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA3C0CA1B05800797802 /* TransparentWindow.m */; }; + E337CA430CA1B05800797802 /* AppleScriptAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA3D0CA1B05800797802 /* AppleScriptAlert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA440CA1B05800797802 /* AppleScriptAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA3E0CA1B05800797802 /* AppleScriptAlert.m */; }; + E337CA450CA1B05800797802 /* IntegrationCopyFiles.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA3F0CA1B05800797802 /* IntegrationCopyFiles.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA460CA1B05800797802 /* IntegrationCopyFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA400CA1B05800797802 /* IntegrationCopyFiles.m */; }; + E337CA490CA1B06100797802 /* HUDWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA470CA1B06100797802 /* HUDWindow.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA4A0CA1B06100797802 /* HUDWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA480CA1B06100797802 /* HUDWindow.m */; }; + E337CA4F0CA1B06A00797802 /* PDFavorite.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA4B0CA1B06A00797802 /* PDFavorite.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA500CA1B06A00797802 /* PDFavorite.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA4C0CA1B06A00797802 /* PDFavorite.m */; }; + E337CA510CA1B06A00797802 /* PDFavoritesBar.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA4D0CA1B06A00797802 /* PDFavoritesBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA520CA1B06A00797802 /* PDFavoritesBar.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA4E0CA1B06A00797802 /* PDFavoritesBar.m */; }; + E337CA5B0CA1B07400797802 /* PDMediaBar.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA530CA1B07400797802 /* PDMediaBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA5C0CA1B07400797802 /* PDMediaBar.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA540CA1B07400797802 /* PDMediaBar.m */; }; + E337CA5D0CA1B07400797802 /* PDMediabarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA550CA1B07400797802 /* PDMediabarItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA5E0CA1B07400797802 /* PDMediabarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA560CA1B07400797802 /* PDMediabarItem.m */; }; + E337CA5F0CA1B07400797802 /* NewMediabarItemController.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA570CA1B07400797802 /* NewMediabarItemController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA600CA1B07400797802 /* NewMediabarItemController.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA580CA1B07400797802 /* NewMediabarItemController.m */; }; + E337CA610CA1B07400797802 /* MediabarItemApplicationPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA590CA1B07400797802 /* MediabarItemApplicationPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA620CA1B07400797802 /* MediabarItemApplicationPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA5A0CA1B07400797802 /* MediabarItemApplicationPicker.m */; }; + E337CA6F0CA1B09F00797802 /* PDToolbar.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA670CA1B09F00797802 /* PDToolbar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA700CA1B09F00797802 /* PDToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA680CA1B09F00797802 /* PDToolbar.m */; }; + E337CA710CA1B09F00797802 /* PDPopUpButtonToolbarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA690CA1B09F00797802 /* PDPopUpButtonToolbarItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA720CA1B09F00797802 /* PDPopUpButtonToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA6A0CA1B09F00797802 /* PDPopUpButtonToolbarItem.m */; }; + E337CA730CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA6B0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA740CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA6C0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.m */; }; + E337CA750CA1B09F00797802 /* PDSelfValidatingToolbarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA6D0CA1B09F00797802 /* PDSelfValidatingToolbarItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA760CA1B09F00797802 /* PDSelfValidatingToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA6E0CA1B09F00797802 /* PDSelfValidatingToolbarItem.m */; }; + E337CA7F0CA1B0BF00797802 /* PDDateDisplayCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA790CA1B0BF00797802 /* PDDateDisplayCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA800CA1B0BF00797802 /* PDDateDisplayCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA7A0CA1B0BF00797802 /* PDDateDisplayCell.m */; }; + E337CA810CA1B0BF00797802 /* PDHorizontallyCenteredText.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA7B0CA1B0BF00797802 /* PDHorizontallyCenteredText.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA820CA1B0BF00797802 /* PDHorizontallyCenteredText.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA7C0CA1B0BF00797802 /* PDHorizontallyCenteredText.m */; }; + E337CA830CA1B0BF00797802 /* ImageAndTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA7D0CA1B0BF00797802 /* ImageAndTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CA840CA1B0BF00797802 /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA7E0CA1B0BF00797802 /* ImageAndTextCell.m */; }; + E337CA9F0CA1B0CB00797802 /* PDTabsView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA850CA1B0CB00797802 /* PDTabsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAA00CA1B0CB00797802 /* PDTabsView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA860CA1B0CB00797802 /* PDTabsView.m */; }; + E337CAA10CA1B0CB00797802 /* PDURLTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA870CA1B0CB00797802 /* PDURLTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAA20CA1B0CB00797802 /* PDURLTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA880CA1B0CB00797802 /* PDURLTextField.m */; }; + E337CAA30CA1B0CB00797802 /* PDURLTextFieldCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA890CA1B0CB00797802 /* PDURLTextFieldCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAA40CA1B0CB00797802 /* PDPrintTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA8A0CA1B0CB00797802 /* PDPrintTextView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAA50CA1B0CB00797802 /* PDPrintTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA8B0CA1B0CB00797802 /* PDPrintTextView.m */; }; + E337CAA60CA1B0CB00797802 /* PDURLTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA8C0CA1B0CB00797802 /* PDURLTextFieldCell.m */; }; + E337CAA70CA1B0CB00797802 /* PDBorderedView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA8D0CA1B0CB00797802 /* PDBorderedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAA80CA1B0CB00797802 /* PDBorderedView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA8E0CA1B0CB00797802 /* PDBorderedView.m */; }; + E337CAA90CA1B0CB00797802 /* RoundedView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA8F0CA1B0CB00797802 /* RoundedView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAAA0CA1B0CB00797802 /* RoundedView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA900CA1B0CB00797802 /* RoundedView.m */; }; + E337CAAB0CA1B0CB00797802 /* RoundedViewWhiteText.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA910CA1B0CB00797802 /* RoundedViewWhiteText.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAAC0CA1B0CB00797802 /* RoundedViewWhiteText.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA920CA1B0CB00797802 /* RoundedViewWhiteText.m */; }; + E337CAAD0CA1B0CB00797802 /* PDGradientView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA930CA1B0CB00797802 /* PDGradientView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAAE0CA1B0CB00797802 /* PDGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA940CA1B0CB00797802 /* PDGradientView.m */; }; + E337CAAF0CA1B0CB00797802 /* JournlerGradientView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA950CA1B0CB00797802 /* JournlerGradientView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAB00CA1B0CB00797802 /* JournlerGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA960CA1B0CB00797802 /* JournlerGradientView.m */; }; + E337CAB10CA1B0CB00797802 /* LabelPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA970CA1B0CB00797802 /* LabelPicker.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAB20CA1B0CB00797802 /* LabelPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA980CA1B0CB00797802 /* LabelPicker.m */; }; + E337CAB30CA1B0CB00797802 /* ConditionController.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA990CA1B0CB00797802 /* ConditionController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAB40CA1B0CB00797802 /* ConditionController.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA9A0CA1B0CB00797802 /* ConditionController.m */; }; + E337CAB50CA1B0CB00797802 /* CollectionManagerView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA9B0CA1B0CB00797802 /* CollectionManagerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAB60CA1B0CB00797802 /* CollectionManagerView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA9C0CA1B0CB00797802 /* CollectionManagerView.m */; }; + E337CAB70CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CA9D0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAB80CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CA9E0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.m */; }; + E337CADB0CA1B0DF00797802 /* PDButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CABB0CA1B0DF00797802 /* PDButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CADC0CA1B0DF00797802 /* PDButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CABC0CA1B0DF00797802 /* PDButton.m */; }; + E337CADD0CA1B0DF00797802 /* PDButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CABD0CA1B0DF00797802 /* PDButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CADE0CA1B0DF00797802 /* PDButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CABE0CA1B0DF00797802 /* PDButtonCell.m */; }; + E337CADF0CA1B0DF00797802 /* PDButtonColorWell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CABF0CA1B0DF00797802 /* PDButtonColorWell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAE00CA1B0DF00797802 /* PDButtonColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAC00CA1B0DF00797802 /* PDButtonColorWell.m */; }; + E337CAE10CA1B0DF00797802 /* PDButtonColorWellCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAC10CA1B0DF00797802 /* PDButtonColorWellCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAE20CA1B0DF00797802 /* PDButtonColorWellCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAC20CA1B0DF00797802 /* PDButtonColorWellCell.m */; }; + E337CAE30CA1B0DF00797802 /* PDButtonTextOnImage.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAC30CA1B0DF00797802 /* PDButtonTextOnImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAE40CA1B0DF00797802 /* PDButtonTextOnImage.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAC40CA1B0DF00797802 /* PDButtonTextOnImage.m */; }; + E337CAE50CA1B0DF00797802 /* PDButtonTextOnImageCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAC50CA1B0DF00797802 /* PDButtonTextOnImageCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAE60CA1B0DF00797802 /* PDButtonTextOnImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAC60CA1B0DF00797802 /* PDButtonTextOnImageCell.m */; }; + E337CAE70CA1B0DF00797802 /* PDCircleButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAC70CA1B0DF00797802 /* PDCircleButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAE80CA1B0DF00797802 /* PDCircleButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAC80CA1B0DF00797802 /* PDCircleButton.m */; }; + E337CAE90CA1B0DF00797802 /* PDCircleButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAC90CA1B0DF00797802 /* PDCircleButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAEA0CA1B0DF00797802 /* PDCircleButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CACA0CA1B0DF00797802 /* PDCircleButtonCell.m */; }; + E337CAEB0CA1B0DF00797802 /* PDInvisibleButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CACB0CA1B0DF00797802 /* PDInvisibleButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAEC0CA1B0DF00797802 /* PDInvisibleButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CACC0CA1B0DF00797802 /* PDInvisibleButton.m */; }; + E337CAED0CA1B0DF00797802 /* PDInvisibleButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CACD0CA1B0DF00797802 /* PDInvisibleButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAEE0CA1B0DF00797802 /* PDInvisibleButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CACE0CA1B0DF00797802 /* PDInvisibleButtonCell.m */; }; + E337CAEF0CA1B0DF00797802 /* PDMatrixButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CACF0CA1B0DF00797802 /* PDMatrixButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAF00CA1B0DF00797802 /* PDMatrixButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAD00CA1B0DF00797802 /* PDMatrixButton.m */; }; + E337CAF10CA1B0DF00797802 /* PDMatrixButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAD10CA1B0DF00797802 /* PDMatrixButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAF20CA1B0DF00797802 /* PDMatrixButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAD20CA1B0DF00797802 /* PDMatrixButtonCell.m */; }; + E337CAF30CA1B0DF00797802 /* PDPopUpButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAD30CA1B0DF00797802 /* PDPopUpButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAF40CA1B0DF00797802 /* PDPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAD40CA1B0DF00797802 /* PDPopUpButton.m */; }; + E337CAF50CA1B0DF00797802 /* PDPopUpButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAD50CA1B0DF00797802 /* PDPopUpButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAF60CA1B0DF00797802 /* PDPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAD60CA1B0DF00797802 /* PDPopUpButtonCell.m */; }; + E337CAF70CA1B0DF00797802 /* PDStylesButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAD70CA1B0DF00797802 /* PDStylesButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAF80CA1B0DF00797802 /* PDStylesButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CAD80CA1B0DF00797802 /* PDStylesButton.m */; }; + E337CAF90CA1B0DF00797802 /* PDStylesButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CAD90CA1B0DF00797802 /* PDStylesButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CAFA0CA1B0DF00797802 /* PDStylesButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CADA0CA1B0DF00797802 /* PDStylesButtonCell.m */; }; + E337CB160CA1B10C00797802 /* MUPhotoView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CB140CA1B10C00797802 /* MUPhotoView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CB170CA1B10C00797802 /* MUPhotoView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CB150CA1B10C00797802 /* MUPhotoView.m */; }; + E337CB1E0CA1B11F00797802 /* RBSplitSubview.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CB190CA1B11F00797802 /* RBSplitSubview.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CB1F0CA1B11F00797802 /* RBSplitSubview.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CB1A0CA1B11F00797802 /* RBSplitSubview.m */; }; + E337CB200CA1B11F00797802 /* RBSplitView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CB1B0CA1B11F00797802 /* RBSplitView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337CB210CA1B11F00797802 /* RBSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337CB1C0CA1B11F00797802 /* RBSplitView.m */; }; + E337CB220CA1B11F00797802 /* RBSplitViewPrivateDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = E337CB1D0CA1B11F00797802 /* RBSplitViewPrivateDefines.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E337CB320CA1B15300797802 /* hud_titlebar-close.tiff in Resources */ = {isa = PBXBuildFile; fileRef = E337CB310CA1B15300797802 /* hud_titlebar-close.tiff */; }; + E337CB3E0CA1B17200797802 /* AppleScriptActionBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB3D0CA1B17200797802 /* AppleScriptActionBarSmall.png */; }; + E337CB460CA1B18000797802 /* InfoBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB450CA1B18000797802 /* InfoBarSmall.png */; }; + E337CB4D0CA1B18D00797802 /* iTunesBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB4B0CA1B18D00797802 /* iTunesBarSmall.png */; }; + E337CB4E0CA1B18D00797802 /* PreviewBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB4C0CA1B18D00797802 /* PreviewBarSmall.png */; }; + E337CB570CA1B19900797802 /* QTBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB550CA1B19900797802 /* QTBarSmall.png */; }; + E337CB580CA1B19900797802 /* RevealInFinderBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB560CA1B19900797802 /* RevealInFinderBarSmall.png */; }; + E337CB650CA1B1AA00797802 /* TextEditBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB630CA1B1AA00797802 /* TextEditBarSmall.png */; }; + E337CB660CA1B1AA00797802 /* WordBarSmall.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB640CA1B1AA00797802 /* WordBarSmall.png */; }; + E337CB9B0CA1B1DE00797802 /* ActualSize.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB850CA1B1DE00797802 /* ActualSize.png */; }; + E337CB9C0CA1B1DE00797802 /* ActualSizePressed.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB860CA1B1DE00797802 /* ActualSizePressed.png */; }; + E337CB9D0CA1B1DE00797802 /* Back.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB870CA1B1DE00797802 /* Back.tif */; }; + E337CB9E0CA1B1DE00797802 /* BackDisabled.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB880CA1B1DE00797802 /* BackDisabled.tif */; }; + E337CB9F0CA1B1DE00797802 /* BackPressed.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB890CA1B1DE00797802 /* BackPressed.tif */; }; + E337CBA00CA1B1DE00797802 /* Bigger.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8A0CA1B1DE00797802 /* Bigger.png */; }; + E337CBA10CA1B1DE00797802 /* BiggerDisabled.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8B0CA1B1DE00797802 /* BiggerDisabled.png */; }; + E337CBA20CA1B1DE00797802 /* BiggerPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8C0CA1B1DE00797802 /* BiggerPressed.png */; }; + E337CBA30CA1B1DE00797802 /* Display.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8D0CA1B1DE00797802 /* Display.png */; }; + E337CBA40CA1B1DE00797802 /* DisplayPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8E0CA1B1DE00797802 /* DisplayPressed.png */; }; + E337CBA50CA1B1DE00797802 /* Forward.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB8F0CA1B1DE00797802 /* Forward.tif */; }; + E337CBA60CA1B1DE00797802 /* ForwardDisabled.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB900CA1B1DE00797802 /* ForwardDisabled.tif */; }; + E337CBA70CA1B1DE00797802 /* ForwardPressed.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB910CA1B1DE00797802 /* ForwardPressed.tif */; }; + E337CBA80CA1B1DE00797802 /* Home.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB920CA1B1DE00797802 /* Home.tif */; }; + E337CBA90CA1B1DE00797802 /* HomePressed.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB930CA1B1DE00797802 /* HomePressed.tif */; }; + E337CBAA0CA1B1DE00797802 /* Reload.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB940CA1B1DE00797802 /* Reload.tif */; }; + E337CBAB0CA1B1DE00797802 /* ReloadPressed.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB950CA1B1DE00797802 /* ReloadPressed.tif */; }; + E337CBAC0CA1B1DE00797802 /* Smaller.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB960CA1B1DE00797802 /* Smaller.png */; }; + E337CBAD0CA1B1DE00797802 /* SmallerDisabled.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB970CA1B1DE00797802 /* SmallerDisabled.png */; }; + E337CBAE0CA1B1DE00797802 /* SmallerPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CB980CA1B1DE00797802 /* SmallerPressed.png */; }; + E337CBAF0CA1B1DE00797802 /* Stop.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB990CA1B1DE00797802 /* Stop.tif */; }; + E337CBB00CA1B1DE00797802 /* StopPressed.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CB9A0CA1B1DE00797802 /* StopPressed.tif */; }; + E337CBB80CA1B21E00797802 /* PDURLTextFieldFileDefault.png in Resources */ = {isa = PBXBuildFile; fileRef = E337CBB60CA1B21E00797802 /* PDURLTextFieldFileDefault.png */; }; + E337CBB90CA1B21E00797802 /* PDURLTextFieldWebDefault.tiff in Resources */ = {isa = PBXBuildFile; fileRef = E337CBB70CA1B21E00797802 /* PDURLTextFieldWebDefault.tiff */; }; + E337CBBE0CA1B23200797802 /* labelall.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CBBB0CA1B23200797802 /* labelall.tif */; }; + E337CBBF0CA1B23200797802 /* labelhover.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CBBC0CA1B23200797802 /* labelhover.tif */; }; + E337CBC00CA1B23200797802 /* labelselected.tif in Resources */ = {isa = PBXBuildFile; fileRef = E337CBBD0CA1B23200797802 /* labelselected.tif */; }; + E337CBED0CA1B2F300797802 /* IntegrationFileCopy.nib in Resources */ = {isa = PBXBuildFile; fileRef = E337CBE70CA1B2F300797802 /* IntegrationFileCopy.nib */; }; + E337CBEE0CA1B2F300797802 /* Mediabar.strings in Resources */ = {isa = PBXBuildFile; fileRef = E337CBE90CA1B2F300797802 /* Mediabar.strings */; }; + E337CBEF0CA1B2F300797802 /* NewMediabarItem.nib in Resources */ = {isa = PBXBuildFile; fileRef = E337CBEB0CA1B2F300797802 /* NewMediabarItem.nib */; }; + E337CBFA0CA1B3CB00797802 /* SproutedUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E337CBF90CA1B3CB00797802 /* SproutedUtilities.framework */; }; + E337CC3E0CA1B45200797802 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E337CC3D0CA1B45200797802 /* QuartzCore.framework */; }; + E337D4060CA1E4D200797802 /* MediaViewer.h in Headers */ = {isa = PBXBuildFile; fileRef = E337D4040CA1E4D200797802 /* MediaViewer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337DA990CA2F80F00797802 /* CustomFindPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = E337DA970CA2F80F00797802 /* CustomFindPanel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337DA9A0CA2F80F00797802 /* CustomFindPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = E337DA980CA2F80F00797802 /* CustomFindPanel.m */; }; + E337DB880CA2F8BB00797802 /* EtchedText.h in Headers */ = {isa = PBXBuildFile; fileRef = E337DB840CA2F8BB00797802 /* EtchedText.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337DB890CA2F8BB00797802 /* EtchedText.m in Sources */ = {isa = PBXBuildFile; fileRef = E337DB850CA2F8BB00797802 /* EtchedText.m */; }; + E337DB8A0CA2F8BB00797802 /* EtchedTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E337DB860CA2F8BB00797802 /* EtchedTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337DB8B0CA2F8BB00797802 /* EtchedTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E337DB870CA2F8BB00797802 /* EtchedTextCell.m */; }; + E337DFD00CA3052A00797802 /* PDAutoCompleteTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = E337DFCE0CA3052A00797802 /* PDAutoCompleteTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337DFD10CA3052A00797802 /* PDAutoCompleteTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = E337DFCF0CA3052A00797802 /* PDAutoCompleteTextField.m */; }; + E337E2AD0CA33F7100797802 /* PDFileInfoView.h in Headers */ = {isa = PBXBuildFile; fileRef = E337E2AB0CA33F7100797802 /* PDFileInfoView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E337E2AE0CA33F7100797802 /* PDFileInfoView.m in Sources */ = {isa = PBXBuildFile; fileRef = E337E2AC0CA33F7100797802 /* PDFileInfoView.m */; }; + E337E4120CA3780000797802 /* FileInfo.strings in Resources */ = {isa = PBXBuildFile; fileRef = E337E4110CA3780000797802 /* FileInfo.strings */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 32DBCF5E0370ADEE00C91783 /* Sprouted Interface_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Sprouted Interface_Prefix.pch"; sourceTree = ""; }; + 723F4F100F6F0BA400212DFE /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/SproutedAboutBox.nib; sourceTree = ""; }; + 723F4F130F6F0BB200212DFE /* da */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = da; path = da.lproj/SproutedAboutBox.nib; sourceTree = ""; }; + 723F4F150F6F0BB800212DFE /* de */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = de; path = de.lproj/SproutedAboutBox.nib; sourceTree = ""; }; + 724BAC8C0DB9288000DDE79D /* LinkController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkController.h; sourceTree = ""; }; + 724BAC8D0DB9288000DDE79D /* LinkController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinkController.m; sourceTree = ""; }; + 724BACA40DB928F500DDE79D /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/InsertLink.nib; sourceTree = ""; }; + 724BACA60DB928FA00DDE79D /* de */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = de; path = de.lproj/InsertLink.nib; sourceTree = ""; }; + 724BACAA0DB9290300DDE79D /* da */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = da; path = da.lproj/InsertLink.nib; sourceTree = ""; }; + 724BACCA0DB929E600DDE79D /* StatsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatsController.h; sourceTree = ""; }; + 724BACCB0DB929E600DDE79D /* StatsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StatsController.m; sourceTree = ""; }; + 724BAD670DB92A6200DDE79D /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Stats.nib; sourceTree = ""; }; + 724BAD690DB92A6900DDE79D /* da */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = da; path = da.lproj/Stats.nib; sourceTree = ""; }; + 724BAD6D0DB92A6E00DDE79D /* de */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = de; path = de.lproj/Stats.nib; sourceTree = ""; }; + 7269D0100DD10821005AD452 /* PDTokenField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDTokenField.h; sourceTree = ""; }; + 7269D0110DD10821005AD452 /* PDTokenField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDTokenField.m; sourceTree = ""; }; + 7269D0120DD10821005AD452 /* PDTokenFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDTokenFieldCell.h; sourceTree = ""; }; + 7269D0130DD10821005AD452 /* PDTokenFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDTokenFieldCell.m; sourceTree = ""; }; + 7269D09C0DD10C75005AD452 /* PDTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDTableView.h; sourceTree = ""; }; + 7269D09D0DD10C75005AD452 /* PDTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDTableView.m; sourceTree = ""; }; + 7269D09E0DD10C75005AD452 /* PDOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDOutlineView.h; sourceTree = ""; }; + 7269D09F0DD10C75005AD452 /* PDOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDOutlineView.m; sourceTree = ""; }; + 727F6F560F462A4E00CFCECB /* SproutedAnchoredDocumentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SproutedAnchoredDocumentView.m; sourceTree = ""; }; + 727F6F570F462A4E00CFCECB /* SproutedAnchoredDocumentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SproutedAnchoredDocumentView.h; sourceTree = ""; }; + 728868EB0CC689D700733960 /* PDRankCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDRankCell.h; sourceTree = ""; }; + 728868EC0CC689D700733960 /* PDRankCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDRankCell.m; sourceTree = ""; }; + 728868EF0CC689E500733960 /* PDBlueHighlightTextCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDBlueHighlightTextCell.h; sourceTree = ""; }; + 728868F00CC689E500733960 /* PDBlueHighlightTextCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDBlueHighlightTextCell.m; sourceTree = ""; }; + 72886AE90CC7C5FB00733960 /* PDFontPreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDFontPreview.h; sourceTree = ""; }; + 72886AEA0CC7C5FB00733960 /* PDFontPreview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDFontPreview.m; sourceTree = ""; }; + 72886AEB0CC7C5FB00733960 /* PDFontDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDFontDisplay.h; sourceTree = ""; }; + 72886AEC0CC7C5FB00733960 /* PDFontDisplay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDFontDisplay.m; sourceTree = ""; }; + 72886B4C0CC7C70100733960 /* PDColorWell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDColorWell.h; sourceTree = ""; }; + 72886B4D0CC7C70100733960 /* PDColorWell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDColorWell.m; sourceTree = ""; }; + 72886B630CC7C7ED00733960 /* JRLRFooter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JRLRFooter.h; sourceTree = ""; }; + 72886B640CC7C7ED00733960 /* JRLRFooter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JRLRFooter.m; sourceTree = ""; }; + 72886B7B0CC7C92600733960 /* DragView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragView.h; sourceTree = ""; }; + 72886B7C0CC7C92600733960 /* DragView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DragView.m; sourceTree = ""; }; + 72887A970CCC4EDB00733960 /* more.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = more.tif; sourceTree = ""; }; + 72887A980CCC4EDB00733960 /* tabcloseback.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabcloseback.tif; sourceTree = ""; }; + 72887A990CCC4EDB00733960 /* tabclosebackdown.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabclosebackdown.tif; sourceTree = ""; }; + 72887A9A0CCC4EDB00733960 /* tabclosebackroll.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabclosebackroll.tif; sourceTree = ""; }; + 72887A9B0CCC4EDB00733960 /* tabclosefront.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabclosefront.tif; sourceTree = ""; }; + 72887A9C0CCC4EDB00733960 /* tabclosefrontdown.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabclosefrontdown.tif; sourceTree = ""; }; + 72887A9D0CCC4EDB00733960 /* tabclosefrontroll.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = tabclosefrontroll.tif; sourceTree = ""; }; + 7298530C0CD27ECD00BB4A53 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/PDFontPreview.strings; sourceTree = ""; }; + 729853300CD27FAA00BB4A53 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/PDTabsView.strings; sourceTree = ""; }; + 7298533C0CD27FF100BB4A53 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/PDFavoritesBar.strings; sourceTree = ""; }; + 729853750CD28A4000BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/PDFavoritesBar.strings; sourceTree = ""; }; + 729853760CD28A4200BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/PDFavoritesBar.strings; sourceTree = ""; }; + 729853770CD28A4900BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/PDTabsView.strings; sourceTree = ""; }; + 729853780CD28A4A00BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/PDTabsView.strings; sourceTree = ""; }; + 729853790CD28A5000BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/PDFontPreview.strings; sourceTree = ""; }; + 7298537A0CD28A5200BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/PDFontPreview.strings; sourceTree = ""; }; + 7298537B0CD28A5800BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/FileInfo.strings; sourceTree = ""; }; + 7298537C0CD28A5900BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/FileInfo.strings; sourceTree = ""; }; + 7298537D0CD28A5E00BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Mediabar.strings; sourceTree = ""; }; + 7298537F0CD28A6900BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Mediabar.strings; sourceTree = ""; }; + 729853830CD28BB200BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/InfoPlist.strings; sourceTree = ""; }; + 729853840CD28BB400BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; + 729853850CD28BEB00BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = de; path = de.lproj/NewMediabarItem.nib; sourceTree = ""; }; + 729853860CD28BEB00BB4A53 /* de */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = de; path = de.lproj/IntegrationFileCopy.nib; sourceTree = ""; }; + 729853880CD28BF300BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = da; path = da.lproj/NewMediabarItem.nib; sourceTree = ""; }; + 729853890CD28BF300BB4A53 /* da */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = da; path = da.lproj/IntegrationFileCopy.nib; sourceTree = ""; }; + 72A7DCCE0CCD0C1C009ED8AC /* EtchedPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EtchedPopUpButton.h; sourceTree = ""; }; + 72A7DCCF0CCD0C1C009ED8AC /* EtchedPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EtchedPopUpButton.m; sourceTree = ""; }; + 72A7DCD00CCD0C1C009ED8AC /* EtchedPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EtchedPopUpButtonCell.h; sourceTree = ""; }; + 72A7DCD10CCD0C1C009ED8AC /* EtchedPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EtchedPopUpButtonCell.m; sourceTree = ""; }; + 72A7DE640CCD1CD0009ED8AC /* EmailBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = EmailBarSmall.png; sourceTree = ""; }; + 72A7DE6C0CCD1D9A009ED8AC /* ABBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ABBarSmall.png; sourceTree = ""; }; + 72A7DE700CCD1DA3009ED8AC /* ComposeMailBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ComposeMailBarSmall.png; sourceTree = ""; }; + 72A7DE740CCD1DDD009ED8AC /* SafariBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SafariBarSmall.png; sourceTree = ""; }; + 72A7E08B0CCD5220009ED8AC /* Read Me.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Read Me.rtf"; sourceTree = ""; }; + 72A7E08C0CCD5220009ED8AC /* Version History.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Version History.rtf"; sourceTree = ""; }; + 72A7E09D0CCD574C009ED8AC /* PolishedWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolishedWindow.h; sourceTree = ""; }; + 72A7E09E0CCD574C009ED8AC /* PolishedWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PolishedWindow.m; sourceTree = ""; }; + 72A7E0A60CCD57DA009ED8AC /* flat_bottom_left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_bottom_left.png; sourceTree = ""; }; + 72A7E0A70CCD57DA009ED8AC /* flat_bottom_middle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_bottom_middle.png; sourceTree = ""; }; + 72A7E0A80CCD57DA009ED8AC /* flat_bottom_right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_bottom_right.png; sourceTree = ""; }; + 72A7E0A90CCD57DA009ED8AC /* flat_middle_left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_middle_left.png; sourceTree = ""; }; + 72A7E0AA0CCD57DA009ED8AC /* flat_middle_right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_middle_right.png; sourceTree = ""; }; + 72A7E0AB0CCD57DA009ED8AC /* flat_top_left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_top_left.png; sourceTree = ""; }; + 72A7E0AC0CCD57DA009ED8AC /* flat_top_middle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_top_middle.png; sourceTree = ""; }; + 72A7E0AD0CCD57DA009ED8AC /* flat_top_right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flat_top_right.png; sourceTree = ""; }; + 72C95BCC0DBE48B3005440D5 /* PDPhotoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDPhotoView.h; sourceTree = ""; }; + 72C95BCD0DBE48B3005440D5 /* PDPhotoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PDPhotoView.m; sourceTree = ""; }; + 72C95BCE0DBE48B3005440D5 /* MUPhotoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MUPhotoCell.h; sourceTree = ""; }; + 72C95BCF0DBE48B3005440D5 /* MUPhotoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MUPhotoCell.m; sourceTree = ""; }; + 72FB5B680E59E1D900BB20D7 /* SproutedAboutBoxController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SproutedAboutBoxController.h; sourceTree = ""; }; + 72FB5B690E59E1D900BB20D7 /* SproutedAboutBoxController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SproutedAboutBoxController.m; sourceTree = ""; }; + 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8DC2EF5B0486A6940098B216 /* SproutedInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SproutedInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + E3046CF60CACE76E006A17BB /* DocumentMakerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentMakerController.h; sourceTree = ""; }; + E3046CF70CACE76E006A17BB /* DocumentMakerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DocumentMakerController.m; sourceTree = ""; }; + E337CA330CA1B05100797802 /* SproutedInterface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SproutedInterface.h; sourceTree = ""; }; + E337CA340CA1B05100797802 /* PDPredicateBuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPredicateBuilder.h; sourceTree = ""; }; + E337CA350CA1B05100797802 /* MediaContentController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MediaContentController.h; sourceTree = ""; }; + E337CA360CA1B05100797802 /* MediaContentController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MediaContentController.m; sourceTree = ""; }; + E337CA3B0CA1B05800797802 /* TransparentWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TransparentWindow.h; sourceTree = ""; }; + E337CA3C0CA1B05800797802 /* TransparentWindow.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = TransparentWindow.m; sourceTree = ""; }; + E337CA3D0CA1B05800797802 /* AppleScriptAlert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleScriptAlert.h; sourceTree = ""; }; + E337CA3E0CA1B05800797802 /* AppleScriptAlert.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AppleScriptAlert.m; sourceTree = ""; }; + E337CA3F0CA1B05800797802 /* IntegrationCopyFiles.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IntegrationCopyFiles.h; sourceTree = ""; }; + E337CA400CA1B05800797802 /* IntegrationCopyFiles.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = IntegrationCopyFiles.m; sourceTree = ""; }; + E337CA470CA1B06100797802 /* HUDWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HUDWindow.h; sourceTree = ""; }; + E337CA480CA1B06100797802 /* HUDWindow.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = HUDWindow.m; sourceTree = ""; }; + E337CA4B0CA1B06A00797802 /* PDFavorite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDFavorite.h; sourceTree = ""; }; + E337CA4C0CA1B06A00797802 /* PDFavorite.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDFavorite.m; sourceTree = ""; }; + E337CA4D0CA1B06A00797802 /* PDFavoritesBar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDFavoritesBar.h; sourceTree = ""; }; + E337CA4E0CA1B06A00797802 /* PDFavoritesBar.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDFavoritesBar.m; sourceTree = ""; }; + E337CA530CA1B07400797802 /* PDMediaBar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDMediaBar.h; sourceTree = ""; }; + E337CA540CA1B07400797802 /* PDMediaBar.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDMediaBar.m; sourceTree = ""; }; + E337CA550CA1B07400797802 /* PDMediabarItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDMediabarItem.h; sourceTree = ""; }; + E337CA560CA1B07400797802 /* PDMediabarItem.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDMediabarItem.m; sourceTree = ""; }; + E337CA570CA1B07400797802 /* NewMediabarItemController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NewMediabarItemController.h; sourceTree = ""; }; + E337CA580CA1B07400797802 /* NewMediabarItemController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NewMediabarItemController.m; sourceTree = ""; }; + E337CA590CA1B07400797802 /* MediabarItemApplicationPicker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MediabarItemApplicationPicker.h; sourceTree = ""; }; + E337CA5A0CA1B07400797802 /* MediabarItemApplicationPicker.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MediabarItemApplicationPicker.m; sourceTree = ""; }; + E337CA670CA1B09F00797802 /* PDToolbar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDToolbar.h; sourceTree = ""; }; + E337CA680CA1B09F00797802 /* PDToolbar.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDToolbar.m; sourceTree = ""; }; + E337CA690CA1B09F00797802 /* PDPopUpButtonToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPopUpButtonToolbarItem.h; sourceTree = ""; }; + E337CA6A0CA1B09F00797802 /* PDPopUpButtonToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDPopUpButtonToolbarItem.m; sourceTree = ""; }; + E337CA6B0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPopUpButtonToolbarItemCell.h; sourceTree = ""; }; + E337CA6C0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDPopUpButtonToolbarItemCell.m; sourceTree = ""; }; + E337CA6D0CA1B09F00797802 /* PDSelfValidatingToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDSelfValidatingToolbarItem.h; sourceTree = ""; }; + E337CA6E0CA1B09F00797802 /* PDSelfValidatingToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDSelfValidatingToolbarItem.m; sourceTree = ""; }; + E337CA790CA1B0BF00797802 /* PDDateDisplayCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDDateDisplayCell.h; sourceTree = ""; }; + E337CA7A0CA1B0BF00797802 /* PDDateDisplayCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDDateDisplayCell.m; sourceTree = ""; }; + E337CA7B0CA1B0BF00797802 /* PDHorizontallyCenteredText.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDHorizontallyCenteredText.h; sourceTree = ""; }; + E337CA7C0CA1B0BF00797802 /* PDHorizontallyCenteredText.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDHorizontallyCenteredText.m; sourceTree = ""; }; + E337CA7D0CA1B0BF00797802 /* ImageAndTextCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageAndTextCell.h; sourceTree = ""; }; + E337CA7E0CA1B0BF00797802 /* ImageAndTextCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ImageAndTextCell.m; sourceTree = ""; }; + E337CA850CA1B0CB00797802 /* PDTabsView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDTabsView.h; sourceTree = ""; }; + E337CA860CA1B0CB00797802 /* PDTabsView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDTabsView.m; sourceTree = ""; }; + E337CA870CA1B0CB00797802 /* PDURLTextField.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDURLTextField.h; sourceTree = ""; }; + E337CA880CA1B0CB00797802 /* PDURLTextField.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDURLTextField.m; sourceTree = ""; }; + E337CA890CA1B0CB00797802 /* PDURLTextFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDURLTextFieldCell.h; sourceTree = ""; }; + E337CA8A0CA1B0CB00797802 /* PDPrintTextView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPrintTextView.h; sourceTree = ""; }; + E337CA8B0CA1B0CB00797802 /* PDPrintTextView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDPrintTextView.m; sourceTree = ""; }; + E337CA8C0CA1B0CB00797802 /* PDURLTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDURLTextFieldCell.m; sourceTree = ""; }; + E337CA8D0CA1B0CB00797802 /* PDBorderedView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDBorderedView.h; sourceTree = ""; }; + E337CA8E0CA1B0CB00797802 /* PDBorderedView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDBorderedView.m; sourceTree = ""; }; + E337CA8F0CA1B0CB00797802 /* RoundedView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RoundedView.h; sourceTree = ""; }; + E337CA900CA1B0CB00797802 /* RoundedView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RoundedView.m; sourceTree = ""; }; + E337CA910CA1B0CB00797802 /* RoundedViewWhiteText.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RoundedViewWhiteText.h; sourceTree = ""; }; + E337CA920CA1B0CB00797802 /* RoundedViewWhiteText.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RoundedViewWhiteText.m; sourceTree = ""; }; + E337CA930CA1B0CB00797802 /* PDGradientView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDGradientView.h; sourceTree = ""; }; + E337CA940CA1B0CB00797802 /* PDGradientView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDGradientView.m; sourceTree = ""; }; + E337CA950CA1B0CB00797802 /* JournlerGradientView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JournlerGradientView.h; sourceTree = ""; }; + E337CA960CA1B0CB00797802 /* JournlerGradientView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = JournlerGradientView.m; sourceTree = ""; }; + E337CA970CA1B0CB00797802 /* LabelPicker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LabelPicker.h; sourceTree = ""; }; + E337CA980CA1B0CB00797802 /* LabelPicker.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = LabelPicker.m; sourceTree = ""; }; + E337CA990CA1B0CB00797802 /* ConditionController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConditionController.h; sourceTree = ""; }; + E337CA9A0CA1B0CB00797802 /* ConditionController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ConditionController.m; sourceTree = ""; }; + E337CA9B0CA1B0CB00797802 /* CollectionManagerView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CollectionManagerView.h; sourceTree = ""; }; + E337CA9C0CA1B0CB00797802 /* CollectionManagerView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = CollectionManagerView.m; sourceTree = ""; }; + E337CA9D0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDCaseInsensitiveComboBoxCell.h; sourceTree = ""; }; + E337CA9E0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDCaseInsensitiveComboBoxCell.m; sourceTree = ""; }; + E337CABB0CA1B0DF00797802 /* PDButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButton.h; sourceTree = ""; }; + E337CABC0CA1B0DF00797802 /* PDButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButton.m; sourceTree = ""; }; + E337CABD0CA1B0DF00797802 /* PDButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButtonCell.h; sourceTree = ""; }; + E337CABE0CA1B0DF00797802 /* PDButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButtonCell.m; sourceTree = ""; }; + E337CABF0CA1B0DF00797802 /* PDButtonColorWell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButtonColorWell.h; sourceTree = ""; }; + E337CAC00CA1B0DF00797802 /* PDButtonColorWell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButtonColorWell.m; sourceTree = ""; }; + E337CAC10CA1B0DF00797802 /* PDButtonColorWellCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButtonColorWellCell.h; sourceTree = ""; }; + E337CAC20CA1B0DF00797802 /* PDButtonColorWellCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButtonColorWellCell.m; sourceTree = ""; }; + E337CAC30CA1B0DF00797802 /* PDButtonTextOnImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButtonTextOnImage.h; sourceTree = ""; }; + E337CAC40CA1B0DF00797802 /* PDButtonTextOnImage.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButtonTextOnImage.m; sourceTree = ""; }; + E337CAC50CA1B0DF00797802 /* PDButtonTextOnImageCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDButtonTextOnImageCell.h; sourceTree = ""; }; + E337CAC60CA1B0DF00797802 /* PDButtonTextOnImageCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDButtonTextOnImageCell.m; sourceTree = ""; }; + E337CAC70CA1B0DF00797802 /* PDCircleButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDCircleButton.h; sourceTree = ""; }; + E337CAC80CA1B0DF00797802 /* PDCircleButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDCircleButton.m; sourceTree = ""; }; + E337CAC90CA1B0DF00797802 /* PDCircleButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDCircleButtonCell.h; sourceTree = ""; }; + E337CACA0CA1B0DF00797802 /* PDCircleButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDCircleButtonCell.m; sourceTree = ""; }; + E337CACB0CA1B0DF00797802 /* PDInvisibleButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDInvisibleButton.h; sourceTree = ""; }; + E337CACC0CA1B0DF00797802 /* PDInvisibleButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDInvisibleButton.m; sourceTree = ""; }; + E337CACD0CA1B0DF00797802 /* PDInvisibleButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDInvisibleButtonCell.h; sourceTree = ""; }; + E337CACE0CA1B0DF00797802 /* PDInvisibleButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDInvisibleButtonCell.m; sourceTree = ""; }; + E337CACF0CA1B0DF00797802 /* PDMatrixButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDMatrixButton.h; sourceTree = ""; }; + E337CAD00CA1B0DF00797802 /* PDMatrixButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDMatrixButton.m; sourceTree = ""; }; + E337CAD10CA1B0DF00797802 /* PDMatrixButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDMatrixButtonCell.h; sourceTree = ""; }; + E337CAD20CA1B0DF00797802 /* PDMatrixButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDMatrixButtonCell.m; sourceTree = ""; }; + E337CAD30CA1B0DF00797802 /* PDPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPopUpButton.h; sourceTree = ""; }; + E337CAD40CA1B0DF00797802 /* PDPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDPopUpButton.m; sourceTree = ""; }; + E337CAD50CA1B0DF00797802 /* PDPopUpButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDPopUpButtonCell.h; sourceTree = ""; }; + E337CAD60CA1B0DF00797802 /* PDPopUpButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDPopUpButtonCell.m; sourceTree = ""; }; + E337CAD70CA1B0DF00797802 /* PDStylesButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDStylesButton.h; sourceTree = ""; }; + E337CAD80CA1B0DF00797802 /* PDStylesButton.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDStylesButton.m; sourceTree = ""; }; + E337CAD90CA1B0DF00797802 /* PDStylesButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDStylesButtonCell.h; sourceTree = ""; }; + E337CADA0CA1B0DF00797802 /* PDStylesButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDStylesButtonCell.m; sourceTree = ""; }; + E337CAFC0CA1B0FB00797802 /* MNLineNumberingRulerView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MNLineNumberingRulerView.h; sourceTree = ""; }; + E337CAFD0CA1B0FB00797802 /* MNLineNumberingRulerView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MNLineNumberingRulerView.m; sourceTree = ""; }; + E337CAFE0CA1B0FB00797802 /* MNLineNumberingTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MNLineNumberingTextStorage.h; sourceTree = ""; }; + E337CAFF0CA1B0FB00797802 /* MNLineNumberingTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MNLineNumberingTextStorage.m; sourceTree = ""; }; + E337CB000CA1B0FB00797802 /* MNLineNumberingTextView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MNLineNumberingTextView.h; sourceTree = ""; }; + E337CB010CA1B0FB00797802 /* MNLineNumberingTextView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MNLineNumberingTextView.m; sourceTree = ""; }; + E337CB020CA1B0FB00797802 /* PDAnnotatedTextView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDAnnotatedTextView.h; sourceTree = ""; }; + E337CB030CA1B0FB00797802 /* PDAnnotatedTextView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDAnnotatedTextView.m; sourceTree = ""; }; + E337CB040CA1B0FB00797802 /* PDAnnotatedTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDAnnotatedTextStorage.h; sourceTree = ""; }; + E337CB050CA1B0FB00797802 /* PDAnnotatedTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDAnnotatedTextStorage.m; sourceTree = ""; }; + E337CB060CA1B0FB00797802 /* PDAnnotatedRulerView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDAnnotatedRulerView.h; sourceTree = ""; }; + E337CB070CA1B0FB00797802 /* PDAnnotatedRulerView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDAnnotatedRulerView.m; sourceTree = ""; }; + E337CB140CA1B10C00797802 /* MUPhotoView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MUPhotoView.h; sourceTree = ""; }; + E337CB150CA1B10C00797802 /* MUPhotoView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MUPhotoView.m; sourceTree = ""; }; + E337CB190CA1B11F00797802 /* RBSplitSubview.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RBSplitSubview.h; sourceTree = ""; }; + E337CB1A0CA1B11F00797802 /* RBSplitSubview.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RBSplitSubview.m; sourceTree = ""; }; + E337CB1B0CA1B11F00797802 /* RBSplitView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RBSplitView.h; sourceTree = ""; }; + E337CB1C0CA1B11F00797802 /* RBSplitView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = RBSplitView.m; sourceTree = ""; }; + E337CB1D0CA1B11F00797802 /* RBSplitViewPrivateDefines.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RBSplitViewPrivateDefines.h; sourceTree = ""; }; + E337CB310CA1B15300797802 /* hud_titlebar-close.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "hud_titlebar-close.tiff"; sourceTree = ""; }; + E337CB3D0CA1B17200797802 /* AppleScriptActionBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AppleScriptActionBarSmall.png; sourceTree = ""; }; + E337CB450CA1B18000797802 /* InfoBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = InfoBarSmall.png; sourceTree = ""; }; + E337CB4B0CA1B18D00797802 /* iTunesBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iTunesBarSmall.png; sourceTree = ""; }; + E337CB4C0CA1B18D00797802 /* PreviewBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PreviewBarSmall.png; sourceTree = ""; }; + E337CB550CA1B19900797802 /* QTBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = QTBarSmall.png; sourceTree = ""; }; + E337CB560CA1B19900797802 /* RevealInFinderBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = RevealInFinderBarSmall.png; sourceTree = ""; }; + E337CB630CA1B1AA00797802 /* TextEditBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TextEditBarSmall.png; sourceTree = ""; }; + E337CB640CA1B1AA00797802 /* WordBarSmall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = WordBarSmall.png; sourceTree = ""; }; + E337CB850CA1B1DE00797802 /* ActualSize.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ActualSize.png; sourceTree = ""; }; + E337CB860CA1B1DE00797802 /* ActualSizePressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ActualSizePressed.png; sourceTree = ""; }; + E337CB870CA1B1DE00797802 /* Back.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Back.tif; sourceTree = ""; }; + E337CB880CA1B1DE00797802 /* BackDisabled.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = BackDisabled.tif; sourceTree = ""; }; + E337CB890CA1B1DE00797802 /* BackPressed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = BackPressed.tif; sourceTree = ""; }; + E337CB8A0CA1B1DE00797802 /* Bigger.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Bigger.png; sourceTree = ""; }; + E337CB8B0CA1B1DE00797802 /* BiggerDisabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BiggerDisabled.png; sourceTree = ""; }; + E337CB8C0CA1B1DE00797802 /* BiggerPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BiggerPressed.png; sourceTree = ""; }; + E337CB8D0CA1B1DE00797802 /* Display.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Display.png; sourceTree = ""; }; + E337CB8E0CA1B1DE00797802 /* DisplayPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DisplayPressed.png; sourceTree = ""; }; + E337CB8F0CA1B1DE00797802 /* Forward.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Forward.tif; sourceTree = ""; }; + E337CB900CA1B1DE00797802 /* ForwardDisabled.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = ForwardDisabled.tif; sourceTree = ""; }; + E337CB910CA1B1DE00797802 /* ForwardPressed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = ForwardPressed.tif; sourceTree = ""; }; + E337CB920CA1B1DE00797802 /* Home.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Home.tif; sourceTree = ""; }; + E337CB930CA1B1DE00797802 /* HomePressed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = HomePressed.tif; sourceTree = ""; }; + E337CB940CA1B1DE00797802 /* Reload.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Reload.tif; sourceTree = ""; }; + E337CB950CA1B1DE00797802 /* ReloadPressed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = ReloadPressed.tif; sourceTree = ""; }; + E337CB960CA1B1DE00797802 /* Smaller.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Smaller.png; sourceTree = ""; }; + E337CB970CA1B1DE00797802 /* SmallerDisabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SmallerDisabled.png; sourceTree = ""; }; + E337CB980CA1B1DE00797802 /* SmallerPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SmallerPressed.png; sourceTree = ""; }; + E337CB990CA1B1DE00797802 /* Stop.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Stop.tif; sourceTree = ""; }; + E337CB9A0CA1B1DE00797802 /* StopPressed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = StopPressed.tif; sourceTree = ""; }; + E337CBB60CA1B21E00797802 /* PDURLTextFieldFileDefault.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = PDURLTextFieldFileDefault.png; sourceTree = ""; }; + E337CBB70CA1B21E00797802 /* PDURLTextFieldWebDefault.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = PDURLTextFieldWebDefault.tiff; sourceTree = ""; }; + E337CBBB0CA1B23200797802 /* labelall.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = labelall.tif; sourceTree = ""; }; + E337CBBC0CA1B23200797802 /* labelhover.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = labelhover.tif; sourceTree = ""; }; + E337CBBD0CA1B23200797802 /* labelselected.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = labelselected.tif; sourceTree = ""; }; + E337CBE80CA1B2F300797802 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/IntegrationFileCopy.nib; sourceTree = ""; }; + E337CBEA0CA1B2F300797802 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Mediabar.strings; sourceTree = ""; }; + E337CBEC0CA1B2F300797802 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/NewMediabarItem.nib; sourceTree = ""; }; + E337CBF90CA1B3CB00797802 /* SproutedUtilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SproutedUtilities.framework; sourceTree = ""; }; + E337CC3D0CA1B45200797802 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; + E337D4040CA1E4D200797802 /* MediaViewer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MediaViewer.h; sourceTree = ""; }; + E337D4050CA1E4D200797802 /* MediaViewer.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = MediaViewer.m; sourceTree = ""; }; + E337DA970CA2F80F00797802 /* CustomFindPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CustomFindPanel.h; sourceTree = ""; }; + E337DA980CA2F80F00797802 /* CustomFindPanel.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = CustomFindPanel.m; sourceTree = ""; }; + E337DB840CA2F8BB00797802 /* EtchedText.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = EtchedText.h; sourceTree = ""; }; + E337DB850CA2F8BB00797802 /* EtchedText.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = EtchedText.m; sourceTree = ""; }; + E337DB860CA2F8BB00797802 /* EtchedTextCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = EtchedTextCell.h; sourceTree = ""; }; + E337DB870CA2F8BB00797802 /* EtchedTextCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = EtchedTextCell.m; sourceTree = ""; }; + E337DFCE0CA3052A00797802 /* PDAutoCompleteTextField.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDAutoCompleteTextField.h; sourceTree = ""; }; + E337DFCF0CA3052A00797802 /* PDAutoCompleteTextField.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDAutoCompleteTextField.m; sourceTree = ""; }; + E337E2AB0CA33F7100797802 /* PDFileInfoView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PDFileInfoView.h; sourceTree = ""; }; + E337E2AC0CA33F7100797802 /* PDFileInfoView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PDFileInfoView.m; sourceTree = ""; }; + E337E40D0CA377FC00797802 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/FileInfo.strings; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */, + E337CBFA0CA1B3CB00797802 /* SproutedUtilities.framework in Frameworks */, + E337CC3E0CA1B45200797802 /* QuartzCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* SproutedInterface.framework */, + ); + name = Products; + sourceTree = ""; + }; + 0867D691FE84028FC02AAC07 /* Sprouted Interface */ = { + isa = PBXGroup; + children = ( + 72A7E08B0CCD5220009ED8AC /* Read Me.rtf */, + 72A7E08C0CCD5220009ED8AC /* Version History.rtf */, + 08FB77AEFE84172EC02AAC07 /* Classes */, + 32C88DFF0371C24200C91783 /* Other Sources */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = "Sprouted Interface"; + sourceTree = ""; + }; + 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */, + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + E337CBB30CA1B20C00797802 /* Images */, + E337CBE90CA1B2F300797802 /* Mediabar.strings */, + E337E4110CA3780000797802 /* FileInfo.strings */, + 7298530B0CD27ECD00BB4A53 /* PDFontPreview.strings */, + 7298532F0CD27FAA00BB4A53 /* PDTabsView.strings */, + 7298533B0CD27FF100BB4A53 /* PDFavoritesBar.strings */, + E337CBE70CA1B2F300797802 /* IntegrationFileCopy.nib */, + E337CBEB0CA1B2F300797802 /* NewMediabarItem.nib */, + 724BACA30DB928F500DDE79D /* InsertLink.nib */, + 724BAD660DB92A6200DDE79D /* Stats.nib */, + 723F4F0F0F6F0BA400212DFE /* SproutedAboutBox.nib */, + 8DC2EF5A0486A6940098B216 /* Info.plist */, + 089C1666FE841158C02AAC07 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 08FB77AEFE84172EC02AAC07 /* Classes */ = { + isa = PBXGroup; + children = ( + E337CA330CA1B05100797802 /* SproutedInterface.h */, + E337CA660CA1B08400797802 /* Media Bar */, + E337CA650CA1B07E00797802 /* Favorites Bar */, + E337CA640CA1B07600797802 /* Custom Windows */, + E337CA770CA1B0A200797802 /* Toolbar */, + E337CA780CA1B0A800797802 /* Custom Controls and Cells */, + E337CABA0CA1B0D500797802 /* PDButton */, + E337CAFB0CA1B0F000797802 /* Annotated Text View */, + E337CB180CA1B11100797802 /* RBSplitView */, + E337D4020CA1E4C000797802 /* Sprouted Media PlugIns */, + E337E4160CA3781800797802 /* Nib Inclusive */, + E3046CF60CACE76E006A17BB /* DocumentMakerController.h */, + E3046CF70CACE76E006A17BB /* DocumentMakerController.m */, + E337CA340CA1B05100797802 /* PDPredicateBuilder.h */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + E337CC3D0CA1B45200797802 /* QuartzCore.framework */, + E337CBF90CA1B3CB00797802 /* SproutedUtilities.framework */, + 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 0867D6A5FE840307C02AAC07 /* AppKit.framework */, + D2F7E79907B2D74100F64583 /* CoreData.framework */, + 0867D69BFE84028FC02AAC07 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 32C88DFF0371C24200C91783 /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32DBCF5E0370ADEE00C91783 /* Sprouted Interface_Prefix.pch */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 72886AF20CC7C5FE00733960 /* Font Preview */ = { + isa = PBXGroup; + children = ( + 72886AE90CC7C5FB00733960 /* PDFontPreview.h */, + 72886AEA0CC7C5FB00733960 /* PDFontPreview.m */, + 72886AEB0CC7C5FB00733960 /* PDFontDisplay.h */, + 72886AEC0CC7C5FB00733960 /* PDFontDisplay.m */, + 72886B4C0CC7C70100733960 /* PDColorWell.h */, + 72886B4D0CC7C70100733960 /* PDColorWell.m */, + ); + name = "Font Preview"; + sourceTree = ""; + }; + 72887AA60CCC4EDD00733960 /* Tab Bar */ = { + isa = PBXGroup; + children = ( + 72887A970CCC4EDB00733960 /* more.tif */, + 72887A980CCC4EDB00733960 /* tabcloseback.tif */, + 72887A990CCC4EDB00733960 /* tabclosebackdown.tif */, + 72887A9A0CCC4EDB00733960 /* tabclosebackroll.tif */, + 72887A9B0CCC4EDB00733960 /* tabclosefront.tif */, + 72887A9C0CCC4EDB00733960 /* tabclosefrontdown.tif */, + 72887A9D0CCC4EDB00733960 /* tabclosefrontroll.tif */, + E337CB310CA1B15300797802 /* hud_titlebar-close.tiff */, + ); + name = "Tab Bar"; + sourceTree = ""; + }; + 72A7E0A20CCD57C2009ED8AC /* Polished Window */ = { + isa = PBXGroup; + children = ( + 72A7E0A60CCD57DA009ED8AC /* flat_bottom_left.png */, + 72A7E0A70CCD57DA009ED8AC /* flat_bottom_middle.png */, + 72A7E0A80CCD57DA009ED8AC /* flat_bottom_right.png */, + 72A7E0A90CCD57DA009ED8AC /* flat_middle_left.png */, + 72A7E0AA0CCD57DA009ED8AC /* flat_middle_right.png */, + 72A7E0AB0CCD57DA009ED8AC /* flat_top_left.png */, + 72A7E0AC0CCD57DA009ED8AC /* flat_top_middle.png */, + 72A7E0AD0CCD57DA009ED8AC /* flat_top_right.png */, + ); + name = "Polished Window"; + sourceTree = ""; + }; + E337CA640CA1B07600797802 /* Custom Windows */ = { + isa = PBXGroup; + children = ( + 72A7E09D0CCD574C009ED8AC /* PolishedWindow.h */, + 72A7E09E0CCD574C009ED8AC /* PolishedWindow.m */, + E337CA470CA1B06100797802 /* HUDWindow.h */, + E337CA480CA1B06100797802 /* HUDWindow.m */, + E337DA970CA2F80F00797802 /* CustomFindPanel.h */, + E337DA980CA2F80F00797802 /* CustomFindPanel.m */, + E337CA3B0CA1B05800797802 /* TransparentWindow.h */, + E337CA3C0CA1B05800797802 /* TransparentWindow.m */, + ); + name = "Custom Windows"; + sourceTree = ""; + }; + E337CA650CA1B07E00797802 /* Favorites Bar */ = { + isa = PBXGroup; + children = ( + E337CA4B0CA1B06A00797802 /* PDFavorite.h */, + E337CA4C0CA1B06A00797802 /* PDFavorite.m */, + E337CA4D0CA1B06A00797802 /* PDFavoritesBar.h */, + E337CA4E0CA1B06A00797802 /* PDFavoritesBar.m */, + ); + name = "Favorites Bar"; + sourceTree = ""; + }; + E337CA660CA1B08400797802 /* Media Bar */ = { + isa = PBXGroup; + children = ( + E337CA530CA1B07400797802 /* PDMediaBar.h */, + E337CA540CA1B07400797802 /* PDMediaBar.m */, + E337CA550CA1B07400797802 /* PDMediabarItem.h */, + E337CA560CA1B07400797802 /* PDMediabarItem.m */, + E337CA570CA1B07400797802 /* NewMediabarItemController.h */, + E337CA580CA1B07400797802 /* NewMediabarItemController.m */, + E337CA590CA1B07400797802 /* MediabarItemApplicationPicker.h */, + E337CA5A0CA1B07400797802 /* MediabarItemApplicationPicker.m */, + ); + name = "Media Bar"; + sourceTree = ""; + }; + E337CA770CA1B0A200797802 /* Toolbar */ = { + isa = PBXGroup; + children = ( + E337CA670CA1B09F00797802 /* PDToolbar.h */, + E337CA680CA1B09F00797802 /* PDToolbar.m */, + E337CA690CA1B09F00797802 /* PDPopUpButtonToolbarItem.h */, + E337CA6A0CA1B09F00797802 /* PDPopUpButtonToolbarItem.m */, + E337CA6B0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.h */, + E337CA6C0CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.m */, + E337CA6D0CA1B09F00797802 /* PDSelfValidatingToolbarItem.h */, + E337CA6E0CA1B09F00797802 /* PDSelfValidatingToolbarItem.m */, + ); + name = Toolbar; + sourceTree = ""; + }; + E337CA780CA1B0A800797802 /* Custom Controls and Cells */ = { + isa = PBXGroup; + children = ( + 72886AF20CC7C5FE00733960 /* Font Preview */, + 727F6F570F462A4E00CFCECB /* SproutedAnchoredDocumentView.h */, + 727F6F560F462A4E00CFCECB /* SproutedAnchoredDocumentView.m */, + 7269D0100DD10821005AD452 /* PDTokenField.h */, + 7269D0110DD10821005AD452 /* PDTokenField.m */, + 7269D0120DD10821005AD452 /* PDTokenFieldCell.h */, + 7269D0130DD10821005AD452 /* PDTokenFieldCell.m */, + 728868EF0CC689E500733960 /* PDBlueHighlightTextCell.h */, + 728868F00CC689E500733960 /* PDBlueHighlightTextCell.m */, + 728868EB0CC689D700733960 /* PDRankCell.h */, + 728868EC0CC689D700733960 /* PDRankCell.m */, + E337CB140CA1B10C00797802 /* MUPhotoView.h */, + E337CB150CA1B10C00797802 /* MUPhotoView.m */, + 72C95BCC0DBE48B3005440D5 /* PDPhotoView.h */, + 72C95BCD0DBE48B3005440D5 /* PDPhotoView.m */, + 72C95BCE0DBE48B3005440D5 /* MUPhotoCell.h */, + 72C95BCF0DBE48B3005440D5 /* MUPhotoCell.m */, + E337E2AB0CA33F7100797802 /* PDFileInfoView.h */, + E337E2AC0CA33F7100797802 /* PDFileInfoView.m */, + E337DFCE0CA3052A00797802 /* PDAutoCompleteTextField.h */, + E337DFCF0CA3052A00797802 /* PDAutoCompleteTextField.m */, + E337CA790CA1B0BF00797802 /* PDDateDisplayCell.h */, + E337CA7A0CA1B0BF00797802 /* PDDateDisplayCell.m */, + E337CA7B0CA1B0BF00797802 /* PDHorizontallyCenteredText.h */, + E337CA7C0CA1B0BF00797802 /* PDHorizontallyCenteredText.m */, + E337CA7D0CA1B0BF00797802 /* ImageAndTextCell.h */, + E337CA7E0CA1B0BF00797802 /* ImageAndTextCell.m */, + E337CA850CA1B0CB00797802 /* PDTabsView.h */, + E337CA860CA1B0CB00797802 /* PDTabsView.m */, + E337DB840CA2F8BB00797802 /* EtchedText.h */, + E337DB850CA2F8BB00797802 /* EtchedText.m */, + E337DB860CA2F8BB00797802 /* EtchedTextCell.h */, + E337DB870CA2F8BB00797802 /* EtchedTextCell.m */, + 72A7DCCE0CCD0C1C009ED8AC /* EtchedPopUpButton.h */, + 72A7DCCF0CCD0C1C009ED8AC /* EtchedPopUpButton.m */, + 72A7DCD00CCD0C1C009ED8AC /* EtchedPopUpButtonCell.h */, + 72A7DCD10CCD0C1C009ED8AC /* EtchedPopUpButtonCell.m */, + E337CA870CA1B0CB00797802 /* PDURLTextField.h */, + E337CA880CA1B0CB00797802 /* PDURLTextField.m */, + E337CA890CA1B0CB00797802 /* PDURLTextFieldCell.h */, + E337CA8A0CA1B0CB00797802 /* PDPrintTextView.h */, + E337CA8B0CA1B0CB00797802 /* PDPrintTextView.m */, + E337CA8C0CA1B0CB00797802 /* PDURLTextFieldCell.m */, + E337CA8D0CA1B0CB00797802 /* PDBorderedView.h */, + E337CA8E0CA1B0CB00797802 /* PDBorderedView.m */, + 72886B630CC7C7ED00733960 /* JRLRFooter.h */, + 72886B640CC7C7ED00733960 /* JRLRFooter.m */, + 72886B7B0CC7C92600733960 /* DragView.h */, + 72886B7C0CC7C92600733960 /* DragView.m */, + E337CA8F0CA1B0CB00797802 /* RoundedView.h */, + E337CA900CA1B0CB00797802 /* RoundedView.m */, + E337CA910CA1B0CB00797802 /* RoundedViewWhiteText.h */, + E337CA920CA1B0CB00797802 /* RoundedViewWhiteText.m */, + E337CA930CA1B0CB00797802 /* PDGradientView.h */, + E337CA940CA1B0CB00797802 /* PDGradientView.m */, + E337CA950CA1B0CB00797802 /* JournlerGradientView.h */, + E337CA960CA1B0CB00797802 /* JournlerGradientView.m */, + E337CA970CA1B0CB00797802 /* LabelPicker.h */, + E337CA980CA1B0CB00797802 /* LabelPicker.m */, + E337CA990CA1B0CB00797802 /* ConditionController.h */, + E337CA9A0CA1B0CB00797802 /* ConditionController.m */, + E337CA9B0CA1B0CB00797802 /* CollectionManagerView.h */, + E337CA9C0CA1B0CB00797802 /* CollectionManagerView.m */, + E337CA9D0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.h */, + E337CA9E0CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.m */, + 7269D09C0DD10C75005AD452 /* PDTableView.h */, + 7269D09D0DD10C75005AD452 /* PDTableView.m */, + 7269D09E0DD10C75005AD452 /* PDOutlineView.h */, + 7269D09F0DD10C75005AD452 /* PDOutlineView.m */, + ); + name = "Custom Controls and Cells"; + sourceTree = ""; + }; + E337CABA0CA1B0D500797802 /* PDButton */ = { + isa = PBXGroup; + children = ( + E337CABB0CA1B0DF00797802 /* PDButton.h */, + E337CABC0CA1B0DF00797802 /* PDButton.m */, + E337CABD0CA1B0DF00797802 /* PDButtonCell.h */, + E337CABE0CA1B0DF00797802 /* PDButtonCell.m */, + E337CABF0CA1B0DF00797802 /* PDButtonColorWell.h */, + E337CAC00CA1B0DF00797802 /* PDButtonColorWell.m */, + E337CAC10CA1B0DF00797802 /* PDButtonColorWellCell.h */, + E337CAC20CA1B0DF00797802 /* PDButtonColorWellCell.m */, + E337CAC30CA1B0DF00797802 /* PDButtonTextOnImage.h */, + E337CAC40CA1B0DF00797802 /* PDButtonTextOnImage.m */, + E337CAC50CA1B0DF00797802 /* PDButtonTextOnImageCell.h */, + E337CAC60CA1B0DF00797802 /* PDButtonTextOnImageCell.m */, + E337CAC70CA1B0DF00797802 /* PDCircleButton.h */, + E337CAC80CA1B0DF00797802 /* PDCircleButton.m */, + E337CAC90CA1B0DF00797802 /* PDCircleButtonCell.h */, + E337CACA0CA1B0DF00797802 /* PDCircleButtonCell.m */, + E337CACB0CA1B0DF00797802 /* PDInvisibleButton.h */, + E337CACC0CA1B0DF00797802 /* PDInvisibleButton.m */, + E337CACD0CA1B0DF00797802 /* PDInvisibleButtonCell.h */, + E337CACE0CA1B0DF00797802 /* PDInvisibleButtonCell.m */, + E337CACF0CA1B0DF00797802 /* PDMatrixButton.h */, + E337CAD00CA1B0DF00797802 /* PDMatrixButton.m */, + E337CAD10CA1B0DF00797802 /* PDMatrixButtonCell.h */, + E337CAD20CA1B0DF00797802 /* PDMatrixButtonCell.m */, + E337CAD30CA1B0DF00797802 /* PDPopUpButton.h */, + E337CAD40CA1B0DF00797802 /* PDPopUpButton.m */, + E337CAD50CA1B0DF00797802 /* PDPopUpButtonCell.h */, + E337CAD60CA1B0DF00797802 /* PDPopUpButtonCell.m */, + E337CAD70CA1B0DF00797802 /* PDStylesButton.h */, + E337CAD80CA1B0DF00797802 /* PDStylesButton.m */, + E337CAD90CA1B0DF00797802 /* PDStylesButtonCell.h */, + E337CADA0CA1B0DF00797802 /* PDStylesButtonCell.m */, + ); + name = PDButton; + sourceTree = ""; + }; + E337CAFB0CA1B0F000797802 /* Annotated Text View */ = { + isa = PBXGroup; + children = ( + E337CAFC0CA1B0FB00797802 /* MNLineNumberingRulerView.h */, + E337CAFD0CA1B0FB00797802 /* MNLineNumberingRulerView.m */, + E337CAFE0CA1B0FB00797802 /* MNLineNumberingTextStorage.h */, + E337CAFF0CA1B0FB00797802 /* MNLineNumberingTextStorage.m */, + E337CB000CA1B0FB00797802 /* MNLineNumberingTextView.h */, + E337CB010CA1B0FB00797802 /* MNLineNumberingTextView.m */, + E337CB020CA1B0FB00797802 /* PDAnnotatedTextView.h */, + E337CB030CA1B0FB00797802 /* PDAnnotatedTextView.m */, + E337CB040CA1B0FB00797802 /* PDAnnotatedTextStorage.h */, + E337CB050CA1B0FB00797802 /* PDAnnotatedTextStorage.m */, + E337CB060CA1B0FB00797802 /* PDAnnotatedRulerView.h */, + E337CB070CA1B0FB00797802 /* PDAnnotatedRulerView.m */, + ); + name = "Annotated Text View"; + sourceTree = ""; + }; + E337CB180CA1B11100797802 /* RBSplitView */ = { + isa = PBXGroup; + children = ( + E337CB190CA1B11F00797802 /* RBSplitSubview.h */, + E337CB1A0CA1B11F00797802 /* RBSplitSubview.m */, + E337CB1B0CA1B11F00797802 /* RBSplitView.h */, + E337CB1C0CA1B11F00797802 /* RBSplitView.m */, + E337CB1D0CA1B11F00797802 /* RBSplitViewPrivateDefines.h */, + ); + name = RBSplitView; + sourceTree = ""; + }; + E337CBB10CA1B1E100797802 /* Media Bar Default */ = { + isa = PBXGroup; + children = ( + 72A7DE740CCD1DDD009ED8AC /* SafariBarSmall.png */, + 72A7DE700CCD1DA3009ED8AC /* ComposeMailBarSmall.png */, + 72A7DE6C0CCD1D9A009ED8AC /* ABBarSmall.png */, + E337CB3D0CA1B17200797802 /* AppleScriptActionBarSmall.png */, + E337CB450CA1B18000797802 /* InfoBarSmall.png */, + E337CB4B0CA1B18D00797802 /* iTunesBarSmall.png */, + E337CB4C0CA1B18D00797802 /* PreviewBarSmall.png */, + E337CB550CA1B19900797802 /* QTBarSmall.png */, + E337CB560CA1B19900797802 /* RevealInFinderBarSmall.png */, + E337CB630CA1B1AA00797802 /* TextEditBarSmall.png */, + E337CB640CA1B1AA00797802 /* WordBarSmall.png */, + 72A7DE640CCD1CD0009ED8AC /* EmailBarSmall.png */, + ); + name = "Media Bar Default"; + sourceTree = ""; + }; + E337CBB20CA1B1FE00797802 /* Media Bar Custom */ = { + isa = PBXGroup; + children = ( + E337CB850CA1B1DE00797802 /* ActualSize.png */, + E337CB860CA1B1DE00797802 /* ActualSizePressed.png */, + E337CB870CA1B1DE00797802 /* Back.tif */, + E337CB880CA1B1DE00797802 /* BackDisabled.tif */, + E337CB890CA1B1DE00797802 /* BackPressed.tif */, + E337CB8A0CA1B1DE00797802 /* Bigger.png */, + E337CB8B0CA1B1DE00797802 /* BiggerDisabled.png */, + E337CB8C0CA1B1DE00797802 /* BiggerPressed.png */, + E337CB8D0CA1B1DE00797802 /* Display.png */, + E337CB8E0CA1B1DE00797802 /* DisplayPressed.png */, + E337CB8F0CA1B1DE00797802 /* Forward.tif */, + E337CB900CA1B1DE00797802 /* ForwardDisabled.tif */, + E337CB910CA1B1DE00797802 /* ForwardPressed.tif */, + E337CB920CA1B1DE00797802 /* Home.tif */, + E337CB930CA1B1DE00797802 /* HomePressed.tif */, + E337CB940CA1B1DE00797802 /* Reload.tif */, + E337CB950CA1B1DE00797802 /* ReloadPressed.tif */, + E337CB960CA1B1DE00797802 /* Smaller.png */, + E337CB970CA1B1DE00797802 /* SmallerDisabled.png */, + E337CB980CA1B1DE00797802 /* SmallerPressed.png */, + E337CB990CA1B1DE00797802 /* Stop.tif */, + E337CB9A0CA1B1DE00797802 /* StopPressed.tif */, + ); + name = "Media Bar Custom"; + sourceTree = ""; + }; + E337CBB30CA1B20C00797802 /* Images */ = { + isa = PBXGroup; + children = ( + 72A7E0A20CCD57C2009ED8AC /* Polished Window */, + 72887AA60CCC4EDD00733960 /* Tab Bar */, + E337CBB20CA1B1FE00797802 /* Media Bar Custom */, + E337CBB10CA1B1E100797802 /* Media Bar Default */, + E337CBBA0CA1B22000797802 /* PDURLTextField */, + E337CBC10CA1B23500797802 /* Label Colors */, + ); + name = Images; + sourceTree = ""; + }; + E337CBBA0CA1B22000797802 /* PDURLTextField */ = { + isa = PBXGroup; + children = ( + E337CBB60CA1B21E00797802 /* PDURLTextFieldFileDefault.png */, + E337CBB70CA1B21E00797802 /* PDURLTextFieldWebDefault.tiff */, + ); + name = PDURLTextField; + sourceTree = ""; + }; + E337CBC10CA1B23500797802 /* Label Colors */ = { + isa = PBXGroup; + children = ( + E337CBBB0CA1B23200797802 /* labelall.tif */, + E337CBBC0CA1B23200797802 /* labelhover.tif */, + E337CBBD0CA1B23200797802 /* labelselected.tif */, + ); + name = "Label Colors"; + sourceTree = ""; + }; + E337D4020CA1E4C000797802 /* Sprouted Media PlugIns */ = { + isa = PBXGroup; + children = ( + E337D4040CA1E4D200797802 /* MediaViewer.h */, + E337D4050CA1E4D200797802 /* MediaViewer.m */, + E337CA350CA1B05100797802 /* MediaContentController.h */, + E337CA360CA1B05100797802 /* MediaContentController.m */, + ); + name = "Sprouted Media PlugIns"; + sourceTree = ""; + }; + E337E4160CA3781800797802 /* Nib Inclusive */ = { + isa = PBXGroup; + children = ( + E337CA3D0CA1B05800797802 /* AppleScriptAlert.h */, + E337CA3E0CA1B05800797802 /* AppleScriptAlert.m */, + E337CA3F0CA1B05800797802 /* IntegrationCopyFiles.h */, + E337CA400CA1B05800797802 /* IntegrationCopyFiles.m */, + 724BAC8C0DB9288000DDE79D /* LinkController.h */, + 724BAC8D0DB9288000DDE79D /* LinkController.m */, + 724BACCA0DB929E600DDE79D /* StatsController.h */, + 724BACCB0DB929E600DDE79D /* StatsController.m */, + 72FB5B680E59E1D900BB20D7 /* SproutedAboutBoxController.h */, + 72FB5B690E59E1D900BB20D7 /* SproutedAboutBoxController.m */, + ); + name = "Nib Inclusive"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E337CA370CA1B05100797802 /* SproutedInterface.h in Headers */, + E337CA380CA1B05100797802 /* PDPredicateBuilder.h in Headers */, + E337CA390CA1B05100797802 /* MediaContentController.h in Headers */, + E337CA410CA1B05800797802 /* TransparentWindow.h in Headers */, + E337CA430CA1B05800797802 /* AppleScriptAlert.h in Headers */, + E337CA450CA1B05800797802 /* IntegrationCopyFiles.h in Headers */, + E337CA490CA1B06100797802 /* HUDWindow.h in Headers */, + E337CA4F0CA1B06A00797802 /* PDFavorite.h in Headers */, + E337CA510CA1B06A00797802 /* PDFavoritesBar.h in Headers */, + E337CA5B0CA1B07400797802 /* PDMediaBar.h in Headers */, + E337CA5D0CA1B07400797802 /* PDMediabarItem.h in Headers */, + E337CA5F0CA1B07400797802 /* NewMediabarItemController.h in Headers */, + E337CA610CA1B07400797802 /* MediabarItemApplicationPicker.h in Headers */, + E337CA6F0CA1B09F00797802 /* PDToolbar.h in Headers */, + E337CA710CA1B09F00797802 /* PDPopUpButtonToolbarItem.h in Headers */, + E337CA730CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.h in Headers */, + E337CA750CA1B09F00797802 /* PDSelfValidatingToolbarItem.h in Headers */, + E337CA7F0CA1B0BF00797802 /* PDDateDisplayCell.h in Headers */, + E337CA810CA1B0BF00797802 /* PDHorizontallyCenteredText.h in Headers */, + E337CA830CA1B0BF00797802 /* ImageAndTextCell.h in Headers */, + E337CA9F0CA1B0CB00797802 /* PDTabsView.h in Headers */, + E337CAA10CA1B0CB00797802 /* PDURLTextField.h in Headers */, + E337CAA30CA1B0CB00797802 /* PDURLTextFieldCell.h in Headers */, + E337CAA40CA1B0CB00797802 /* PDPrintTextView.h in Headers */, + E337CAA70CA1B0CB00797802 /* PDBorderedView.h in Headers */, + E337CAA90CA1B0CB00797802 /* RoundedView.h in Headers */, + E337CAAB0CA1B0CB00797802 /* RoundedViewWhiteText.h in Headers */, + E337CAAD0CA1B0CB00797802 /* PDGradientView.h in Headers */, + E337CAAF0CA1B0CB00797802 /* JournlerGradientView.h in Headers */, + E337CAB10CA1B0CB00797802 /* LabelPicker.h in Headers */, + E337CAB30CA1B0CB00797802 /* ConditionController.h in Headers */, + E337CAB50CA1B0CB00797802 /* CollectionManagerView.h in Headers */, + E337CAB70CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.h in Headers */, + E337CADB0CA1B0DF00797802 /* PDButton.h in Headers */, + E337CADD0CA1B0DF00797802 /* PDButtonCell.h in Headers */, + E337CADF0CA1B0DF00797802 /* PDButtonColorWell.h in Headers */, + E337CAE10CA1B0DF00797802 /* PDButtonColorWellCell.h in Headers */, + E337CAE30CA1B0DF00797802 /* PDButtonTextOnImage.h in Headers */, + E337CAE50CA1B0DF00797802 /* PDButtonTextOnImageCell.h in Headers */, + E337CAE70CA1B0DF00797802 /* PDCircleButton.h in Headers */, + E337CAE90CA1B0DF00797802 /* PDCircleButtonCell.h in Headers */, + E337CAEB0CA1B0DF00797802 /* PDInvisibleButton.h in Headers */, + E337CAED0CA1B0DF00797802 /* PDInvisibleButtonCell.h in Headers */, + E337CAEF0CA1B0DF00797802 /* PDMatrixButton.h in Headers */, + E337CAF10CA1B0DF00797802 /* PDMatrixButtonCell.h in Headers */, + E337CAF30CA1B0DF00797802 /* PDPopUpButton.h in Headers */, + E337CAF50CA1B0DF00797802 /* PDPopUpButtonCell.h in Headers */, + E337CAF70CA1B0DF00797802 /* PDStylesButton.h in Headers */, + E337CAF90CA1B0DF00797802 /* PDStylesButtonCell.h in Headers */, + E337CB160CA1B10C00797802 /* MUPhotoView.h in Headers */, + E337CB1E0CA1B11F00797802 /* RBSplitSubview.h in Headers */, + E337CB200CA1B11F00797802 /* RBSplitView.h in Headers */, + E337CB220CA1B11F00797802 /* RBSplitViewPrivateDefines.h in Headers */, + E337D4060CA1E4D200797802 /* MediaViewer.h in Headers */, + E337DA990CA2F80F00797802 /* CustomFindPanel.h in Headers */, + E337DB880CA2F8BB00797802 /* EtchedText.h in Headers */, + E337DB8A0CA2F8BB00797802 /* EtchedTextCell.h in Headers */, + E337DFD00CA3052A00797802 /* PDAutoCompleteTextField.h in Headers */, + E337E2AD0CA33F7100797802 /* PDFileInfoView.h in Headers */, + E3046CF80CACE76E006A17BB /* DocumentMakerController.h in Headers */, + 728868ED0CC689D700733960 /* PDRankCell.h in Headers */, + 728868F10CC689E500733960 /* PDBlueHighlightTextCell.h in Headers */, + 72886AED0CC7C5FB00733960 /* PDFontPreview.h in Headers */, + 72886AEF0CC7C5FB00733960 /* PDFontDisplay.h in Headers */, + 72886B4E0CC7C70100733960 /* PDColorWell.h in Headers */, + 72886B650CC7C7ED00733960 /* JRLRFooter.h in Headers */, + 72886B7D0CC7C92600733960 /* DragView.h in Headers */, + 72A7DCD20CCD0C1C009ED8AC /* EtchedPopUpButton.h in Headers */, + 72A7DCD40CCD0C1C009ED8AC /* EtchedPopUpButtonCell.h in Headers */, + 72A7E09F0CCD574C009ED8AC /* PolishedWindow.h in Headers */, + 724BAC8E0DB9288000DDE79D /* LinkController.h in Headers */, + 724BACCC0DB929E600DDE79D /* StatsController.h in Headers */, + 72C95BD00DBE48B3005440D5 /* PDPhotoView.h in Headers */, + 72C95BD20DBE48B3005440D5 /* MUPhotoCell.h in Headers */, + 7269D0140DD10821005AD452 /* PDTokenField.h in Headers */, + 7269D0160DD10821005AD452 /* PDTokenFieldCell.h in Headers */, + 7269D0A00DD10C75005AD452 /* PDTableView.h in Headers */, + 7269D0A20DD10C75005AD452 /* PDOutlineView.h in Headers */, + 72FB5B6A0E59E1D900BB20D7 /* SproutedAboutBoxController.h in Headers */, + 727F6F590F462A4E00CFCECB /* SproutedAnchoredDocumentView.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8DC2EF4F0486A6940098B216 /* Sprouted Interface */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Sprouted Interface" */; + buildPhases = ( + 8DC2EF500486A6940098B216 /* Headers */, + 8DC2EF520486A6940098B216 /* Resources */, + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Sprouted Interface"; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = "Sprouted Interface"; + productReference = 8DC2EF5B0486A6940098B216 /* SproutedInterface.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Sprouted Interface" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + de, + da, + d, + ); + mainGroup = 0867D691FE84028FC02AAC07 /* Sprouted Interface */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* Sprouted Interface */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8DC2EF520486A6940098B216 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, + E337CB320CA1B15300797802 /* hud_titlebar-close.tiff in Resources */, + E337CB3E0CA1B17200797802 /* AppleScriptActionBarSmall.png in Resources */, + E337CB460CA1B18000797802 /* InfoBarSmall.png in Resources */, + E337CB4D0CA1B18D00797802 /* iTunesBarSmall.png in Resources */, + E337CB4E0CA1B18D00797802 /* PreviewBarSmall.png in Resources */, + E337CB570CA1B19900797802 /* QTBarSmall.png in Resources */, + E337CB580CA1B19900797802 /* RevealInFinderBarSmall.png in Resources */, + E337CB650CA1B1AA00797802 /* TextEditBarSmall.png in Resources */, + E337CB660CA1B1AA00797802 /* WordBarSmall.png in Resources */, + E337CB9B0CA1B1DE00797802 /* ActualSize.png in Resources */, + E337CB9C0CA1B1DE00797802 /* ActualSizePressed.png in Resources */, + E337CB9D0CA1B1DE00797802 /* Back.tif in Resources */, + E337CB9E0CA1B1DE00797802 /* BackDisabled.tif in Resources */, + E337CB9F0CA1B1DE00797802 /* BackPressed.tif in Resources */, + E337CBA00CA1B1DE00797802 /* Bigger.png in Resources */, + E337CBA10CA1B1DE00797802 /* BiggerDisabled.png in Resources */, + E337CBA20CA1B1DE00797802 /* BiggerPressed.png in Resources */, + E337CBA30CA1B1DE00797802 /* Display.png in Resources */, + E337CBA40CA1B1DE00797802 /* DisplayPressed.png in Resources */, + E337CBA50CA1B1DE00797802 /* Forward.tif in Resources */, + E337CBA60CA1B1DE00797802 /* ForwardDisabled.tif in Resources */, + E337CBA70CA1B1DE00797802 /* ForwardPressed.tif in Resources */, + E337CBA80CA1B1DE00797802 /* Home.tif in Resources */, + E337CBA90CA1B1DE00797802 /* HomePressed.tif in Resources */, + E337CBAA0CA1B1DE00797802 /* Reload.tif in Resources */, + E337CBAB0CA1B1DE00797802 /* ReloadPressed.tif in Resources */, + E337CBAC0CA1B1DE00797802 /* Smaller.png in Resources */, + E337CBAD0CA1B1DE00797802 /* SmallerDisabled.png in Resources */, + E337CBAE0CA1B1DE00797802 /* SmallerPressed.png in Resources */, + E337CBAF0CA1B1DE00797802 /* Stop.tif in Resources */, + E337CBB00CA1B1DE00797802 /* StopPressed.tif in Resources */, + E337CBB80CA1B21E00797802 /* PDURLTextFieldFileDefault.png in Resources */, + E337CBB90CA1B21E00797802 /* PDURLTextFieldWebDefault.tiff in Resources */, + E337CBBE0CA1B23200797802 /* labelall.tif in Resources */, + E337CBBF0CA1B23200797802 /* labelhover.tif in Resources */, + E337CBC00CA1B23200797802 /* labelselected.tif in Resources */, + E337CBED0CA1B2F300797802 /* IntegrationFileCopy.nib in Resources */, + E337CBEE0CA1B2F300797802 /* Mediabar.strings in Resources */, + E337CBEF0CA1B2F300797802 /* NewMediabarItem.nib in Resources */, + E337E4120CA3780000797802 /* FileInfo.strings in Resources */, + 72887A9E0CCC4EDB00733960 /* more.tif in Resources */, + 72887A9F0CCC4EDB00733960 /* tabcloseback.tif in Resources */, + 72887AA00CCC4EDB00733960 /* tabclosebackdown.tif in Resources */, + 72887AA10CCC4EDB00733960 /* tabclosebackroll.tif in Resources */, + 72887AA20CCC4EDB00733960 /* tabclosefront.tif in Resources */, + 72887AA30CCC4EDB00733960 /* tabclosefrontdown.tif in Resources */, + 72887AA40CCC4EDB00733960 /* tabclosefrontroll.tif in Resources */, + 72A7DE650CCD1CD0009ED8AC /* EmailBarSmall.png in Resources */, + 72A7DE6D0CCD1D9A009ED8AC /* ABBarSmall.png in Resources */, + 72A7DE710CCD1DA3009ED8AC /* ComposeMailBarSmall.png in Resources */, + 72A7DE750CCD1DDD009ED8AC /* SafariBarSmall.png in Resources */, + 72A7E0AE0CCD57DA009ED8AC /* flat_bottom_left.png in Resources */, + 72A7E0AF0CCD57DA009ED8AC /* flat_bottom_middle.png in Resources */, + 72A7E0B00CCD57DA009ED8AC /* flat_bottom_right.png in Resources */, + 72A7E0B10CCD57DA009ED8AC /* flat_middle_left.png in Resources */, + 72A7E0B20CCD57DA009ED8AC /* flat_middle_right.png in Resources */, + 72A7E0B30CCD57DA009ED8AC /* flat_top_left.png in Resources */, + 72A7E0B40CCD57DA009ED8AC /* flat_top_middle.png in Resources */, + 72A7E0B50CCD57DA009ED8AC /* flat_top_right.png in Resources */, + 7298530D0CD27ECD00BB4A53 /* PDFontPreview.strings in Resources */, + 729853310CD27FAA00BB4A53 /* PDTabsView.strings in Resources */, + 7298533D0CD27FF100BB4A53 /* PDFavoritesBar.strings in Resources */, + 724BACA50DB928F500DDE79D /* InsertLink.nib in Resources */, + 724BAD680DB92A6200DDE79D /* Stats.nib in Resources */, + 723F4F110F6F0BA400212DFE /* SproutedAboutBox.nib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E337CA3A0CA1B05100797802 /* MediaContentController.m in Sources */, + E337CA420CA1B05800797802 /* TransparentWindow.m in Sources */, + E337CA440CA1B05800797802 /* AppleScriptAlert.m in Sources */, + E337CA460CA1B05800797802 /* IntegrationCopyFiles.m in Sources */, + E337CA4A0CA1B06100797802 /* HUDWindow.m in Sources */, + E337CA500CA1B06A00797802 /* PDFavorite.m in Sources */, + E337CA520CA1B06A00797802 /* PDFavoritesBar.m in Sources */, + E337CA5C0CA1B07400797802 /* PDMediaBar.m in Sources */, + E337CA5E0CA1B07400797802 /* PDMediabarItem.m in Sources */, + E337CA600CA1B07400797802 /* NewMediabarItemController.m in Sources */, + E337CA620CA1B07400797802 /* MediabarItemApplicationPicker.m in Sources */, + E337CA700CA1B09F00797802 /* PDToolbar.m in Sources */, + E337CA720CA1B09F00797802 /* PDPopUpButtonToolbarItem.m in Sources */, + E337CA740CA1B09F00797802 /* PDPopUpButtonToolbarItemCell.m in Sources */, + E337CA760CA1B09F00797802 /* PDSelfValidatingToolbarItem.m in Sources */, + E337CA800CA1B0BF00797802 /* PDDateDisplayCell.m in Sources */, + E337CA820CA1B0BF00797802 /* PDHorizontallyCenteredText.m in Sources */, + E337CA840CA1B0BF00797802 /* ImageAndTextCell.m in Sources */, + E337CAA00CA1B0CB00797802 /* PDTabsView.m in Sources */, + E337CAA20CA1B0CB00797802 /* PDURLTextField.m in Sources */, + E337CAA50CA1B0CB00797802 /* PDPrintTextView.m in Sources */, + E337CAA60CA1B0CB00797802 /* PDURLTextFieldCell.m in Sources */, + E337CAA80CA1B0CB00797802 /* PDBorderedView.m in Sources */, + E337CAAA0CA1B0CB00797802 /* RoundedView.m in Sources */, + E337CAAC0CA1B0CB00797802 /* RoundedViewWhiteText.m in Sources */, + E337CAAE0CA1B0CB00797802 /* PDGradientView.m in Sources */, + E337CAB00CA1B0CB00797802 /* JournlerGradientView.m in Sources */, + E337CAB20CA1B0CB00797802 /* LabelPicker.m in Sources */, + E337CAB40CA1B0CB00797802 /* ConditionController.m in Sources */, + E337CAB60CA1B0CB00797802 /* CollectionManagerView.m in Sources */, + E337CAB80CA1B0CB00797802 /* PDCaseInsensitiveComboBoxCell.m in Sources */, + E337CADC0CA1B0DF00797802 /* PDButton.m in Sources */, + E337CADE0CA1B0DF00797802 /* PDButtonCell.m in Sources */, + E337CAE00CA1B0DF00797802 /* PDButtonColorWell.m in Sources */, + E337CAE20CA1B0DF00797802 /* PDButtonColorWellCell.m in Sources */, + E337CAE40CA1B0DF00797802 /* PDButtonTextOnImage.m in Sources */, + E337CAE60CA1B0DF00797802 /* PDButtonTextOnImageCell.m in Sources */, + E337CAE80CA1B0DF00797802 /* PDCircleButton.m in Sources */, + E337CAEA0CA1B0DF00797802 /* PDCircleButtonCell.m in Sources */, + E337CAEC0CA1B0DF00797802 /* PDInvisibleButton.m in Sources */, + E337CAEE0CA1B0DF00797802 /* PDInvisibleButtonCell.m in Sources */, + E337CAF00CA1B0DF00797802 /* PDMatrixButton.m in Sources */, + E337CAF20CA1B0DF00797802 /* PDMatrixButtonCell.m in Sources */, + E337CAF40CA1B0DF00797802 /* PDPopUpButton.m in Sources */, + E337CAF60CA1B0DF00797802 /* PDPopUpButtonCell.m in Sources */, + E337CAF80CA1B0DF00797802 /* PDStylesButton.m in Sources */, + E337CAFA0CA1B0DF00797802 /* PDStylesButtonCell.m in Sources */, + E337CB170CA1B10C00797802 /* MUPhotoView.m in Sources */, + E337CB1F0CA1B11F00797802 /* RBSplitSubview.m in Sources */, + E337CB210CA1B11F00797802 /* RBSplitView.m in Sources */, + E337DA9A0CA2F80F00797802 /* CustomFindPanel.m in Sources */, + E337DB890CA2F8BB00797802 /* EtchedText.m in Sources */, + E337DB8B0CA2F8BB00797802 /* EtchedTextCell.m in Sources */, + E337DFD10CA3052A00797802 /* PDAutoCompleteTextField.m in Sources */, + E337E2AE0CA33F7100797802 /* PDFileInfoView.m in Sources */, + E3046CF90CACE76E006A17BB /* DocumentMakerController.m in Sources */, + 728868EE0CC689D700733960 /* PDRankCell.m in Sources */, + 728868F20CC689E500733960 /* PDBlueHighlightTextCell.m in Sources */, + 72886AEE0CC7C5FB00733960 /* PDFontPreview.m in Sources */, + 72886AF00CC7C5FB00733960 /* PDFontDisplay.m in Sources */, + 72886B4F0CC7C70100733960 /* PDColorWell.m in Sources */, + 72886B660CC7C7ED00733960 /* JRLRFooter.m in Sources */, + 72886B7E0CC7C92600733960 /* DragView.m in Sources */, + 72A7DCD30CCD0C1C009ED8AC /* EtchedPopUpButton.m in Sources */, + 72A7DCD50CCD0C1C009ED8AC /* EtchedPopUpButtonCell.m in Sources */, + 72A7E0A00CCD574C009ED8AC /* PolishedWindow.m in Sources */, + 724BAC8F0DB9288000DDE79D /* LinkController.m in Sources */, + 724BACCD0DB929E600DDE79D /* StatsController.m in Sources */, + 72C95BD10DBE48B3005440D5 /* PDPhotoView.m in Sources */, + 72C95BD30DBE48B3005440D5 /* MUPhotoCell.m in Sources */, + 7269D0150DD10821005AD452 /* PDTokenField.m in Sources */, + 7269D0170DD10821005AD452 /* PDTokenFieldCell.m in Sources */, + 7269D0A10DD10C75005AD452 /* PDTableView.m in Sources */, + 7269D0A30DD10C75005AD452 /* PDOutlineView.m in Sources */, + 72FB5B6B0E59E1D900BB20D7 /* SproutedAboutBoxController.m in Sources */, + 727F6F580F462A4E00CFCECB /* SproutedAnchoredDocumentView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C1667FE841158C02AAC07 /* English */, + 729853830CD28BB200BB4A53 /* da */, + 729853840CD28BB400BB4A53 /* de */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 723F4F0F0F6F0BA400212DFE /* SproutedAboutBox.nib */ = { + isa = PBXVariantGroup; + children = ( + 723F4F100F6F0BA400212DFE /* English */, + 723F4F130F6F0BB200212DFE /* da */, + 723F4F150F6F0BB800212DFE /* de */, + ); + name = SproutedAboutBox.nib; + sourceTree = ""; + }; + 724BACA30DB928F500DDE79D /* InsertLink.nib */ = { + isa = PBXVariantGroup; + children = ( + 724BACA40DB928F500DDE79D /* English */, + 724BACAA0DB9290300DDE79D /* da */, + 724BACA60DB928FA00DDE79D /* de */, + ); + name = InsertLink.nib; + sourceTree = ""; + }; + 724BAD660DB92A6200DDE79D /* Stats.nib */ = { + isa = PBXVariantGroup; + children = ( + 724BAD670DB92A6200DDE79D /* English */, + 724BAD690DB92A6900DDE79D /* da */, + 724BAD6D0DB92A6E00DDE79D /* de */, + ); + name = Stats.nib; + sourceTree = ""; + }; + 7298530B0CD27ECD00BB4A53 /* PDFontPreview.strings */ = { + isa = PBXVariantGroup; + children = ( + 7298530C0CD27ECD00BB4A53 /* English */, + 729853790CD28A5000BB4A53 /* de */, + 7298537A0CD28A5200BB4A53 /* da */, + ); + name = PDFontPreview.strings; + sourceTree = ""; + }; + 7298532F0CD27FAA00BB4A53 /* PDTabsView.strings */ = { + isa = PBXVariantGroup; + children = ( + 729853300CD27FAA00BB4A53 /* English */, + 729853770CD28A4900BB4A53 /* de */, + 729853780CD28A4A00BB4A53 /* da */, + ); + name = PDTabsView.strings; + sourceTree = ""; + }; + 7298533B0CD27FF100BB4A53 /* PDFavoritesBar.strings */ = { + isa = PBXVariantGroup; + children = ( + 7298533C0CD27FF100BB4A53 /* English */, + 729853750CD28A4000BB4A53 /* de */, + 729853760CD28A4200BB4A53 /* da */, + ); + name = PDFavoritesBar.strings; + sourceTree = ""; + }; + E337CBE70CA1B2F300797802 /* IntegrationFileCopy.nib */ = { + isa = PBXVariantGroup; + children = ( + E337CBE80CA1B2F300797802 /* English */, + 729853860CD28BEB00BB4A53 /* de */, + 729853890CD28BF300BB4A53 /* da */, + ); + name = IntegrationFileCopy.nib; + sourceTree = ""; + }; + E337CBE90CA1B2F300797802 /* Mediabar.strings */ = { + isa = PBXVariantGroup; + children = ( + E337CBEA0CA1B2F300797802 /* English */, + 7298537D0CD28A5E00BB4A53 /* de */, + 7298537F0CD28A6900BB4A53 /* da */, + ); + name = Mediabar.strings; + sourceTree = ""; + }; + E337CBEB0CA1B2F300797802 /* NewMediabarItem.nib */ = { + isa = PBXVariantGroup; + children = ( + E337CBEC0CA1B2F300797802 /* English */, + 729853850CD28BEB00BB4A53 /* de */, + 729853880CD28BF300BB4A53 /* da */, + ); + name = NewMediabarItem.nib; + sourceTree = ""; + }; + E337E4110CA3780000797802 /* FileInfo.strings */ = { + isa = PBXVariantGroup; + children = ( + E337E40D0CA377FC00797802 /* English */, + 7298537B0CD28A5800BB4A53 /* de */, + 7298537C0CD28A5900BB4A53 /* da */, + ); + name = FileInfo.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)\""; + FRAMEWORK_VERSION = A; + 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 = "Sprouted Interface_Prefix.pch"; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = SproutedInterface; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WRAPPER_EXTENSION = framework; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)\""; + FRAMEWORK_VERSION = A; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Sprouted Interface_Prefix.pch"; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = SproutedInterface; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; + ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Sprouted Interface" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Sprouted Interface" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/Sprouted Interface_Prefix.pch b/Sprouted Interface_Prefix.pch new file mode 100644 index 0000000..e362bcc --- /dev/null +++ b/Sprouted Interface_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'Sprouted Interface' target in the 'Sprouted Interface' project. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/SproutedAboutBoxController.h b/SproutedAboutBoxController.h new file mode 100644 index 0000000..6d8b25e --- /dev/null +++ b/SproutedAboutBoxController.h @@ -0,0 +1,24 @@ +// +// SproutedAboutBoxController.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + + +#import + +@interface SproutedAboutBoxController : NSWindowController +{ + IBOutlet NSTextView *additionalText; + IBOutlet NSTextField *appnameField; + IBOutlet NSImageView *imageView; + IBOutlet NSTextField *versionField; + IBOutlet NSTextView *aboutText; +} + ++ (id)sharedController; + +@end diff --git a/SproutedAboutBoxController.m b/SproutedAboutBoxController.m new file mode 100644 index 0000000..1b9166a --- /dev/null +++ b/SproutedAboutBoxController.m @@ -0,0 +1,89 @@ +// +// SproutedAboutBoxController.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@implementation SproutedAboutBoxController + ++ (id)sharedController +{ + static SproutedAboutBoxController *sharedAboutBoxController = nil; + + if (!sharedAboutBoxController) + { + sharedAboutBoxController = [[SproutedAboutBoxController allocWithZone:NULL] init]; + } + + return sharedAboutBoxController; +} + +- (id)init +{ + if ( self = [self initWithWindowNibName:@"SproutedAboutBox"] ) + { + [self window]; + } + return self; +} + +- (void) awakeFromNib +{ + [[additionalText enclosingScrollView] setDrawsBackground:NO]; + [additionalText setDrawsBackground:NO]; +} + +- (void)dealloc +{ + [super dealloc]; +} + +- (void) windowDidLoad +{ + // set the window's background color + [[self window] setBackgroundColor:[NSColor whiteColor]]; + + // prepare other fields with default values taken from the apps info.plist files + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; + NSDictionary *localInfoDictionary = (NSDictionary *)CFBundleGetLocalInfoDictionary( CFBundleGetMainBundle() ); + + NSString *shortVersion = [localInfoDictionary objectForKey:@"CFBundleShortVersionString"]; + NSString *version = [infoDictionary objectForKey:@"CFBundleVersion"]; + + NSString *versionString = [NSString stringWithFormat:@"Version %@ (%@)", + ( shortVersion != nil ? shortVersion : @"" ), ( version != nil ? version : @"" )]; + + [appnameField setStringValue:[localInfoDictionary objectForKey:@"CFBundleName"]]; + [versionField setStringValue:versionString]; + + [aboutText setTextContainerInset:NSMakeSize(5,10)]; + + // prepare the about text + NSString *path = [[NSBundle mainBundle] pathForResource:@"SproutedAboutBoxText" ofType:@"rtf"]; + if ( path == nil ) path = [[NSBundle mainBundle] pathForResource:@"SproutedAboutBoxText" ofType:@"rtfd"]; + if ( path == nil ) + NSLog(@"%@ %s - unable to locate SproutedAboutBoxText.rtf or SproutedAboutBoxText.rtfd in the application bundle", [self className], _cmd); + else { + [aboutText readRTFDFromFile:path]; + } +} + +#pragma mark - + +- (IBAction)showWindow:(id)sender +{ + [NSApp runModalForWindow:[self window]]; +} + +- (void)windowWillClose:(NSNotification *)aNotification +{ + if ( [NSApp modalWindow] == [self window] ) + [NSApp stopModal]; +} + +@end diff --git a/SproutedAnchoredDocumentView.h b/SproutedAnchoredDocumentView.h new file mode 100644 index 0000000..ec8f0b2 --- /dev/null +++ b/SproutedAnchoredDocumentView.h @@ -0,0 +1,18 @@ +// +// SproutedAnchoredDocumentView.h +// SproutedInterface +// +// Created by Philip Dow on 8/26/08. +// Copyright 2008 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// +// Code from CocoaDev + +#import + + +@interface SproutedAnchoredDocumentView : NSView { + float startHeight; +} + +@end diff --git a/SproutedAnchoredDocumentView.m b/SproutedAnchoredDocumentView.m new file mode 100644 index 0000000..6c51f36 --- /dev/null +++ b/SproutedAnchoredDocumentView.m @@ -0,0 +1,27 @@ +// +// SproutedAnchoredDocumentView.m +// SproutedInterface +// +// Created by Philip Dow on 8/26/08. +// Copyright 2008 Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + + +@implementation SproutedAnchoredDocumentView + +- (id)initWithFrame:(NSRect)frame { + if ([super initWithFrame:frame]) { + startHeight = NSHeight(frame); + } + return self; +} + +- (void)setFrame:(NSRect)frame { + frame.size.height = MAX([[[self enclosingScrollView] contentView] frame].size.height, startHeight); + [super setFrame:frame]; +} + +@end diff --git a/SproutedInterface.h b/SproutedInterface.h new file mode 100644 index 0000000..f081b3b --- /dev/null +++ b/SproutedInterface.h @@ -0,0 +1,110 @@ + +// +// SproutedInterface.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + + +#define kWebURLsWithTitlesPboardType @"WebURLsWithTitlesPboardType" +#define kMailMessagePboardType @"MV Super-secret message transfer pasteboard type" + +#import + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#import +#import + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include diff --git a/StatsController.h b/StatsController.h new file mode 100644 index 0000000..5296571 --- /dev/null +++ b/StatsController.h @@ -0,0 +1,27 @@ +// +// StatsController.h +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + +#import + +@interface StatsController : NSWindowController +{ + IBOutlet NSTextField *charsField; + IBOutlet NSTextField *parsField; + IBOutlet NSTextField *wordsField; +} + +- (int) runAsSheetForWindow:(NSWindow*)window + attached:(BOOL)sheet + chars:(int)charNum + words:(int)wordNum + pars:(int)parNum; + +- (IBAction)genericStop:(id)sender; + +@end diff --git a/StatsController.m b/StatsController.m new file mode 100644 index 0000000..b0f614f --- /dev/null +++ b/StatsController.m @@ -0,0 +1,69 @@ + +// +// StatsController.m +// SproutedInterface +// +// Created by Philip Dow on xx. +// Copyright Sprouted. All rights reserved. +// Inquiries should be directed to developer@journler.com +// + + +#import + +@implementation StatsController + +- (id)init { + if ( self = [self initWithWindowNibName:@"Stats"] ) { + [self window]; + } + return self; +} + +- (void) dealloc { + [super dealloc]; +} + +- (void)windowWillClose:(NSNotification *)aNotification { + +} + +- (int) runAsSheetForWindow:(NSWindow*)window + attached:(BOOL)sheet + chars:(int)charNum + words:(int)wordNum + pars:(int)parNum { + + int result; + + [charsField setIntValue:charNum]; + [wordsField setIntValue:wordNum]; + [parsField setIntValue:parNum]; + + if ( sheet ) { + + [[self window] setAlphaValue:0.99]; + [[self window] setBackgroundColor:[NSColor whiteColor]]; + + [NSApp beginSheet: [self window] modalForWindow: window modalDelegate: nil + didEndSelector: nil contextInfo: nil]; + + } + + result = [NSApp runModalForWindow: [self window]]; + + if ( sheet ) + [NSApp endSheet: [self window]]; + + [self close]; + + return result; + +} + +- (IBAction)genericStop:(id)sender +{ + [NSApp stopModal]; +} + +@end diff --git a/Stop.tif b/Stop.tif new file mode 100644 index 0000000000000000000000000000000000000000..41f2f0397c57c690bccdcbb051acc88072dbd218 GIT binary patch literal 1564 zcmYj~3pmqz7{~vA8S+q@HcQ6VaoKX|YA)qc8jcg$$Z&EwVzdsKQgU4Wsl%jHn9I=q zU5Iiz9<`FBR3s${U5LoFkqn!RUCz#Vbk2Ex&-4C1&*y!=@9XIam;nHSejFfBZINfS z>^H6U_=)3efE;%(&50Sl>`78&HVtjc;2$CzWIYSlv6bdK5VIQhvEC<{V%1RR2)VX; z8Yi5cOUk``LjQQL*h1ZpHd|iAcD?*su&0QjbK%GGj&ZA=v^9xN7jV2=%tj@8Uc4(d&F~z8$~QYxzyTtZnk({lF@ly?r0WEIt`O=etun%}(}vn%+q#mtK43 z)R$nN?_)agd~~y^DAb#+*O39+PC2FSl0sk4?uMoc8$ z>z%66PyTv1wxM^LtmiQ2lUO)5ZHN1)jy+lT`p97|!y(1K=%kK#*#_ddmrb+6`rr_^ znst>|xcS3}`s7stq;>(HNCS$SADpqw}=dS7G4Mz#tt;>>1mzr|kJF`tVR`+&xzs+F=Eyd53(z z-e{^k%pKX%ZvxK*^qaQi#9bmj_s*^}hX?I%TfErExesw~X_ar{u39H2zSJ2w3!U1+ zRG1gv!d045A{xIyTs8Oe&?{Gu&Bv(fGT<0>kG8sVJI4XDox^9!jlI#yMjJHUBo}tQ zT4mKv>~MD33gwBlQMC54gg#=Mx}=c7&1Q1xZ^Q>GARhS!b1%I-D<;T~+?O2uj?diX z)qxgX3u~SAJnfaQ8w~~0Um18u_ON9Ykv(s3RB7?(0>wcdT~^Nu^wVxR+#B!t*e598 z#E8+&V2m94$gz8o2#>xIK}GSC^UO7olCsnRe}tU5lgL9upWJwQX`k+<7-S3pjaEnwtv1;wzWR!}mg_cr0eShvVE z4mX2J2`T6d?@gNk;pSx{pI}DG`Nuh$k6&z!D5Uc%II6_22xq&grwXtLK#VzoH9b_}L zI9>ms_k9& z{BXDR?)Ve<9B5c2RUWlq2tMigErnP)a5T6%t$UH$GBpLuB~wD_%B~$bC2UEv7#<^b za{?S$rzG$Q9xE<^{6go3`{QSb7Xd{|C=yEZ*Al8NHXdDBmh-SscQNF{*VJ=2)h=aE zBbudHye1~d=2ENEfQS$iCaZrm-TIL&;aj)lIh;L4TmE4vF@0lJz0I=&PEQFQAxsa}5E{lBE z(+*iQk(zalKvpI#>S5D-v;JV02i|BT#4xlcDN7XZnBDscKlBOTW|8EWqhgPv;JkOw zOZ0^%B$CVSjJ(YT?w`dvX5mR0#{9e-QWNQV9NDye(3i700adonFgJYWD0{~Eo%Y%w z^Ddn`)bTgY7T`b?+N!od=c|8Z8BnF3d5YSJ*xS19SIdFn7MhRFFRcg-bA*2-`Kqnq zOKK0{YQsXXbM?*JBki>X-lF2!OjeuSOS?$QK%iw-m1niWS{1oabWvn|-mPdY#Y$pW zQ5Nv3qulBFbv?LCEtOO1<4D;k<_)(OsVv}Ds#>BjKMZEBsPK16_tf*^95_=xzRmTs z7+1O{J;z(q(@o%FBkBR<_t&v(?+T11mrPSOx$92;h_jTw*;XtNg>N z0HCG{E?e>lrB_>G6(yqpWnY;E01XhcL*AYFeQFzl;WP dOIc+HB>iu{_kUiQQ(jqmn$qI{Ktuvd|6e&=xRU?? literal 0 HcmV?d00001 diff --git a/StopPressed.tif b/StopPressed.tif new file mode 100644 index 0000000000000000000000000000000000000000..e144aead64d20dbde9d5f89558ec18237da904a8 GIT binary patch literal 20156 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 +// + + +#import + +@interface TransparentWindow : NSWindow +{ + BOOL _closesOnEvent; + NSPoint initialLocation; +} + +- (BOOL) closesOnEvent; +- (void) setClosesOnEvent:(BOOL)closes; + +- (void) completelyFillScreen; +- (void) fillScreenHorizontallyAndCenter; + +@end diff --git a/TransparentWindow.m b/TransparentWindow.m new file mode 100644 index 0000000..a827b20 --- /dev/null +++ b/TransparentWindow.m @@ -0,0 +1,103 @@ +// +// TransparentWindow.m +// RoundedFloatingPanel +// +// Created by Matt Gemmell on Thu Jan 08 2004. +// +// + +#define kEdgeInset 40 +#define kWinHeight 186 + +#import + +@implementation TransparentWindow + +- (id)init { + return [self initWithContentRect:NSMakeRect(0,0,186,186) styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered defer:NO]; +} + +- (id)initWithContentRect:(NSRect)contentRect + styleMask:(unsigned int)aStyle + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag { + + if (self = [super initWithContentRect:contentRect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]) { + [self setLevel: NSStatusWindowLevel]; + [self setBackgroundColor: [NSColor clearColor]]; + [self setAlphaValue:1.0]; + [self setOpaque:NO]; + [self setHasShadow:NO]; + + [self setReleasedWhenClosed:YES]; + + return self; + } + + return nil; +} + +- (BOOL) closesOnEvent +{ + return _closesOnEvent; +} + +- (void) setClosesOnEvent:(BOOL)closes +{ + _closesOnEvent = closes; +} + +- (void) fillScreenHorizontallyAndCenter +{ + + NSScreen *screen = [NSScreen mainScreen]; + NSRect visible_frame = [screen visibleFrame]; + + NSRect win_frame = NSMakeRect( kEdgeInset, 20, visible_frame.size.width - kEdgeInset*2, kWinHeight ); + [self setFrame:win_frame display:NO]; + [self center]; +} + +- (void) completelyFillScreen +{ + [self setFrame:[[NSScreen mainScreen] frame] display:YES]; +} + +- (BOOL) canBecomeKeyWindow +{ + return YES; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + if ( _closesOnEvent ) + [self close]; + else + [super mouseDown:theEvent]; +} + +- (void)keyDown:(NSEvent *)theEvent +{ + if ( _closesOnEvent ) + [self close]; + else + [super keyDown:theEvent]; +} + +- (void)resignKeyWindow +{ + if ( _closesOnEvent ) + [self close]; +} + +- (void)resignMainWindow +{ + if ( _closesOnEvent ) + [self close]; +} + +@end diff --git a/Version History.rtf b/Version History.rtf new file mode 100644 index 0000000..99fc09d --- /dev/null +++ b/Version History.rtf @@ -0,0 +1,22 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid1} +{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid2}} +{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}} +\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural +\ls1\ilvl0 +\f0\b\fs24 \cf0 \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural +\ls1\ilvl0\cf0 101 +\b0 \ +\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural +\ls1\ilvl0\cf0 {\listtext \'95 }Cleaned up initial document comments +\b \ +\ + \ +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural +\cf0 100 +\b0 \ +\pard\tx220\tx720\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li720\fi-720\ql\qnatural\pardirnatural +\ls2\ilvl0\cf0 {\listtext \'95 }Initial release.} \ No newline at end of file diff --git a/WordBarSmall.png b/WordBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..34f8d394fd8601ad7a0158d878b6be5183ccf7d4 GIT binary patch literal 1357 zcmV-T1+w~yP)gUYsZf~+$7F}JesCyX`3jOT3XRo6cC3d5(fkaK%y7mPOqp)NE|pI z1QHSwH^hlU1sBAj2TGwuk%~&GLz~1-LLArL_j-3{hgmyG6DZI_JJPOJ^J~8Ee|-Nx zix6M%7#F_($yn=ov`Yw)Tew&PKm>r=P0J&SjD#pCI({DK=RU`M&%Xu9;eAa1vy7;= z`tKy6M@`fJI)RYbeUkLP_B|ea0%H3{Kq>Tterr*yfBEK1P``fZA0&)z=Mg4Buu@2R7uZW{FI?+7TAuu@Nd*};^ow+ryLx;CWF!w)QjRntMM*LDTS> zLQ%$#OaY3dTQUx-88kpIUZa`;j@ID97C}tsd$%=D>sp{!Y}c?r>>e8C9%P#Y%)0w6 zGd3(wGr_26V5kl7EDsWez6^?Y_1%{oNXTAWpsEJ0Y4ff@Am)Z9x9k!@9jsQdsN?cr zl5rGEZIM}(yUjG+(?RDcuuT`D?I|SWh7YlA?en5}YL%%fcn0rB=7ZcbG0mx^ z(8z*@#?*Dwvm6kjF@j^s4&3yMQ-HO6ty$>024;G# z0@DPft!da;TXt8AMQ`!yk8XA07tgE~Df3FaP7Xt@f`!mK3HUtW>JsIFh!{VBvlC~a zbMi@+?CC=YGiYbncM!iUZtp!{jI~sBOeSdHFJZ}y`j7dU7q?2Hh z;}=FeVAQ6*U8XEp=YSU54fvlI4|?#W&)9=*=Z67&NP@@mSMhk(UjhsOM5I$yO*A}P P00000NkvXXu0mjfy*F@0 literal 0 HcmV?d00001 diff --git a/da.lproj/FileInfo.strings b/da.lproj/FileInfo.strings new file mode 100644 index 0000000..83ac170 --- /dev/null +++ b/da.lproj/FileInfo.strings @@ -0,0 +1,10 @@ + +"mditem title name" = "Title"; +"mditem kind name" = "Art"; +"mditem size name" = "Størrelse"; +"mditem size kb" = "KB på disk"; +"mditem size mb" = "MB på disk"; +"mditem size gb" = "GB på disk"; +"mditem created name" = "Oprettet"; +"mditem modified name" = "Ændret"; +"mditem lastopened name" = "Sidst åbnet"; diff --git a/da.lproj/InfoPlist.strings b/da.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..befb935928a91b7a4f445b0cd6df7a65ec416b4a GIT binary patch literal 210 zcmW-bO%B0O7)8(6D#Wl66%zw7Vn8Ayx`Lu;&^E0Sc4U({ZC>*I+;{JJ@AnM}=&~Yb zPt28+Hwg!|hrOgy$;s?p`_Z~|J30?2T7Sh|^`iULx&lHvo;48*YHo5fw%*5bV|Jzz uW)cb$rTi1;mNAvn<73^Zq%FO0o9lhjcZ$rEZnggAmyI@J=oy=w`05{6P$Z-P literal 0 HcmV?d00001 diff --git a/da.lproj/InsertLink.nib/classes.nib b/da.lproj/InsertLink.nib/classes.nib new file mode 100644 index 0000000..8687110 --- /dev/null +++ b/da.lproj/InsertLink.nib/classes.nib @@ -0,0 +1,17 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {genericCancel = id; genericOkay = id; }; + CLASS = LinkController; + LANGUAGE = ObjC; + OUTLETS = { + linkField = NSTextField; + objectController = NSObjectController; + urlField = NSTextField; + }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/da.lproj/InsertLink.nib/info.nib b/da.lproj/InsertLink.nib/info.nib new file mode 100644 index 0000000..5f3d3fc --- /dev/null +++ b/da.lproj/InsertLink.nib/info.nib @@ -0,0 +1,14 @@ + + + + + IBDocumentLocation + 91 173 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBSystem Version + 8R2210 + + diff --git a/da.lproj/InsertLink.nib/keyedobjects.nib b/da.lproj/InsertLink.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..80ff5dcc2ad2bf59719cac383d6ebb539dbf11ea GIT binary patch literal 7004 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 literal 0 HcmV?d00001 diff --git a/da.lproj/IntegrationFileCopy.nib/classes.nib b/da.lproj/IntegrationFileCopy.nib/classes.nib new file mode 100644 index 0000000..4360a16 --- /dev/null +++ b/da.lproj/IntegrationFileCopy.nib/classes.nib @@ -0,0 +1,12 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = IntegrationCopyFiles; + LANGUAGE = ObjC; + OUTLETS = {controller = NSObjectController; progress = NSProgressIndicator; }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/da.lproj/IntegrationFileCopy.nib/info.nib b/da.lproj/IntegrationFileCopy.nib/info.nib new file mode 100644 index 0000000..fbf23e7 --- /dev/null +++ b/da.lproj/IntegrationFileCopy.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 52 79 356 240 0 0 1280 1002 + IBFramework Version + 446.1 + IBSystem Version + 8P135 + + diff --git a/da.lproj/IntegrationFileCopy.nib/keyedobjects.nib b/da.lproj/IntegrationFileCopy.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..958a7b1f9977701de0f8af4801b64d772f1d03ee GIT binary patch literal 4315 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 qJl9-iR++VCo!MZvnr&vg88u_(CNpVf{4=c}_; + + + + IBClasses + + + ACTIONS + + cancel + id + chooseApplication + id + help + id + save + id + verifyDraggedImage + id + + CLASS + NewMediabarItemController + LANGUAGE + ObjC + OUTLETS + + appImageView + NSImageView + applicationField + MediabarItemApplicationPicker + appnameField + NSTextField + delegate + id + objectController + NSObjectController + representedObject + id + scriptText + NSTextView + titleField + NSTextField + + SUPERCLASS + NSWindowController + + + CLASS + NSView + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + RBSplitSubview + LANGUAGE + ObjC + SUPERCLASS + NSView + + + CLASS + RBSplitView + LANGUAGE + ObjC + OUTLETS + + delegate + id + + SUPERCLASS + RBSplitSubview + + + CLASS + PDMediabarItem + LANGUAGE + ObjC + SUPERCLASS + NSButton + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + ACTIONS + + didAdjustSubviews + RBSplitView + perfomCustomMediabarItemAction + PDMediabarItem + runClose + id + willAdjustSubviews + RBSplitView + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + MediabarItemApplicationPicker + LANGUAGE + ObjC + OUTLETS + + delegate + id + + SUPERCLASS + JournlerGradientView + + + CLASS + JournlerGradientView + LANGUAGE + ObjC + SUPERCLASS + NSView + + + IBVersion + 1 + + diff --git a/da.lproj/NewMediabarItem.nib/info.nib b/da.lproj/NewMediabarItem.nib/info.nib new file mode 100644 index 0000000..9f0cfac --- /dev/null +++ b/da.lproj/NewMediabarItem.nib/info.nib @@ -0,0 +1,16 @@ + + + + + IBFramework Version + 628 + IBOldestOS + 5 + IBOpenObjects + + IBSystem Version + 9A559 + targetFramework + IBCocoaFramework + + diff --git a/da.lproj/NewMediabarItem.nib/keyedobjects.nib b/da.lproj/NewMediabarItem.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..5f78f58411112f4042dfc204386f218002a9ae24 GIT binary patch literal 13080 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 z zt+Bl^+t|t2#n{a_+&I!W+BnuY-dJXI8>bt$8n+pD7@s%3V0_WI*Z7k0gz;nJ1>+ya zzl{GR-~>K_Bt#@w6M84)B@`qSCiF|VD`8N=kOY6i{DcJwixM78Seo!u!p?+U3A+>a zB4ND~(`TkjrY}raOjk{Rnf@_jGjCRym1dRMZti6+Fc+Hpnk&o`%~j?} z=4$g4v(G%=yxF|Pyw$wTyuO9xF>O6;=#oC6VD``PrRD=TaqG4 znWRe6CmEB{lkQ3ykW`#BIB957Nz$;Snxsuh&m=vY^jy;Rq@78-l6EKUNqQ~m?WE&L z-zNQ%9Gje&oRXZAJRo^oa#^xFxjfmEJTrMw@`K4slOIZcB>Cy&?a4cncO~ym-jn=p z@`dD2lRr!TJo$3+4^~JYti&2&jkLyDQ>~)4t+lmvw-(*ji?FTg$B; zYo*n1ool_%I^Vj$y2$#7b-i_?b+dJgb*pv1waI$W`nvV7^|bYj^_=x%>jmpI8)qZ7 z2wS8r$|l&-ZCz}+w!3W;Y!$YNwkq2sTea;z+alX4+eX`Sw!^m1Y@gdM+rF}WWBbl_ zCB>A|KBZ5}gp`Vui78bnlTxZvYEl-ZtW9|}d+f9A)PAr13Hvkl=j|`pKe1o5U$TE;|I+@o{agF@_8;um z>_6Fmw*TAyoBa>_U-o|-*ugs#4y8kI=p6=!-OnSmIdWSm`+8IO=%I@s8s?#|Mt%j+2hljx&yP zj*lG|9G^NqbA0Z&?D)#@jpIAV6~|S_Z;n5lqO+~Dy|aTe!|wsEyt(&ouFXWCq9b0t-gnwaWJ z%}(u=Iv{m;>b}(1QV*pbPJJ)+gVbZG=Tbj*^>Foc^>XF9@?CvgeO*Pa{;q+pL9QXL z64x--2-hgr7}q#gnak}ecX?cuF0X5{Yl_R~n(7L;>Ri)Z^{xijEY}=Y$Tin>pKHEr zfoqZLLDy2(L#{_$%Uvs6Yg~;Y7Kx}7qeP7;h_Pb4Xc7}et7sS7h%T|Mm@a0B*a-ML7Xjy#ChU;aiO?a zTp}(LSBg)HtHjmfT5+AYLEI!hBR(rWCvF#aio3+!;vR9I__DZPY!VNOuZxGpH^eu^ zx5anG_r+u43GtNpp?FsONIWloB3=|PiQkD=#2>_8#oxt0(nwlFnlepDi-VI(_{VYb NH~B{XZvISj{x2I9Y7qbc literal 0 HcmV?d00001 diff --git a/da.lproj/PDFavoritesBar.strings b/da.lproj/PDFavoritesBar.strings new file mode 100644 index 0000000..b604ca9 --- /dev/null +++ b/da.lproj/PDFavoritesBar.strings @@ -0,0 +1,5 @@ +"Favorites Name" = "Favoritters navn:"; +"Cancel" = "Afbryd"; +"OK" = "OK"; + +"draw labels" = "Træk label"; \ No newline at end of file diff --git a/da.lproj/PDFontPreview.strings b/da.lproj/PDFontPreview.strings new file mode 100644 index 0000000..697bdb3 --- /dev/null +++ b/da.lproj/PDFontPreview.strings @@ -0,0 +1 @@ +"set font title" = "Vælg skrift..."; \ No newline at end of file diff --git a/da.lproj/PDTabsView.strings b/da.lproj/PDTabsView.strings new file mode 100644 index 0000000..11ae9ba --- /dev/null +++ b/da.lproj/PDTabsView.strings @@ -0,0 +1,4 @@ +"new tab" = "Nyt faneblad"; +"close tab" = "Luk faneblad"; +"close other tabs" = "Luk andre faneblade"; +"close tab tip" = "Luk dette faneblad"; \ No newline at end of file diff --git a/da.lproj/SproutedAboutBox.nib/classes.nib b/da.lproj/SproutedAboutBox.nib/classes.nib new file mode 100644 index 0000000..41e769e --- /dev/null +++ b/da.lproj/SproutedAboutBox.nib/classes.nib @@ -0,0 +1,98 @@ + + + + + IBClasses + + + CLASS + PDGradientView + LANGUAGE + ObjC + SUPERCLASS + PDBorderedView + + + ACTIONS + + relaunch + id + + CLASS + NSApplication + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + PDBorderedView + LANGUAGE + ObjC + SUPERCLASS + NSView + + + CLASS + NSView + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + ACTIONS + + doSomething + id + showAboutBox + id + + CLASS + SproutedAboutBoxController + LANGUAGE + ObjC + OUTLETS + + aboutText + NSTextView + additionalText + NSTextView + appnameField + NSTextField + imageView + NSImageView + versionField + NSTextField + + SUPERCLASS + NSWindowController + + + CLASS + NSCell + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + IBVersion + 1 + + diff --git a/da.lproj/SproutedAboutBox.nib/info.nib b/da.lproj/SproutedAboutBox.nib/info.nib new file mode 100644 index 0000000..b5d3140 --- /dev/null +++ b/da.lproj/SproutedAboutBox.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + ../Journler.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + IBSystem Version + 9E17 + targetFramework + IBCocoaFramework + + diff --git a/da.lproj/SproutedAboutBox.nib/keyedobjects.nib b/da.lproj/SproutedAboutBox.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..1d4464fe3e2eb1b960e422fe98ce5e5c712841c4 GIT binary patch literal 7281 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

=KczpTzo`F*{(A!$+=iisWWz+m zR6~Jbk)g`4(hxMPF>EkwGVC`TGdykho#FR}=L|0xE*p9b?;HMR_|Wi?;S;0IINCVP zSZG{otTi?mWn+^uU~D$F7^B9xalLVy@owW@W4G~$@nPd};|b%7#y5#I$?Us z^n&RvQ;+Er(>G?V*=ZhWPBD)*k2POo_L*gK*u37n$-LdX!+eiVq zuxz*7XSv_Z^19`W<&x#HWe(NghTI&YuX6rWVz1F?fr>xIgFIqph8EwOC>9$PUB-<2QjxEX_n~=a}#CIhHvp9kL_pxXE#g<5tHO z$5zKvj+Y&096gRt9Y0{04iP2_Il>%au23v25K4rlLYYu5R0`EXjZiDJ2{#Hi3)_Ty zg~TJCCet#@s4-R0WvI_mnf>w@c|>yqoTtH8xcJ*PbvJ(oQ1c|P=f?D@p=mFF92h%`(}l150$(kN++ zlq!vrCP)*d3@J;RBu$ZWq+F>`Dv|`SL^>)Rmrh8JNKZ?@lb)4cmR^-!lTJ(Lu&u&B%0JZd N>m%y5_gDJh{{aHmizom9 literal 0 HcmV?d00001 diff --git a/da.lproj/Stats.nib/classes.nib b/da.lproj/Stats.nib/classes.nib new file mode 100644 index 0000000..776d57c --- /dev/null +++ b/da.lproj/Stats.nib/classes.nib @@ -0,0 +1,14 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + {CLASS = PDGradientView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, + { + ACTIONS = {genericStop = id; }; + CLASS = StatsController; + LANGUAGE = ObjC; + OUTLETS = {charsField = NSTextField; parsField = NSTextField; wordsField = NSTextField; }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/da.lproj/Stats.nib/info.nib b/da.lproj/Stats.nib/info.nib new file mode 100644 index 0000000..1fa14e0 --- /dev/null +++ b/da.lproj/Stats.nib/info.nib @@ -0,0 +1,14 @@ + + + + + IBDocumentLocation + 95 15 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBSystem Version + 8R2210 + + diff --git a/da.lproj/Stats.nib/keyedobjects.nib b/da.lproj/Stats.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..09b9f46f64f61319445f8b42cbd3d4535e356b1e GIT binary patch literal 5712 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 literal 0 HcmV?d00001 diff --git a/de.lproj/InsertLink.nib/classes.nib b/de.lproj/InsertLink.nib/classes.nib new file mode 100644 index 0000000..8687110 --- /dev/null +++ b/de.lproj/InsertLink.nib/classes.nib @@ -0,0 +1,17 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {genericCancel = id; genericOkay = id; }; + CLASS = LinkController; + LANGUAGE = ObjC; + OUTLETS = { + linkField = NSTextField; + objectController = NSObjectController; + urlField = NSTextField; + }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/de.lproj/InsertLink.nib/data.dependency b/de.lproj/InsertLink.nib/data.dependency new file mode 100644 index 0000000..6215193 --- /dev/null +++ b/de.lproj/InsertLink.nib/data.dependency @@ -0,0 +1,10 @@ + + + + + IBPaletteDependency + + Controllers + + + diff --git a/de.lproj/InsertLink.nib/info.nib b/de.lproj/InsertLink.nib/info.nib new file mode 100644 index 0000000..67faa4f --- /dev/null +++ b/de.lproj/InsertLink.nib/info.nib @@ -0,0 +1,14 @@ + + + + + IBDocumentLocation + 410 47 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBSystem Version + 8L127 + + diff --git a/de.lproj/InsertLink.nib/keyedobjects.nib b/de.lproj/InsertLink.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..ed7bef163fae2f5638e5c1184884fbd834a20db5 GIT binary patch literal 6988 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 literal 0 HcmV?d00001 diff --git a/de.lproj/IntegrationFileCopy.nib/classes.nib b/de.lproj/IntegrationFileCopy.nib/classes.nib new file mode 100644 index 0000000..4360a16 --- /dev/null +++ b/de.lproj/IntegrationFileCopy.nib/classes.nib @@ -0,0 +1,12 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = IntegrationCopyFiles; + LANGUAGE = ObjC; + OUTLETS = {controller = NSObjectController; progress = NSProgressIndicator; }; + SUPERCLASS = NSWindowController; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/de.lproj/IntegrationFileCopy.nib/data.dependency b/de.lproj/IntegrationFileCopy.nib/data.dependency new file mode 100644 index 0000000..6215193 --- /dev/null +++ b/de.lproj/IntegrationFileCopy.nib/data.dependency @@ -0,0 +1,10 @@ + + + + + IBPaletteDependency + + Controllers + + + diff --git a/de.lproj/IntegrationFileCopy.nib/info.nib b/de.lproj/IntegrationFileCopy.nib/info.nib new file mode 100644 index 0000000..9e8ae5d --- /dev/null +++ b/de.lproj/IntegrationFileCopy.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 414 78 356 240 0 0 1280 778 + IBFramework Version + 446.1 + IBSystem Version + 8L127 + + diff --git a/de.lproj/IntegrationFileCopy.nib/keyedobjects.nib b/de.lproj/IntegrationFileCopy.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..ad25262c045ecd986819468e3362321978263c29 GIT binary patch literal 4282 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 + + + + IBClasses + + + ACTIONS + + cancel + id + chooseApplication + id + help + id + save + id + verifyDraggedImage + id + + CLASS + NewMediabarItemController + LANGUAGE + ObjC + OUTLETS + + appImageView + NSImageView + applicationField + MediabarItemApplicationPicker + appnameField + NSTextField + delegate + id + objectController + NSObjectController + representedObject + id + scriptText + NSTextView + titleField + NSTextField + + SUPERCLASS + NSWindowController + + + CLASS + NSView + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + PDMediabarItem + LANGUAGE + ObjC + SUPERCLASS + NSButton + + + CLASS + RBSplitView + LANGUAGE + ObjC + OUTLETS + + delegate + id + + SUPERCLASS + RBSplitSubview + + + CLASS + RBSplitSubview + LANGUAGE + ObjC + SUPERCLASS + NSView + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + ACTIONS + + didAdjustSubviews + RBSplitView + perfomCustomMediabarItemAction + PDMediabarItem + runClose + id + willAdjustSubviews + RBSplitView + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + MediabarItemApplicationPicker + LANGUAGE + ObjC + OUTLETS + + delegate + id + + SUPERCLASS + JournlerGradientView + + + CLASS + JournlerGradientView + LANGUAGE + ObjC + SUPERCLASS + NSView + + + IBVersion + 1 + + diff --git a/de.lproj/NewMediabarItem.nib/info.nib b/de.lproj/NewMediabarItem.nib/info.nib new file mode 100644 index 0000000..c8787fc --- /dev/null +++ b/de.lproj/NewMediabarItem.nib/info.nib @@ -0,0 +1,18 @@ + + + + + IBFramework Version + 628 + IBLastKnownRelativeProjectPath + ../../Sprouted Interface.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + IBSystem Version + 9A559 + targetFramework + IBCocoaFramework + + diff --git a/de.lproj/NewMediabarItem.nib/keyedobjects.nib b/de.lproj/NewMediabarItem.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..0c397aca134b48372009a1dbfb36b5c8007e235d GIT binary patch literal 13843 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 literal 0 HcmV?d00001 diff --git a/de.lproj/PDFavoritesBar.strings b/de.lproj/PDFavoritesBar.strings new file mode 100644 index 0000000..8f81604 --- /dev/null +++ b/de.lproj/PDFavoritesBar.strings @@ -0,0 +1,5 @@ +"Favorites Name" = "Name des Lesezeichens:"; +"Cancel" = "Abbrechen"; +"OK" = "OK"; + +"draw labels" = "Etiketten zeichnen"; \ No newline at end of file diff --git a/de.lproj/PDFontPreview.strings b/de.lproj/PDFontPreview.strings new file mode 100644 index 0000000..6a759d0 --- /dev/null +++ b/de.lproj/PDFontPreview.strings @@ -0,0 +1 @@ +"set font title" = "Schrift festlegen…"; \ No newline at end of file diff --git a/de.lproj/PDTabsView.strings b/de.lproj/PDTabsView.strings new file mode 100644 index 0000000..19074fa --- /dev/null +++ b/de.lproj/PDTabsView.strings @@ -0,0 +1,4 @@ +"new tab" = "Neuer Tab"; +"close tab" = "Tab schließen"; +"close other tabs" = "Andere Tabs schließen"; +"close tab tip" = "Diesen Tab schließen"; \ No newline at end of file diff --git a/de.lproj/SproutedAboutBox.nib/classes.nib b/de.lproj/SproutedAboutBox.nib/classes.nib new file mode 100644 index 0000000..41e769e --- /dev/null +++ b/de.lproj/SproutedAboutBox.nib/classes.nib @@ -0,0 +1,98 @@ + + + + + IBClasses + + + CLASS + PDGradientView + LANGUAGE + ObjC + SUPERCLASS + PDBorderedView + + + ACTIONS + + relaunch + id + + CLASS + NSApplication + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + PDBorderedView + LANGUAGE + ObjC + SUPERCLASS + NSView + + + CLASS + NSView + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + ACTIONS + + doSomething + id + showAboutBox + id + + CLASS + SproutedAboutBoxController + LANGUAGE + ObjC + OUTLETS + + aboutText + NSTextView + additionalText + NSTextView + appnameField + NSTextField + imageView + NSImageView + versionField + NSTextField + + SUPERCLASS + NSWindowController + + + CLASS + NSCell + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + IBVersion + 1 + + diff --git a/de.lproj/SproutedAboutBox.nib/info.nib b/de.lproj/SproutedAboutBox.nib/info.nib new file mode 100644 index 0000000..86ce116 --- /dev/null +++ b/de.lproj/SproutedAboutBox.nib/info.nib @@ -0,0 +1,20 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + ../Journler.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 25 + + IBSystem Version + 9E17 + targetFramework + IBCocoaFramework + + diff --git a/de.lproj/SproutedAboutBox.nib/keyedobjects.nib b/de.lproj/SproutedAboutBox.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..d9e9dd1ac6f7de3c27f191a3d19735d00840b7fd GIT binary patch literal 7373 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 + + + + IBDocumentLocation + 136 22 356 240 0 0 1680 1028 + IBFramework Version + 446.1 + IBOldestOS + 3 + IBOpenObjects + + 5 + + IBSystem Version + 8R4031 + + diff --git a/de.lproj/Stats.nib/keyedobjects.nib b/de.lproj/Stats.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..bede670c3f87934a84f5cc5ecc8135056e6efb52 GIT binary patch literal 5754 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 N=snlCcl;`6{vUuew}b!y literal 0 HcmV?d00001 diff --git a/flat_bottom_left.png b/flat_bottom_left.png new file mode 100644 index 0000000000000000000000000000000000000000..17ef53984269bbf0249bf4c6d83c9a694e4c66e6 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA+!3HD^j~Yk=Db50q$YKTtZXpn6ymYtj4^WUL z-O<;Pf#JsMuQDR5fP95yk04(LhU_E;h7vOdhR>@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK(%{3T^vIyZoQdykn^yC0L%AtOraCptv+bWF6j$-Ar<7%b<+7kd#60xT(kZq zjV$v8wuyfc=`PFTKWV_zV|XaIk;UW3EQTY`e|QEuKAi8p|CqE#)1CYn8@C-hj}=BH0 UeBJ2Q1oQ`kr>mdKI;Vst001m{eE@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK()c1E{-7;x86*3fw+n?99yKRVuNet~}|^6P(XEoA@$R z&GEkEvQ=-gn%x8oPL$(<{9 literal 0 HcmV?d00001 diff --git a/flat_bottom_right.png b/flat_bottom_right.png new file mode 100644 index 0000000000000000000000000000000000000000..cf96147d3a18caec17c119ceab43799d0c8ec2e5 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA+!3HD^j~Yk=Db50q$YKTtZXpn6ymYtj4^WUL z-O<;Pf#JsMuQDR5fP95yk04(LhU_E;h7vOdhR>@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK(%{4T^vIyZoQdyk@JXxfXng2|9*4)sApZ$dSI%6!GrLy8!;v8TO}e5i*6ry zQ2lsS;W z&vGXG+rd^CRN|ktZL5{uL^VH`|EW4rUt_~}OcdTyaOu9-ySpb1=I=Jty5sZb^X;j{ zZs#Jut30o4%80+}6y%kVmUG)In%Cv{N7jpd0*8)Q+uux$G%;9v#^$($x>D7DHU@Ro WGK=}Wf8&83VeoYIb6Mw<&;$Tt0(@rx literal 0 HcmV?d00001 diff --git a/flat_middle_left.png b/flat_middle_left.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3d3a5d6cf3469d9868a61105021ad6cec08a14 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-Y!3HG1DAjiXDVAa<&kznEsNqQI0P;BtJR*x3 z7`TN%nDNrxx<5cc`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ#L{N}Y>R6H7Al^Atidb5j`%E%lA`4a`paE}aTgAn57h7{W0#d5&@Vxq3M{IW`6% XSEipYxOZ&|zCrtr?dp zfJ#L{N}Y>R6H7Al^Atidb5j`%E%lA`4a`paE}aTgAmr)d7{W0#Ic8(h(f|7K`wSQu Yq%&Esez)xi2g)*dy85}Sb4q9e0DIaq+W-In literal 0 HcmV?d00001 diff --git a/flat_top_left.png b/flat_top_left.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa3b0bb76dc6075429042dd8ee71112cc4f4a8e GIT binary patch literal 344 zcmeAS@N?(olHy`uVBq!ia0vp^l0a<1!3HEbB!fQyDb50q$YKTtZXpn6ymYtj4^WUL z-O<;Pf#JsMuQDR5fP95yk04(LhU_E;h7vOdhR>@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK(*&QT^vIyZoQdi$k%MZ<618$^j4^|%ZpcM%F3Nig6t1ibYzx`>qQIRkiE55 zSm<2B&7f!N_oQ1}_B^gwwQ3drL%Sqa&l7z21-E*msV5EP`5I9;bLXv@f=J z`xsZzaR-rc1v;d2tVuX)Q{w0BQ^(53j#n88Y?FyNrA?h>HS7(8A5T-G@yGywp)2Y9sr literal 0 HcmV?d00001 diff --git a/flat_top_middle.png b/flat_top_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..d56e450b408ddfe385a04961366c6759a7f35249 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^l0a<1!3HEbB!fQyDb50q$YKTtZXpn6ymYtj4^WUL z-O<;Pf#JsMuQDR5fP95yk04(LhU_E;h7vOdhR>@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK()!9E{-7;x8BS+$jhL>!Mr;0|HTy1xeVza8WpQz8w!?AxNyf^Bhu`7P?ezO zUcu7X3)ZeWOfmL-2FH?Zj)@z}`Tw)s@93BHP^m}9;~LkF1FnxG6AKz&`$<&t%Vjb% eF#P||%y4tF!G^}YS(QNR7(8A5T-G@yGywo0#Yz7F literal 0 HcmV?d00001 diff --git a/flat_top_right.png b/flat_top_right.png new file mode 100644 index 0000000000000000000000000000000000000000..08132275070036596e6c5b92ded2fc88283ac968 GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^l0a<1!3HEbB!fQyDb50q$YKTtZXpn6ymYtj4^WUL z-O<;Pf#JsMuQDR5fP95yk04(LhU_E;h7vOdhR>@R7<%S0Fyt?0V0d+gfx$qIfk9$c z!CkhGK((hlT^vIyZoQde$alzq$F<&R$tE-5NNW+p0+w}*=}%Z>8a9>bO2=x2-I{re zr)N!JOVEGrh`RT;m*qygJ@L8x<<0NoTVKC>o+zQ0ClepYE|Hw@R_n^wZ!h-VH$ThU zr~Lll8HK9m47bQ%v7w>r>&K1~b^>edzU<|kIu`_Zi+@F)K-CrttjZ0ha=vIc9N(;|T jo{RL)%zVJqaGv3nVQsr(<1Y@NuNXXC{an^LB{Ts5h8%u! literal 0 HcmV?d00001 diff --git a/hud_titlebar-close.tiff b/hud_titlebar-close.tiff new file mode 100644 index 0000000000000000000000000000000000000000..3fbbc1b996ce82adc1a22ab4e289a50e90f692b6 GIT binary patch literal 622 zcmebEWzb?^V4Tyypb%i8!comG*Qe;*m|_wk)xkFBqPcO9&Xp9mNFIyFeBAO3EGdpc zd#0=log(TGv_YgPhN0dk{?yJzYlF>0c0c#~p}43fW3uSeFIFmC1uK1mf(061G0kb1 z#?W_s3C9j61^&H0&zwG2Mf{)15UhDrpmX1Yf~Jce$-li){w-g?x7~Q9)*G)Tl}jfN zYWJRa%F@An@cPDCJMQ^LviPwJ_lU^yvE6%iIdI~3mguywQ!EPaP!nHbFmwDIP zw97f6n!+*({~o`QykF-iKhOMGx$T0F6$d;^E;YDrWX*MY-y6L=dSbPd&oQ>|vVZRH z&|dUv_kxy<2L3EP$uh6ynKGs*$sC=T6Q|@GA#l*3IpBh!bkAXvWqMj&%T^uiJG_O( zmHp*M(T2R{C9fE{qi$_qr}?UG!HSKi92T#1Im9t>NvBcJRMm->Shg=)xv608@-C$r ztqVJflsc6EB| WzAX|v2%!dO2GB+b^ne)10HXnRyt=ml literal 0 HcmV?d00001 diff --git a/iTunesBarSmall.png b/iTunesBarSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..733214fbb0e0d5631f15e16615786a1ee44fa1d6 GIT binary patch literal 1936 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 literal 0 HcmV?d00001 diff --git a/labelselected.tif b/labelselected.tif new file mode 100644 index 0000000000000000000000000000000000000000..fb37fac081cf4d8e767bdb8971fe647b478a39ca GIT binary patch literal 17088 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 literal 0 HcmV?d00001 diff --git a/more.tif b/more.tif new file mode 100644 index 0000000000000000000000000000000000000000..c16782ac9fefa6c6ec14fcfd4f497f5255aa5093 GIT binary patch literal 482 zcmebEWzb?^V3cWKP;hu5z{tqzb1>*b;1w}Wrse|+4K!l7q*;61k^^@L$l0*Vo$z$( zRO+x*k8W1=GSJyluPAro$)|7xOSO!fW!kf(~T3RZWZ1g+5XczEAEbt#^WMO$A75| zcMm=+c+4>GflB**#mO};m(r)qoO$MZ^*w(1$!A~id|Nz0fPsOJk%57k0T?_CfdxzHd;tT2#c$+E4yFJDV4FBp!S4$ z$(@p@zFv0zjRl@Y+9IqiX|9ejS0(J{Xs9#)yz;EvcAo#UMO#u%D1~%1t#po(xmUD* zh5d!CW=sCn2Rm)m;{N`ZE7yya*Tu}(Hmaz8i+Ogb*3zV{fm`HnZ_9kzF6`9i2erANwpi8zg> z-7gKIR1P$G>}5VEV8f+y!0-3Jh6V-(K1K!xW(HsYGVlNiMkt#X$YuhwS%9oJjLcAR zRv?cJ%4Pzx1sQwTfX*l~2qYP9p bNJaz6{2+ulP#@41DCGLnz`&p`zyPHIi!PSA literal 0 HcmV?d00001 diff --git a/tabclosebackdown.tif b/tabclosebackdown.tif new file mode 100644 index 0000000000000000000000000000000000000000..92a566685269cf311a25a343cf791e6722b5de2f GIT binary patch literal 518 zcmebEWzb?^V036;PzbP4U{GdOJaG1cNs5suN8`Z<8!aR{_{A++7JF@YQ<|eTLH`L; z>Yoy;ZM`g03kxidX^U_)r@0qAxtgUp$6z_r%q!2zZRhzvTX=NM390gqrc9SpGWUvl zR@k5ZYA*AyK3IRpD~{uTxpKW&CNqbbxJDI4Z?VcQ)moagHE@gAU9-%mJtiFj_d>V3 z2~7HPa>uPzW_x&lc%0l9=c08n%rv)V{`4Zh>e%%vvBgi+EiMM#$etf~U-yQ$AKUf3 zed)(m8E)J1x#m*LhBI^L&01V@t+(Iu;Em5U%jQ3tdE5Hg`BwY;{35pxq?<_Cz7YRu z!}&d|`Pu@5UA2ra>*w$^vHo!^;-9j_`-^gW+*XI(cXoZ}o*uXH(&7u=?v);@`Vw&( zO}iiFu!waUXiU;~6z~yb<}{FqdcXe#2Ll5iBLf37126~~cz^^Wl+6odGlAJGK-N1( zW~ewTkjDmPGXdFx3_y9HUIqpZMp39ZNQW3qoM{!KIE>9`&M3tIGy$ZZ@f)Kwoc)hc e2C5e%qk&|85JDWN4`>S%a{XywU{DuefYJa#nVV(+ literal 0 HcmV?d00001 diff --git a/tabclosebackroll.tif b/tabclosebackroll.tif new file mode 100644 index 0000000000000000000000000000000000000000..e237e014a3dca012901b4ba128860af77430e945 GIT binary patch literal 518 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 literal 0 HcmV?d00001 diff --git a/tabclosefrontroll.tif b/tabclosefrontroll.tif new file mode 100755 index 0000000000000000000000000000000000000000..8ea53954392f39977a4fd31f4e477a5693c2a132 GIT binary patch literal 17044 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 uW50XsjiyU4fBuGuFRv+>J literal 0 HcmV?d00001