/* * "p" - A very simple Project Manager using the GIMP Toolkit * Copyright (c) 1998, 1999, 2000 Elmar Ludwig * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef HAVE_UNISTD_H #include #include #else extern char *getcwd (); #endif #include #include #include #include #include "Manager.h" #define KEY(listitem) [[listitem child] stringValue] @implementation Manager - (id) init { GTKWindow *window = [GTKWindow windowWithType:GTK_WINDOW_TOPLEVEL]; GTKVBox *vbox = [GTKVBox vBoxWithHomogeneous:NO spacing:0]; GTKHBox *hbox1 = [GTKHBox hBoxWithHomogeneous:NO spacing:0]; GTKButton *launch = [GTKButton buttonWithLabel:@"Launch"]; GTKButton *debug = [GTKButton buttonWithLabel:@"Debug"]; GTKButton *attrib = [GTKButton buttonWithLabel:@"Attributes"]; GTKButton *build = [GTKButton buttonWithLabel:@"Build"]; GTKHSeparator *hsep = [GTKHSeparator hSeparator]; GTKVSeparator *vsep = [GTKVSeparator vSeparator]; GTKHBox *hbox2 = [GTKHBox hBoxWithHomogeneous:NO spacing:0]; GTKMenu *popup = [GTKMenu menu]; GTKItemFactory *item_factory = [GTKItemFactory itemFactoryWithContainerType:GTK_TYPE_MENU_BAR path:@"" accelGroup:nil]; GTKWidget *menubar; GTKScrolledWindow *scroll1 = [GTKScrolledWindow scrolledWindowWithHadjustment:nil vadjustment:nil]; GTKScrolledWindow *scroll2 = [GTKScrolledWindow scrolledWindowWithHadjustment:nil vadjustment:nil]; GTKAction *select = [GTKAction actionWithTarget:self selector:@selector(select:)]; GTKTooltips *tips = [GTKTooltips tooltips]; char buffer[1024]; int index; static GTKItemFactoryEntry menus[] = { // target = self {{ "/_Project", NULL, 0, 0, "" }}, {{ "/Project/_Info Panel...", "I" }, @selector(info:) }, {{ "/Project/_Preferences..." }}, {{ "/Project/sep1", NULL, 0, 0, "" }}, {{ "/_File", NULL, 0, 0, "" }}, {{ "/File/_Add...", "A" }, @selector(add:) }, {{ "/File/sep1", NULL, 0, 0, "" }}, {{ "/File/_Open", "O" }, @selector(open:) }, {{ "/File/_Remove", "R" }, @selector(remove:) }, // target = window {{ "/Project/_Quit", "Q" }, @selector(destroy) }, }; [super init]; #ifdef HAVE_GETCWD // this should be replaced with [filemanager currentDirectoryPath] if (getcwd(buffer, sizeof buffer)) path = [[NSString alloc] initWithCString:buffer]; else #endif path = [@"." retain]; program = [[path lastPathComponent] retain]; list1 = [GTKList list]; list2 = [GTKList list]; groups = [NSArray arrayWithObjects: [GTKListItem listItemWithLabel:@"Classes"], [GTKListItem listItemWithLabel:@"Headers"], [GTKListItem listItemWithLabel:@"Other Sources"], [GTKListItem listItemWithLabel:@"Images"], [GTKListItem listItemWithLabel:@"Other Resources"], [GTKListItem listItemWithLabel:@"Supporting Files"], [GTKListItem listItemWithLabel:@"Libraries"], nil]; [list1 appendItems:groups]; [item_factory createItems:&menus[0] count:9 forTarget:self]; [item_factory createItems:&menus[9] count:1 forTarget:window]; [[item_factory getWidget:@"/Project/Preferences..."] setSensitive:NO]; target = [GTKOptionMenu optionMenu]; [popup append:[GTKMenuItem menuItemWithLabel:@"(default)"]]; [popup append:[GTKMenuItem menuItemWithLabel:@"install"]]; [popup append:[GTKMenuItem menuItemWithLabel:@"clean"]]; [target setMenu:popup]; [scroll1 setPolicy:GTK_POLICY_AUTOMATIC vscrollbarPolicy:GTK_POLICY_ALWAYS]; [scroll2 setPolicy:GTK_POLICY_AUTOMATIC vscrollbarPolicy:GTK_POLICY_ALWAYS]; [scroll1 addWithViewport:list1]; [scroll2 addWithViewport:list2]; [launch connectSignal:@"clicked" withTarget:self sel:@selector(launch:)]; [debug connectSignal:@"clicked" withTarget:self sel:@selector(debug:)]; [attrib connectSignal:@"clicked" withTarget:self sel:@selector(attrib:)]; [build connectSignal:@"clicked" withTarget:self sel:@selector(build:)]; [tips setTip:launch tipText:@"Start the Program" tipPrivate:nil]; [tips setTip:debug tipText:@"Start the Debugger" tipPrivate:nil]; [tips setTip:attrib tipText:@"Modify Project Options" tipPrivate:nil]; [tips setTip:build tipText:@"Build the Project" tipPrivate:nil]; [tips setTip:target tipText:@"Select Build Target" tipPrivate:nil]; [hbox1 packStart:launch expand:NO fill:YES padding:4]; [hbox1 packStart:debug expand:NO fill:YES padding:4]; [hbox1 packStart:attrib expand:NO fill:YES padding:4]; [hbox1 packStart:build expand:NO fill:YES padding:4]; [hbox1 packStart:vsep expand:NO fill:YES padding:4]; [hbox1 packStart:target expand:NO fill:YES padding:4]; [hbox2 packStart:scroll1 expand:YES fill:YES padding:4]; [hbox2 packStart:scroll2 expand:YES fill:YES padding:4]; menubar = [item_factory getWidget:@""]; [vbox packStart:menubar expand:NO fill:YES padding:0]; [vbox packStart:hbox1 expand:NO fill:NO padding:8]; [vbox packStart:hsep expand:NO fill:YES padding:0]; [vbox packStart:hbox2 expand:YES fill:YES padding:8]; [window add:vbox]; [window addAccelGroup:[item_factory accelGroup]]; [window connectSignal:@"destroy" withTarget:GTKApp sel:@selector(terminate:)]; [window setUsize:320 height:220]; [window setTitle:[NSString stringWithFormat:@" %@ - %@ ", program, [path stringByAbbreviatingWithTildeInPath]]]; [window show]; files = [[NSMutableDictionary alloc] initWithCapacity:8]; for (index = [groups count]; index;) { GTKListItem *item = [groups objectAtIndex:--index]; [files setObject:[NSMutableArray array] forKey:KEY(item)]; [item connectSignal:@"select" withAction:select]; } [list2 connectSignal:@"selection_changed" withTarget:self sel:@selector(selectFile:)]; return self; } - (void) dealloc { [files release]; [program release]; [path release]; [filename release]; [super dealloc]; } - (void) info:(id) sender { GTKRunMessageBox(@"Info Panel", @"This is an example of a very simple\n" @"Project Manager using the GIMP Toolkit.", @"Continue", nil, nil); } - (void) select:(id) sender { [list2 removeItems:[list2 children]]; [list2 appendItems:[files objectForKey:KEY(sender)]]; if ([GTKApp getCurrentEvent]->type == GDK_2BUTTON_PRESS) [self addFile:sender]; } - (void) selectFile:(id) sender { if ([GTKApp getCurrentEvent]->type == GDK_2BUTTON_PRESS) [self open:sender]; } - (void) add:(id) sender { NSArray *sel = [list1 selection]; if ([sel count]) [self addFile:[sel objectAtIndex:0]]; else GTKRunMessageBox(@"Warning", @"You must select a group first", @"Continue", nil, nil); } - (void) addFile:(GTKListItem *) group { NSMutableArray *items = [files objectForKey:KEY(group)]; GTKFileSelection *filesel = [[GTKFileSelection alloc] initWithTitle:@"Add File..."]; [[filesel okButton] connectSignal:@"clicked" withTarget:self sel:@selector(ok:)]; [[filesel cancelButton] connectSignal:@"clicked" withTarget:self sel:@selector(cancel:)]; [filesel connectSignal:@"delete_event" withTarget:GTKApp sel:@selector(true)]; [filesel hideFileopButtons]; [filesel show]; if ([GTKApp runModalForWindow:filesel]) { NSString *name = [[filesel getFilename] lastPathComponent]; GTKListItem *item = [GTKListItem listItemWithLabel:name]; [items addObject:item]; [list2 add:item]; [self save:self]; } [filesel destroy]; [filesel release]; } - (void) ok:(id) sender { [GTKApp stopModalWithCode:YES]; } - (void) cancel:(id) sender { [GTKApp stopModalWithCode:NO]; } - (void) remove:(id) sender { NSArray *sel1 = [list1 selection]; NSArray *sel2 = [list2 selection]; NSMutableArray *items; GTKListItem *item; if ([sel1 count] == 0 || [sel2 count] == 0) return; items = [files objectForKey:KEY([sel1 objectAtIndex:0])]; item = [sel2 objectAtIndex:0]; [list2 remove:item]; [items removeObject:item]; [self save:self]; } - (void) open:(id) sender { NSArray *sel2 = [list2 selection]; NSString *command; if ([sel2 count] == 0) return; command = [NSString stringWithFormat:@"%@ '%@' &", EDIT_CMD, [[[sel2 objectAtIndex:0] child] stringValue]]; system([command cString]); } - (void) launch:(id) sender { NSString *command = [NSString stringWithFormat:@"%@ '%@' &", LAUNCH_CMD, program]; system([command cString]); } - (void) debug:(id) sender { NSString *command = [NSString stringWithFormat:@"%@ '%@' &", DEBUG_CMD, program]; system([command cString]); } - (void) attrib:(id) sender { NSString *command = [NSString stringWithFormat:@"%@ '%@' &", EDIT_CMD, @"Makefile"]; system([command cString]); } - (void) build:(id) sender { static GdkFont *font; GTKWindow *output = [GTKWindow windowWithType:GTK_WINDOW_TOPLEVEL]; GTKHBox *box = [GTKHBox hBoxWithHomogeneous:NO spacing:4]; GTKVScrollbar *bar = [GTKVScrollbar vScrollbarWithAdjustment:nil]; GTKText *text = [GTKText textWithHadj:nil vadj:[bar getAdjustment]]; NSString *command; FILE *pipe; char buffer[1024]; if (!font) font = gdk_font_load(OUTPUT_FONT); [text setEditable:NO]; [box packStart:text expand:YES fill:YES padding:0]; [box packStart:bar expand:NO fill:YES padding:0]; [output setTitle:@"Build Output Window"]; [output setBorderWidth:2]; [output add:box]; [output setUsize:480 height:240]; [output show]; [text grabFocus]; command = [[target child] stringValue]; if ([command isEqualToString:@"(default)"]) command = @""; command = [MAKE_CMD stringByAppendingFormat:@" %@", command]; if ((pipe = popen([command cString], "r"))) { while (fgets(buffer, sizeof buffer, pipe)) [text insert:font fore:NULL back:NULL chars:[NSString stringWithCString:buffer] length:-1]; pclose(pipe); } [text insert:font fore:NULL back:NULL chars:@"--- finished ---" length:-1]; } - (void) loadFromFile:(NSString *) _filename { const char *name; FILE *file; NSEnumerator *keys; GTKListItem *item; [filename autorelease]; filename = [_filename copy]; name = [_filename cString]; file = fopen(name, "r"); if (!file) { perror(name); return; } keys = [groups objectEnumerator]; while ((item = [keys nextObject])) { NSMutableArray *array = [files objectForKey:KEY(item)]; char buffer[4096]; char *ptr, *string; [array removeAllObjects]; if (!fgets(buffer, sizeof buffer, file) || !(ptr = strchr(buffer, '='))) break; ++ptr; while ((string = strtok(ptr, " \t\r\n"))) { ptr = NULL; item = [GTKListItem listItemWithLabel: [NSString stringWithCString:string]]; [array addObject:item]; } } if (ferror(file)) perror(name); fclose(file); } - (void) save:(id) sender { if (!filename) filename = [[program stringByAppendingString:@".project"] retain]; [self saveToFile:filename]; } - (void) saveToFile:(NSString *) _filename { const char *name = [_filename cString]; FILE *file = fopen(name, "w"); NSEnumerator *keys, *values; GTKListItem *item; NSMutableString *command = [[MAKEFILE_GEN mutableCopy] autorelease]; NSString *string; if (!file) { perror(name); return; } [command appendFormat:@" %@", program]; keys = [groups objectEnumerator]; while ((item = [keys nextObject])) { fprintf(file, "%s =", [KEY(item) cString]); values = [[files objectForKey:KEY(item)] objectEnumerator]; while ((item = [values nextObject])) { string = [[item child] stringValue]; [command appendFormat:@" %@", string]; fprintf(file, " %s", [string cString]); } fputc('\n', file); } fflush(file); if (ferror(file)) perror(name); fclose(file); system([command cString]); } @end