From 6f85c6383a87883585c68197f6b7bc8cf1bc918a Mon Sep 17 00:00:00 2001 From: Sergii Stoian Date: Thu, 5 Feb 2009 23:59:32 +0000 Subject: [PATCH] * Framework/PCProject.m: (dealloc): Replace DEVELOPMENT with DEBUG * Framework/PCProjectBrowser.m: (fileNameIconPath): Implement new method. * Framework/PCFileNameIcon.m: (mouseDown:) Finish drag&drop implementation. (init): Do not set image by default. (dealloc): Replace DEVELOPMENT with DEBUG. (setDelegate:): Use ASSIGN. (updateIcon): Cleanup. * Framework/English.lproj/ProjectInspector.gorm: Remove 'Hide on deactivate' attribute to panel. It allows drag&drop operations for external applications (e.g. Workspace). * Modules/Projects/Application/PCAppProject.*: Use PCFileNameIcon in inspector to use drag&drop functionality. Cleanup. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/projectcenter/trunk@27798 72102866-910b-0410-8b05-ffd578937521 --- .../BuilderOptions.gorm/data.info | Bin 184 -> 184 bytes .../BuilderOptions.gorm/objects.gorm | Bin 4909 -> 4909 bytes .../ProjectInspector.gorm/data.info | Bin 210 -> 184 bytes .../ProjectInspector.gorm/objects.gorm | Bin 3387 -> 3184 bytes Framework/PCFileNameIcon.m | 53 ++- Framework/PCProject.m | 2 +- Framework/PCProjectBrowser.m | 9 + Headers/ProjectCenter/PCFileNameIcon.h | 8 +- .../Application/PCAppProject+Inspector.h | 28 +- .../Application/PCAppProject+Inspector.m | 448 ++++++++---------- Modules/Projects/Application/PCAppProject.h | 6 +- Modules/Projects/Application/PCAppProject.m | 4 +- .../Resources/Inspector.gorm/data.classes | 10 +- .../Resources/Inspector.gorm/data.info | Bin 184 -> 184 bytes .../Resources/Inspector.gorm/objects.gorm | Bin 29739 -> 29094 bytes 15 files changed, 282 insertions(+), 286 deletions(-) diff --git a/Framework/English.lproj/BuilderOptions.gorm/data.info b/Framework/English.lproj/BuilderOptions.gorm/data.info index e233f826678d75319f952731e1f6602aa013f991..3bc8f05d4a6be2a0a9d14ad67d0720f682795b0a 100644 GIT binary patch delta 19 acmdnNxPx(m2y;r3$wYBKCMNcY>45+_sRdpD delta 19 acmdnNxPx(m2y=33@45+{dj*LA diff --git a/Framework/English.lproj/BuilderOptions.gorm/objects.gorm b/Framework/English.lproj/BuilderOptions.gorm/objects.gorm index be94118199210e6d16f76823e932dee541263ac6..7cf4fa40363c611e34a242870ecb4bfb8d386f3d 100644 GIT binary patch delta 199 zcmZ3hwpML|2y;r3$wu)iCPwDTlbD*AcvvP2aBFRLU=Cx1u@AB6!`ZTIEQ~;vO6;0I z(uX~ik!A8Cb{ioU1_RxV9BK?eut7tOL4bi_@(1=PW+1)Umm{4Ks0wK4-W delta 199 zcmZ3hwpML|2y=33@<#D0CPt>olbD*A3>YR0aBFRLU=Cx1u@AB6!`ZTIEQ~;vO6;0I z(uX}1NG@Wx5n^UA(A~(P#sCBxG(eQV`R!1Llp)AQe1t6+BEKl?ACO3P2-L6LSI9+Y|i& delta 124 zcmdnNc!_a>2yiboxlmIlI#0AL!3r@vyr(d-gkjd(PQf{aMGiyfw4kcy9k_0sd`T zTa6MeaLJ>^{mp0rPy&r>Y^r9|?c<8;_@?bxZN`|+b(XFhhsWPr4IjT51Dz+>WX(9} z`sQ)dGAu#nNj6y@rj4<&x)Cw34Lqwsf~Q!%W_)WqC+^wTR?BOezC}BHoTOKpW~XDE znVu)4qqHPXlLCg{ww+UA6hPy*aXD7RVO*~pN2X&nd4`QgOMy2*$D|zm)_Im?>&8>7 z0M{6SuwZ^Z`{bOlY&p-^e75p4E-QbY3o!}7fy9e*maY1)7>w~rmZ}@y*wz`I z{Rap{CJAEbL)IDoG+iT)%mx9Zc#cge=at)S^93E_Q)E#5DeczCWDUmoG`V)y{fRy= z?Vw`=(*8h`u22HWkrKj8hDxM+IT0Z#Ak&*v&iU`4!ZHG#kf1t&>X7AmmctOa-ZO8v z>-(;QWR1^Ip!&XNS*C8#9c;TzVz@MK_g9L|?;=bSxGcXMF)t?f`Vxe1R@U%)wx)mnNsO0H*mO zZSA31Bu40w41|_46!EC_)5KvKbQ%)sQ$|gFCIiUx8-#y=iX*4SU?vg`v(oY;#UKd< zzQiUZ9~nqA26K`(uaYXS?{@9x$y(XRv^(zlRtJg^-Uh=oA<2J<3!-Z<&zI?EYUrZH-V)r9=VsNpS^cQ(Qtj!}B`l68 zfgq!RO9;3u0SgMSpa82@r_r`Oir>FQTtUQ}5^-7~PV0Mi)9TX?Zb=q&(~z&OQd8Fg z7098u%1`N~ivU(5*Z|hzm3}EBB~XIkvgBOC(wzzmVLlL8G-yME&S1SKY!U_W6|!V$ zz_RrVCEaf$nHH0yOq04|roAyxNZ!1rki@5ls#8pkKvf}mD@tFu-CKYSX?_3YvYn2H zm&9#TVGhFSt1>IjFfo&FL{do+m#!LIB{5=yl;IHdRafO)25+O9??^SXL>8?oi#g!< zmgE0Vlzf-3P~ukHrc13p!Qefq@{Ce>2D@wBY*{CQ$?(jE1@B9ylwwNh#tVFIwBQ4| zQ&c-e{Y*6aU9<7SY1{2O5(hpUg^-;Z?u=>>7l8dZ#^Ig5W;&nUTiIb^AhFa~0~0zv8NzYcmK#YWI7u5kT!#m8C#`nUN~N#>CAr&wKWc8fHPA`JEIgEKSJ}nG zMR+v2t#l3(@OX4P_R40s1fNK!=cu3M;0a%)hAm&Mjwk_0XDoaKI}+y#_XSYyt%h4z ztafoO;atIa8|NxtV{-!Tu$dxPFjL;9D(9XOC6i%S2+KK)5t)jp{_ jH=R?f1a)-F19ZzF&JS@u!uc`IU*UWY=cm1!qB_0?Q9L8z literal 3387 zcmcf^Yf~Fl^z3E{kPrxuP})MF*476tJ(pUw_@IyoqOzbX?MG(`D@{#ycan{1zx5|% z`oZyI$6v7d15W(`jz3Ayxp#NT3(Jf%CX@R(_nyZ+@9dgKjll6&?0Wf0Xa(wpyIi9{W%{B113zX7Y4WJAcH9}!j!C_UU5$eqDlDZO;Q2JAous)V!xTZ9}C^9mdjDJImwF@+%?k!NxLW?ay zDR;EQadk1Dkj@*h3l_bnN%9Buq8hEMVAHNa^4j2IrjuflfLVo{N{~|qY!k{eoDich zVp`kYGrFgVF-V)%ql(j#yK%^x)^|?B_uLa@Mo{w1&u5vg9OkpdUuaqU6W|=MPO8y0 zUA__MDLIjW$;9$o^}4N$o`q4K zo`2+TH-o@)nU~11dv)z6VcfLXm+M}YFPy1h`!{~~AN1~QF+WE3T^SvF_91DuVVt&MYHj*oWe zS;QtK2q{Qo#A}M8ZW7r8*Bpu7dmOYJjAoN z$*VbRPR_ak18^o80I z33W}O^d*n(#4$9U!z%+4^#}4YQD0HiXIUVbnr1mQ^-?c!exMY^`NF3FuTZ?YZ>Arn zDR-z~dD+J6k)GQ4R=iSiD3z9$b_*B6g2G@lt#6>LcB3QHE3_%TU(*#ikk9|h?*IFM z&&OctH(g=>wz7N_(l^fu=@`2&m&D+RXc9=bqCmoTIco!x`qro*|;ksO6|)5-y^BsS5jpeBBjb2WL7e!ECD?JpAxMq zX^cb~BPs#3A$wn@AirxpuDB;&>wBl>SM9)In~DYQREkx*(Xd*! z@5>TL)pA{t?d>TJZP%%a%bZ)}QWChrwL%f5y?$02XxCdE|9T+({tHjP~U?etMfu~UNE2~W9)=%*CIRGHg0r@D7}yTr9UkW*f-pWI}p}Zc4zS+$bm(aZ3nj=^iw0?C!KjJ37>Yc zO0==%`_)R>=0Ps8lv=y3|x9a-tw8!e2xoR4nG%*T(MRA>r%5T)ejIN zZYq|&ZY5jQHa_euhFLP>7R_rkZ_~U=b5Sh8oFsS94605*eMmRaO(I)TWG54oOb$zW zhh!L+(q0w6=q!bsVHS53-kZ}B?n;a`{PKdFIH;S{e(p)URs2ffT`Vo**Wwx!VhwWB z)%WJLa1*~#6c>^=FARTkBngzr$=DH}NG+U_9yV~FRD7FMY|?y(<^!7V(tJqs2+iM$ hWtiBF|DRZn{M#Z{xXX(Ev&69L+(Abh8Rc3i{sH6ZAOHXW diff --git a/Framework/PCFileNameIcon.m b/Framework/PCFileNameIcon.m index 99baa75..98e2387 100644 --- a/Framework/PCFileNameIcon.m +++ b/Framework/PCFileNameIcon.m @@ -33,8 +33,9 @@ - (void)awakeFromNib { filePath = nil; + [self setRefusesFirstResponder:YES]; // [self setEditable:NO]; // prevents dragging - [self setImage:[NSImage imageNamed:@"ProjectCenter"]]; +// [self setImage:[NSImage imageNamed:@"ProjectCenter"]]; [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; } @@ -46,14 +47,14 @@ filePath = nil; [self setRefusesFirstResponder:YES]; // [self setEditable:NO]; // prevents dragging - [self setImage:[NSImage imageNamed:@"ProjectCenter"]]; +// [self setImage:[NSImage imageNamed:@"ProjectCenter"]]; return self; } - (void)dealloc { -#ifdef DEVELOPMENT +#ifdef DEBUG NSLog (@"PCFileNameIcon: dealloc"); #endif @@ -61,6 +62,7 @@ RELEASE(fileNameField); RELEASE(delegate); + RELEASE(filePath); [super dealloc]; } @@ -72,7 +74,7 @@ - (void)setDelegate:(id)object { - delegate = object; + ASSIGN(delegate, object); } - (void)updateIcon @@ -83,23 +85,45 @@ { [self setImage:[delegate fileNameIconImage]]; } - if ([delegate respondsToSelector:@selector(fileNameIconTitle)]) + if ((fileNameField != nil) && + [delegate respondsToSelector:@selector(fileNameIconTitle)]) { [fileNameField setStringValue:[delegate fileNameIconTitle]]; } - if ([delegate respondsToSelector:@selector(isFileNameIconDraggable)]) + if ([delegate respondsToSelector:@selector(fileNameIconPath)]) { - [self setEditable:[delegate isFileNameIconDraggable]]; + ASSIGN(filePath, [delegate fileNameIconPath]); } -/* if ([delegate respondsToSelector:@selector(fileNameIconTitle)]) - { - [fileNameField setStringValue:[delegate fileNameIconTitle]]; - }*/ } } // --- Drag and drop +- (void)mouseDown:(NSEvent *)theEvent +{ + NSArray *fileList = [NSArray arrayWithObjects:filePath, nil]; + NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSPoint dragPosition; + + [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] + owner:nil]; + [pboard setPropertyList:fileList forType:NSFilenamesPboardType]; + + // Start the drag operation + dragPosition = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + dragPosition.x -= 16; + dragPosition.y -= 16; + + [self dragImage:[self image] + at:dragPosition + offset:NSZeroSize + event:theEvent + pasteboard:pboard + source:self + slideBack:YES]; +} + // --- NSDraggingDestination protocol methods // -- Before the image is released - (unsigned int)draggingEntered:(id )sender @@ -108,7 +132,7 @@ NSArray *paths = [pb propertyListForType:NSFilenamesPboardType]; unsigned int draggingOp = NSDragOperationNone; - NSLog(@"Dragging entered"); +// NSLog(@"Dragging entered: %@", paths); if (![paths isKindOfClass:[NSArray class]] || [paths count] == 0) { @@ -181,9 +205,10 @@ } // --- NSDraggingSource protocol methods -- (void)draggedImage:(NSImage *)anImage beganAt:(NSPoint)aPoint + +- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)isLocal { - NSLog(@"Icon dragging started"); + return NSDragOperationCopy; } @end diff --git a/Framework/PCProject.m b/Framework/PCProject.m index 31341bf..cc6f4db 100644 --- a/Framework/PCProject.m +++ b/Framework/PCProject.m @@ -89,7 +89,7 @@ NSString - (void)dealloc { -#ifdef DEVELOPMENT +#ifdef DEBUG NSLog (@"PCProject %@: dealloc", projectName); #endif diff --git a/Framework/PCProjectBrowser.m b/Framework/PCProjectBrowser.m index f0423ae..3fc4aa2 100644 --- a/Framework/PCProjectBrowser.m +++ b/Framework/PCProjectBrowser.m @@ -675,6 +675,15 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; return PCFileNameFieldNoFiles; } +- (NSString *)fileNameIconPath +{ + NSString *fileName = [self nameOfSelectedFile]; + NSString *category = [self nameOfSelectedCategory]; + + return [project pathForFile:fileName + forKey:[project keyForCategory:category]]; +} + - (BOOL)canPerformDraggingOf:(NSArray *)paths { NSString *category = [self nameOfSelectedCategory]; diff --git a/Headers/ProjectCenter/PCFileNameIcon.h b/Headers/ProjectCenter/PCFileNameIcon.h index 9bd6faa..09e5f2b 100644 --- a/Headers/ProjectCenter/PCFileNameIcon.h +++ b/Headers/ProjectCenter/PCFileNameIcon.h @@ -29,10 +29,9 @@ @interface PCFileNameIcon : NSImageView { - NSString *filePath; - NSTextField *fileNameField; - - id delegate; + NSString *filePath; + NSTextField *fileNameField; + id delegate; } - (void)setFileNameField:(NSTextField *)field; @@ -46,6 +45,7 @@ // --- NSDraggingDestination protocol methods - (NSImage *)fileNameIconImage; - (NSString *)fileNameIconTitle; +- (NSString *)fileNameIconPath; - (BOOL)canPerformDraggingOf:(NSArray *)paths; - (BOOL)prepareForDraggingOf:(NSArray *)paths; - (BOOL)performDraggingOf:(NSArray *)paths; diff --git a/Modules/Projects/Application/PCAppProject+Inspector.h b/Modules/Projects/Application/PCAppProject+Inspector.h index 072ff07..889ecf4 100644 --- a/Modules/Projects/Application/PCAppProject+Inspector.h +++ b/Modules/Projects/Application/PCAppProject+Inspector.h @@ -32,30 +32,28 @@ // ---------------------------------------------------------------------------- // --- User Interface // ---------------------------------------------------------------------------- -- (void)createProjectAttributes; - (NSView *)projectAttributesView; // ---------------------------------------------------------------------------- // --- Actions // ---------------------------------------------------------------------------- +- (void)setAppType:(id)sender; - (void)setAppClass:(id)sender; -- (void)setFile:(id)sender; -- (void)clearFile:(id)sender; -- (void)setAppIcon:(id)sender; + - (void)clearAppIcon:(id)sender; -- (void)setHelpFile:(id)sender; +- (BOOL)setAppIconWithFileAtPath:(NSString *)path; + - (void)clearHelpFile:(id)sender; -- (BOOL)setAppIconWithImageAtPath:(NSString *)path; -- (void)setMainNib:(id)sender; -- (BOOL)setMainNibWithFileAtPath:(NSString *)path; + - (void)clearMainNib:(id)sender; +- (BOOL)setMainNibWithFileAtPath:(NSString *)path; - (void)setDocBasedApp:(id)sender; - (int)numberOfRowsInTableView:(NSTableView *)aTableView; -- (id) tableView: (NSTableView *)aTableView - objectValueForTableColumn: (NSTableColumn *)aTableColumn - row: (int)rowIndex; +- (id) tableView:(NSTableView *)aTableView + objectValueForTableColumn:(NSTableColumn *)aTableColumn + row:(int)rowIndex; - (void) tableView:(NSTableView *)aTableView setObjectValue:anObject forTableColumn:(NSTableColumn *)aTableColumn @@ -71,4 +69,12 @@ @end +@interface PCAppProject (FileNameIconDelegate) + +- (BOOL)canPerformDraggingOf:(NSArray *)paths; +- (BOOL)prepareForDraggingOf:(NSArray *)paths; +- (BOOL)performDraggingOf:(NSArray *)paths; + +@end + #endif diff --git a/Modules/Projects/Application/PCAppProject+Inspector.m b/Modules/Projects/Application/PCAppProject+Inspector.m index f6310b3..98803e9 100644 --- a/Modules/Projects/Application/PCAppProject+Inspector.m +++ b/Modules/Projects/Application/PCAppProject+Inspector.m @@ -22,6 +22,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#import #import #import "PCAppProject+Inspector.h" @@ -81,39 +82,39 @@ cleanup(NSMutableDictionary *m, NSString *k) - (void)awakeFromNib { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(tfGetFocus:) + name:PCITextFieldGetFocus + object:nil]; + + // Icon view + [iconView setImage:nil]; + [iconView setDelegate:self]; + + // Help text view + [helpText setDrawsBackground:NO]; + [helpText setTextColor:[NSColor darkGrayColor]]; + [helpText setFont:[NSFont systemFontOfSize:11.0]]; + [helpText setText:@"Click on the field and drop file in the box above"]; + + // Document types buttons + [addDocTypeButton setRefusesFirstResponder:YES]; + [removeDocTypeButton setRefusesFirstResponder:YES]; [docBasedAppButton setRefusesFirstResponder:YES]; + [self setDocBasedApp:docBasedAppButton]; + [docBasedAppButton setState: - ([[projectDict objectForKey: PCDocumentBasedApp] - isEqualToString: @"YES"]) ? NSOnState : NSOffState]; + ([[projectDict objectForKey:PCDocumentBasedApp] + isEqualToString:@"YES"]) ? NSOnState : NSOffState]; + + [self updateInspectorValues:nil]; } // ---------------------------------------------------------------------------- // --- User Interface // ---------------------------------------------------------------------------- -- (void)createProjectAttributes -{ - // TFs Buttons - [setFieldButton setRefusesFirstResponder: YES]; - [clearFieldButton setRefusesFirstResponder: YES]; - - // Document types buttons - [addDocTypeButton setRefusesFirstResponder: YES]; - [removeDocTypeButton setRefusesFirstResponder: YES]; - [docBasedAppButton setRefusesFirstResponder: YES]; - - [self setDocBasedApp: docBasedAppButton]; - - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector(tfGetFocus:) - name: PCITextFieldGetFocus - object: nil]; - [projectAttributesView retain]; - - [self updateInspectorValues: nil]; -} - - (NSView *)projectAttributesView { if (!projectAttributesView) @@ -123,7 +124,7 @@ cleanup(NSMutableDictionary *m, NSString *k) NSLog(@"PCAppProject: error loading Inspector NIB!"); return nil; } - [self createProjectAttributes]; + [projectAttributesView retain]; } return projectAttributesView; @@ -133,250 +134,121 @@ cleanup(NSMutableDictionary *m, NSString *k) // --- Actions // ---------------------------------------------------------------------------- -- (void)setAppType: (id)sender +- (void)setAppType:(id)sender { NSString *appType = [appTypeField stringValue]; - NSMutableArray *libs = [[projectDict objectForKey: PCLibraries] mutableCopy]; + NSMutableArray *libs = [[projectDict objectForKey:PCLibraries] mutableCopy]; - if ([appType isEqualToString: @"Renaissance"]) + if ([appType isEqualToString:@"Renaissance"]) { - [libs addObject: @"Renaissance"]; + [libs addObject:@"Renaissance"]; } else { - [libs removeObject: @"Renaissance"]; + [libs removeObject:@"Renaissance"]; } - [self setProjectDictObject: libs forKey: PCLibraries notify: YES]; + [self setProjectDictObject:libs forKey:PCLibraries notify:YES]; RELEASE(libs); - [self setProjectDictObject: appType forKey: PCAppType notify: YES]; + [self setProjectDictObject:appType forKey:PCAppType notify:YES]; } -- (void)setAppClass: (id)sender +- (void)setAppClass:(id)sender { - [self setProjectDictObject: [appClassField stringValue] - forKey: PCPrincipalClass - notify: YES]; -} - -- (void)setIconViewImage: (NSImage *)image -{ - [iconView setImage: nil]; - [iconView display]; - - if (image == nil) - { - return; - } - - [iconView setImage: image]; - [iconView display]; -} - -- (void)setFile: (id)sender -{ - if (!activeTextField) - { - return; - } - - if (activeTextField == appImageField) - { - [self setAppIcon: self]; - } - else if (activeTextField == helpFileField) - { - [self setHelpFile: self]; - } - else if (activeTextField == mainNIBField) - { - [self setMainNib: self]; - } -} - -- (void)clearFile: (id)sender -{ - if (!activeTextField) - { - return; - } - - if (activeTextField == appImageField) - { - [self clearAppIcon: self]; - } - else if (activeTextField == helpFileField) - { - [self clearHelpFile: self]; - } - else if (activeTextField == mainNIBField) - { - [self clearMainNib: self]; - } - [self setIconViewImage: nil]; + [self setProjectDictObject:[appClassField stringValue] + forKey:PCPrincipalClass + notify:YES]; } // Application Icon -- (void)setAppIcon: (id)sender +- (void)clearAppIcon:(id)sender { - int result; - NSArray *fileTypes = [NSImage imageFileTypes]; - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - NSString *dir = nil; - - [openPanel setAllowsMultipleSelection: NO]; - [openPanel setTitle: @"Set Application Icon"]; + [appImageField setStringValue:@""]; + [infoDict setObject:@"" forKey:@"NSIcon"]; + [infoDict setObject:@"" forKey:@"ApplicationIcon"]; - dir = [[NSUserDefaults standardUserDefaults] - objectForKey: @"LastOpenDirectory"]; - result = [openPanel runModalForDirectory: dir - file: nil - types: fileTypes]; + [self setProjectDictObject:@"" forKey:PCAppIcon notify:YES]; +} - if (result == NSOKButton) - { - NSString *imageFilePath = [[openPanel filenames] objectAtIndex: 0]; - - if (![self setAppIconWithImageAtPath: imageFilePath]) - { - NSRunAlertPanel(@"Error while opening file!", - @"Couldn't open %@", @"OK", nil, nil,imageFilePath); - } - } -} - -- (void)setHelpFile: (id)sender -{ - int result; - NSArray *fileTypes = [NSArray arrayWithObjects: - @"rtfd", @"rtf", @"txt", nil]; - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - NSString *dir = nil; - - [openPanel setAllowsMultipleSelection: NO]; - [openPanel setTitle: @"Set Help File"]; - - dir = [[NSUserDefaults standardUserDefaults] - objectForKey: @"LastOpenDirectory"]; - result = [openPanel runModalForDirectory: dir - file: nil - types: fileTypes]; - - if (result == NSOKButton) - { - NSString *path = [[openPanel filenames] objectAtIndex: 0]; - NSString *file = [path lastPathComponent]; - - [helpFileField setStringValue: file]; - - [self addAndCopyFiles: [NSArray arrayWithObject: path] - forKey: PCDocuFiles]; - - [infoDict setObject: file forKey: @"GSHelpContentsFile"]; - [self setProjectDictObject: file forKey: PCHelpFile notify: YES]; - } -} - -- (void)clearAppIcon: (id)sender -{ - [appImageField setStringValue: @""]; - [infoDict setObject: @"" forKey: @"NSIcon"]; - [infoDict setObject: @"" forKey: @"ApplicationIcon"]; - - [self setProjectDictObject: @"" forKey: PCAppIcon notify: YES]; -} - -- (void)clearHelpFile: (id)sender -{ - [infoDict removeObjectForKey: @"GSHelpContentsFile"]; - [self setProjectDictObject: @"" forKey: PCHelpFile notify: YES]; -} - -- (BOOL)setAppIconWithImageAtPath: (NSString *)path -{ - NSImage *image = nil; - NSString *imageName = nil; - - if (!(image = [[NSImage alloc] initWithContentsOfFile: path])) +- (BOOL)setAppIconWithFileAtPath:(NSString *)path +{ + NSImage *image = [[NSImage alloc] initWithContentsOfFile:path]; + NSString *imageName = nil; + NSFileManager *fm = [NSFileManager defaultManager]; + NSArray *fileTypes = [self fileTypesForCategoryKey:PCImages]; + + NSLog(@"setAppIconWithFileAtPath -- %@", path); + + // TODO: GNUstep bug - NSImage should return nil if image cannot + // be created, but it doesn't + if (!path || !image || ![fm fileExistsAtPath:path] + || ![fileTypes containsObject:[path pathExtension]]) { + [iconView setImage:nil]; + [self clearAppIcon:self]; return NO; } + // TODO: Image nil here even if 'path' exists. Why? It results in + // empty imageView on drag&drop operation. + [iconView setImage:image]; + imageName = [path lastPathComponent]; + [appImageField setStringValue:imageName]; - [appImageField setStringValue: imageName]; - - [self setIconViewImage: image]; - - [self addAndCopyFiles: [NSArray arrayWithObject: path] forKey: PCImages]; + [self addAndCopyFiles:[NSArray arrayWithObject:path] forKey:PCImages]; - [infoDict setObject: imageName forKey: @"NSIcon"]; - [infoDict setObject: imageName forKey: @"ApplicationIcon"]; + [infoDict setObject:imageName forKey:@"NSIcon"]; + [infoDict setObject:imageName forKey:@"ApplicationIcon"]; - [self setProjectDictObject: imageName forKey: PCAppIcon notify: YES]; + [self setProjectDictObject:imageName forKey:PCAppIcon notify:YES]; return YES; } -// Main Interface File -- (void)setMainNib: (id)sender +// Help file +- (void)clearHelpFile:(id)sender { - int result; - NSOpenPanel *openPanel = [NSOpenPanel openPanel]; - NSString *dir = nil; - NSArray *types = nil; + [infoDict removeObjectForKey:@"GSHelpContentsFile"]; + [self setProjectDictObject:@"" forKey:PCHelpFile notify:YES]; +} - [openPanel setAllowsMultipleSelection: NO]; - [openPanel setTitle: @"Set Main Interface File"]; - if ([[projectDict objectForKey: PCAppType] isEqualToString: @"GORM"]) - { - types = [NSArray arrayWithObject: @"gorm"]; - } - else - { - types = [NSArray arrayWithObject: @"gsmarkup"]; - } - - dir = [[NSUserDefaults standardUserDefaults] - objectForKey: @"LastOpenDirectory"]; - result = [openPanel runModalForDirectory: dir file: nil types: types]; +// Main Interface File +- (void)clearMainNib: (id)sender +{ + [mainNIBField setStringValue:@""]; + [infoDict setObject:@"" forKey:@"NSMainNibFile"]; - if (result == NSOKButton) - { - NSString *file = [[openPanel filenames] objectAtIndex: 0]; - - if (![self setMainNibWithFileAtPath: file]) - { - NSRunAlertPanel(@"Error while opening file!", - @"Couldn't open %@", @"OK", nil, nil,file); - } - } + [self setProjectDictObject:@"" forKey:PCMainInterfaceFile notify:YES]; } - (BOOL)setMainNibWithFileAtPath: (NSString *)path { - NSString *nibName = [path lastPathComponent]; + NSString *nibName = [path lastPathComponent]; + NSFileManager *fm = [NSFileManager defaultManager]; + NSArray *fileTypes = [self fileTypesForCategoryKey:PCInterfaces]; - [self setIconViewImage: [[NSWorkspace sharedWorkspace] iconForFile: path]]; + // TODO: check if it's interface file and it exists + if (![fm fileExistsAtPath:path] + || ![fileTypes containsObject:[path pathExtension]]) + { + [iconView setImage:nil]; + [self clearMainNib:self]; + return NO; + } - [self addAndCopyFiles: [NSArray arrayWithObject: path] forKey: PCInterfaces]; - [infoDict setObject: nibName forKey: @"NSMainNibFile"]; + [iconView setImage:[[NSWorkspace sharedWorkspace] iconForFile:path]]; - [self setProjectDictObject: nibName forKey: PCMainInterfaceFile notify: YES]; + [self addAndCopyFiles:[NSArray arrayWithObject: path] forKey:PCInterfaces]; + [infoDict setObject:nibName forKey:@"NSMainNibFile"]; - [mainNIBField setStringValue: nibName]; + [self setProjectDictObject:nibName forKey:PCMainInterfaceFile notify:YES]; + + [mainNIBField setStringValue:nibName]; return YES; } -- (void)clearMainNib: (id)sender -{ - [mainNIBField setStringValue: @""]; - [infoDict setObject: @"" forKey: @"NSMainNibFile"]; - - [self setProjectDictObject: @"" forKey: PCMainInterfaceFile notify: YES]; -} - // Document Types - (void)showDocTypesPanel: (id)sender { @@ -683,15 +555,15 @@ cleanup(NSMutableDictionary *m, NSString *k) // NSLog (@"PCAppProject: updateInspectorValues"); // Project Attributes view - [appTypeField selectItemWithTitle: [projectDict objectForKey: PCAppType]]; - [appClassField setStringValue: [projectDict objectForKey: PCPrincipalClass]]; + [appTypeField selectItemWithTitle:[projectDict objectForKey:PCAppType]]; + [appClassField setStringValue:[projectDict objectForKey: PCPrincipalClass]]; - [appImageField setStringValue: [projectDict objectForKey: PCAppIcon]]; - [helpFileField setStringValue: [projectDict objectForKey: PCHelpFile]]; + [appImageField setStringValue:[projectDict objectForKey:PCAppIcon]]; + [helpFileField setStringValue:[projectDict objectForKey:PCHelpFile]]; [mainNIBField setStringValue: - [projectDict objectForKey: PCMainInterfaceFile]]; + [projectDict objectForKey:PCMainInterfaceFile]]; - docTypesItems = [projectDict objectForKey: PCDocumentTypes]; + docTypesItems = [projectDict objectForKey:PCDocumentTypes]; [docTypesList reloadData]; } @@ -707,6 +579,7 @@ cleanup(NSMutableDictionary *m, NSString *k) id anObject = [aNotif object]; NSString *file = nil; NSString *path = nil; + NSImage *image = nil; if (anObject != appImageField @@ -723,10 +596,9 @@ cleanup(NSMutableDictionary *m, NSString *k) if (![file isEqualToString: @""]) { - path = [self dirForCategoryKey: PCImages]; - path = [path stringByAppendingPathComponent: file]; - [self setIconViewImage: [[NSImage alloc] - initWithContentsOfFile: path]]; + path = [self dirForCategoryKey:PCImages]; + path = [path stringByAppendingPathComponent:file]; + image = [[NSImage alloc] initWithContentsOfFile:path]; } activeTextField = appImageField; } @@ -738,42 +610,118 @@ cleanup(NSMutableDictionary *m, NSString *k) { file = [mainNIBField stringValue]; - if (![file isEqualToString: @""]) + if (![file isEqualToString:@""]) { - path = [projectPath stringByAppendingPathComponent: file]; - [self setIconViewImage: [[NSWorkspace sharedWorkspace] - iconForFile: path]]; + path = [projectPath stringByAppendingPathComponent:file]; + image = [[NSWorkspace sharedWorkspace] iconForFile:path]; } activeTextField = mainNIBField; } - [setFieldButton setEnabled: YES]; - [clearFieldButton setEnabled: YES]; + [iconView setImage:image]; } -- (void)controlTextDidEndEditing: (NSNotification *)aNotification +- (void)controlTextDidEndEditing:(NSNotification *)aNotification { NSControl *anObject = [aNotification object]; id target = [anObject target]; SEL action = [anObject action]; + NSString *fileName; + NSString *filePath; - if (anObject == appImageField - || anObject == helpFileField - || anObject == mainNIBField) + if (anObject != appImageField + && anObject != helpFileField + && anObject != mainNIBField) { - activeTextField = nil; - [self setIconViewImage: nil]; - - [setFieldButton setEnabled: NO]; - [clearFieldButton setEnabled: NO]; + if ([target respondsToSelector:action]) + { + [target performSelector:action withObject:anObject]; + } return; } - if ([target respondsToSelector: action]) + fileName = [anObject stringValue]; + if (anObject == appImageField) { - [target performSelector: action withObject: anObject]; + filePath = [self pathForFile:fileName forKey:PCImages]; + [self setAppIconWithFileAtPath:filePath]; + } + else if (anObject == helpFileField) + { + } + else if (anObject == mainNIBField) + { + filePath = [self pathForFile:fileName forKey:PCInterfaces]; + [self setMainNibWithFileAtPath:filePath]; } } @end + +@implementation PCAppProject (FileNameIconDelegate) + +- (BOOL)canPerformDraggingOf:(NSArray *)paths +{ + NSString *categoryKey; + NSArray *fileTypes; + NSEnumerator *e = [paths objectEnumerator]; + NSString *s; + + if (activeTextField == appImageField) + { + categoryKey = PCImages; + } + else if (activeTextField == helpFileField) + { + return NO; + } + else if (activeTextField == mainNIBField) + { + categoryKey = PCInterfaces; + } + else + { + return NO; + } + + NSLog(@"PCAppProject: canPerformDraggingOf -> %@", + [self projectFileFromFile:[paths objectAtIndex:0] forKey:categoryKey]); + + fileTypes = [self fileTypesForCategoryKey:categoryKey]; + + // Check if we can accept files of such types + while ((s = [e nextObject])) + { + if (![fileTypes containsObject:[s pathExtension]]) + { + return NO; + } + } + + return YES; +} + +- (BOOL)prepareForDraggingOf:(NSArray *)paths +{ + return YES; +} + +- (BOOL)performDraggingOf:(NSArray *)paths +{ + if (activeTextField == appImageField) + { + [self setAppIconWithFileAtPath:[paths objectAtIndex:0]]; + } + else if (activeTextField == helpFileField) + { + } + else if (activeTextField == mainNIBField) + { + [self setMainNibWithFileAtPath:[paths objectAtIndex:0]]; + } + + return YES; +} + +@end diff --git a/Modules/Projects/Application/PCAppProject.h b/Modules/Projects/Application/PCAppProject.h index 5a48dba..4b28eb7 100644 --- a/Modules/Projects/Application/PCAppProject.h +++ b/Modules/Projects/Application/PCAppProject.h @@ -34,6 +34,7 @@ #import #import #import +#import #import @@ -54,10 +55,9 @@ IBOutlet PCAppTextField *helpFileField; IBOutlet PCAppTextField *mainNIBField; - IBOutlet NSImageView *iconView; + IBOutlet NSTextView *helpText; + IBOutlet PCFileNameIcon *iconView; NSImage *icon; - IBOutlet NSButton *setFieldButton; - IBOutlet NSButton *clearFieldButton; IBOutlet NSButton *docTypesButton; diff --git a/Modules/Projects/Application/PCAppProject.m b/Modules/Projects/Application/PCAppProject.m index 90a800c..bdf8409 100644 --- a/Modules/Projects/Application/PCAppProject.m +++ b/Modules/Projects/Application/PCAppProject.m @@ -120,7 +120,7 @@ - (void)dealloc { -#ifdef DEVELOPMENT +#ifdef DEBUG NSLog (@"PCAppProject: dealloc"); #endif @@ -356,7 +356,7 @@ [self clearAppIcon:self]; if ([super renameFile:ff toFile:tf] == YES) { - [self setAppIconWithImageAtPath: + [self setAppIconWithFileAtPath: [[self dirForCategoryKey:categoryKey] stringByAppendingPathComponent:tf]]; success = YES; diff --git a/Modules/Projects/Application/Resources/Inspector.gorm/data.classes b/Modules/Projects/Application/Resources/Inspector.gorm/data.classes index 7bbd28a..03cc3fe 100644 --- a/Modules/Projects/Application/Resources/Inspector.gorm/data.classes +++ b/Modules/Projects/Application/Resources/Inspector.gorm/data.classes @@ -60,7 +60,8 @@ iconColumn, roleColumn, classColumn, - appTypeField + appTypeField, + helpText ); Super = NSObject; }; @@ -71,4 +72,11 @@ ); Super = NSTextField; }; + PCFileNameIcon = { + Actions = ( + ); + Outlets = ( + ); + Super = NSImageView; + }; } \ No newline at end of file diff --git a/Modules/Projects/Application/Resources/Inspector.gorm/data.info b/Modules/Projects/Application/Resources/Inspector.gorm/data.info index 3bc8f05d4a6be2a0a9d14ad67d0720f682795b0a..da98e4327f70ff8ec64d5cb98405097d84145e8a 100644 GIT binary patch delta 18 ZcmdnNxPx(m2y?1=@1zZ3C diff --git a/Modules/Projects/Application/Resources/Inspector.gorm/objects.gorm b/Modules/Projects/Application/Resources/Inspector.gorm/objects.gorm index 525e8d4b0016db82482f2b382691db4e693db5d2..706d40fd5366dcc6dfd13407271d1a7def5e13da 100644 GIT binary patch delta 6714 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 delta 7107 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 ok*cSN>5w~is@$ea