Commits

Ivan Vučica committed aa216bc

Initial commit of HelloGNUstepOutlineView.

  • Participants

Comments (0)

Files changed (11)

+ifeq ($(GNUSTEP_MAKEFILES),)
+ GNUSTEP_MAKEFILES := $(shell gnustep-config --variable=GNUSTEP_MAKEFILES 2>/dev/null)
+endif
+ifeq ($(GNUSTEP_MAKEFILES),)
+ $(error You need to set GNUSTEP_MAKEFILES before compiling!)
+endif
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+###########################
+# HelloGNUstepOutlineView #
+###########################
+VERSION = 1.0
+APP_NAME = HelloGNUstepOutlineView
+PACKAGE_NAME = $(APP_NAME)
+$(APP_NAME)_APPLICATION_ICON = GNUstep.tiff
+$(APP_NAME)_OBJC_FILES = $(APP_NAME).m
+
+-include GNUmakefile.preamble
+include $(GNUSTEP_MAKEFILES)/aggregate.make
+include $(GNUSTEP_MAKEFILES)/application.make
+-include GNUmakefile.postamble
+
+
+###########################
+# HelloGNUstepTableView #
+###########################
+VERSION = 1.0
+APP_NAME = HelloGNUstepTableView
+PACKAGE_NAME = $(APP_NAME)
+$(APP_NAME)_APPLICATION_ICON = GNUstep.tiff
+$(APP_NAME)_OBJC_FILES = $(APP_NAME).m
+
+#-include GNUmakefile.preamble
+#include $(GNUSTEP_MAKEFILES)/aggregate.make
+#include $(GNUSTEP_MAKEFILES)/application.make
+#-include GNUmakefile.postamble
+
+

File GNUstep.iconheader

+F	GNUstep		GNUstep		app

File GNUstep.tiff

Added
New image

File HelloGNUstep.postamble.h

+
+int main (int argc, const char** argv) 
+{
+#if !GNUSTEP
+    /* OS X initialization code. */
+    OSX_Startup_CPS();
+
+    /* Load image from Mach-O... */
+    [NSApp setApplicationIconImage: [NSImage imageNamed: @"NSApplicationIcon"]];
+#endif
+
+    /* Create app delegate and assign it to NSApp. */
+    AppController *controller = [[AppController new] autorelease];
+    [[NSApplication sharedApplication] setDelegate:controller];
+
+    /* Under OS X, it's de-facto required to create menus. */
+    [NSApp setMainMenu:[[[NSMenu alloc] init] autorelease]];
+    setApplicationMenu();
+    setupWindowMenu();
+
+    /* Okay, run the regular NSApplicationMain, as we usually would. */
+    return NSApplicationMain(argc, argv);
+}

File HelloGNUstep.preamble.h

+
+#import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
+
+#define APPNAME @"HelloGNUstepOutlineView"
+#import "StandardMenus.h"
+
+#if !GNUSTEP
+#import "OSX_Startup.h"
+#define APPCONTROLLER_PROTOCOLS <NSApplicationDelegate,NSOutlineViewDelegate>
+#define DATASOURCE_PROTOCOLS <NSOutlineViewDataSource>
+#else
+#define APPCONTROLLER_PROTOCOLS
+#define DATASOURCE_PROTOCOLS
+#endif
+

File HelloGNUstepOutlineView.m

+#import "HelloGNUstep.preamble.h"
+
+/* This class represents the 'model' for each row in the outline. */
+@interface Item : NSObject
+{
+    NSString * _value;
+    NSMutableArray * _children;
+}
++ (Item *) itemWithString: (NSString *)string;
+- (id) initWithString: (NSString *)string;
+- (void) addChild: (Item *)child;
+@end
+@implementation Item
++ (Item *) itemWithString: (NSString *)string
+{
+    return [[[self alloc] initWithString: string] autorelease];
+}
+- (id) initWithString: (NSString *)string
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    
+    _value = [string retain];
+    _children = [NSMutableArray new];
+
+    return self;
+}
+- (void) dealloc
+{
+    [_children release];
+    [_value release];
+    [super dealloc];
+}
+- (NSString *) description
+{
+    return _value;
+}
+- (BOOL) isEqualToString: (NSString *)aString
+{
+    return [_value isEqualToString: aString];
+}
+- (void) addChild: (Item *)child
+{
+    [_children addObject: child];
+}
+- (Item *) child: (NSInteger) index
+{
+    return [_children objectAtIndex: index];
+}
+- (NSInteger) childrenCount
+{
+    return [_children count];
+}
+@end
+
+@interface DataSource : NSObject DATASOURCE_PROTOCOLS
+{
+    Item * _root;
+}
+@end
+@implementation DataSource
+- (id) init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    _root = [[Item itemWithString: @"Root item"] retain];
+    
+    for(int i = 0; i < 2; i++)
+    {
+        Item * item = [Item itemWithString: @"Top-level item"];
+	[_root addChild: item];
+	for(int j = 0; j < 4; j++)
+	{
+	    Item * childItem = [Item itemWithString: @"Child item"];
+	    [item addChild: childItem];
+	}
+    }
+
+    return self;
+}
+-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
+{
+    if(item == nil)
+        return [_root childrenCount];
+
+    return [item childrenCount];
+}
+-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)parent
+{
+    if(parent == nil)
+        return [_root child: index];
+    return [parent child: index];
+}
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
+{
+    if(item == nil)
+        return [_root childrenCount] > 0;
+
+    return [item childrenCount] > 0;
+}
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
+{
+    return [item description];
+}
+@end
+
+@interface PrimitiveDataSource : NSObject DATASOURCE_PROTOCOLS
+@end
+@implementation PrimitiveDataSource
+/* A primitive and LEAKY data source implementation.
+
+   Leaks because NSOutlineView tries to LATER access, inside the
+   -outlineView:objectValueForTableColumn:ofItem:, an item that was provided to it
+   in -outlineView:child:ofItem:. Sadly, it does not retain the item and release it
+   later on.
+
+   This would be our duty.
+
+   But we don't do that in this class; instead we just -retain the items, and
+   conveniently 'forget' to release them.
+ 
+   This is a simpler class to understand it, so it's nonetheless provided here. */
+
+-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
+{
+    /* Two top-level items */
+    if(item == nil)
+        return 2;
+    
+    if([[item description] isEqualToString:@"Top-level item"])
+        return 3;
+    
+    return 0;
+}
+-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)parent
+{
+    /* NOTE THE LEAK! */
+
+    /* Note: You must not return the same object for multiple rows.
+       That'll break at least 'expandability'. So we return an "Item"
+       class, even though not required for this demo. */
+
+    /* Also note that the leak would not be a problem if we actually
+       returned the constant strings as the code originally did. */
+
+    if(parent == nil)
+        return [[Item itemWithString:@"Top-level item"] retain];
+    
+    return [[Item itemWithString:@"Child item"] retain];
+}
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
+{
+    /* Expandability of the root item does not really matter */
+    if(item == nil)
+        return NO;
+    
+    if([item isEqualToString:@"Top-level item"])
+        return YES;
+
+    return NO;
+}
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
+{
+    return [item description];
+}
+@end
+
+@interface AppController : NSObject APPCONTROLLER_PROTOCOLS
+{
+    NSWindow *window;
+    NSOutlineView *_outlineView;
+    id _dataSource;
+}
+-(id)init;
+-(void)applicationDidFinishLaunching:(NSNotification*)notif;
+-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(id)sender;
+@end
+
+@implementation AppController
+-(id)init 
+{ 
+    self = [super init];
+    if(self)
+    {
+        
+    }
+    return self;
+}
+
+-(void)dealloc
+{
+    [_outlineView release];
+    [_dataSource release];
+    [window release];
+    [super dealloc];    
+}
+
+-(void)applicationDidFinishLaunching:(NSNotification*)notif 
+{
+    window = [[NSWindow alloc] initWithContentRect:NSMakeRect(50,50,640,480) 
+                                         styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
+                                           backing:NSBackingStoreBuffered
+                                             defer:NO];
+    [window setTitle:APPNAME];
+    [window makeKeyAndOrderFront:nil];
+
+    NSButton* button = [[NSButton alloc] initWithFrame:NSMakeRect(15,300,150,24)];
+    [button setTitle:@"Test button"];
+    [button setTarget:self];
+    [button setAction:@selector(buttonWasClicked:)];
+    [button setBezelStyle:NSRoundedBezelStyle];
+    [[window contentView] addSubview:button];
+    [window setDefaultButtonCell:[button cell]];
+    [button release];
+    
+    NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(50,50,300,150)];
+    [[window contentView] addSubview:scrollView];
+    [scrollView release];
+    
+    _dataSource = [DataSource new];
+
+    NSOutlineView* outlineView = [[NSOutlineView alloc] initWithFrame:NSMakeRect(0,0,150,150)];
+    [outlineView setDataSource:_dataSource];
+    [outlineView setDelegate:self];
+    [scrollView setDocumentView:outlineView];
+    [outlineView release];
+    
+    NSTableColumn * column = [[NSTableColumn alloc] initWithIdentifier:@"Column"];
+    [column setWidth: 250];
+    [outlineView addTableColumn:column];
+    [outlineView setOutlineTableColumn:column];
+    [column release];
+        
+    _outlineView = outlineView;
+}
+
+-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(id)sender 
+{ 
+    return YES; 
+}
+
+-(void)buttonWasClicked:(id)sender
+{
+    [sender setTitle:@"Ouch!"];
+}
+
+@end
+
+#include "HelloGNUstep.postamble.h"
+
+<?xml version="1.0"?>
+<plist version="1.0">
+<dict>
+<key>CFBundleDevelopmentRegion</key>
+<string>English</string>
+<key>CFBundleIdentifier</key>
+<string>net.vucica.hellognustep.outlineview</string>
+<key>CFBundleInfoDictionaryVersion</key>
+<string>6.0</string>
+<key>CFBundleName</key>
+<string>HelloGNUstepOutlineView</string>
+<key>CFBundleVersion</key>
+<string>1.0</string>
+<key>NSPrincipalClass</key>
+<string>NSApplication</string>
+</dict>
+</plist>

File Makefile.mac

+EMBED_INFOPLIST=-sectcreate __TEXT __info_plist Info.plist 
+EMBED_ICON=-sectcreate __ICON __header GNUstep.iconheader -segprot __ICON r r  -sectcreate __ICON app GNUstep.tiff 
+
+CFLAGS=-mmacosx-version-min=10.6
+LDFLAGS+=$(CFLAGS) $(EMBED_INFOPLIST) $(EMBED_ICON) -framework Foundation -framework AppKit
+
+#DEPS=Info.plist GNUstep.tiff GNUstep.iconheader
+
+all: HelloGNUstepOutlineView
+#HelloGNUstepTableView
+
+clean:
+	-rm *.o
+	-rm HelloGNUstepOutlineView
+
+# Verify using: 
+# otool -s __TEXT __info_plist main|xxd -r

File OSX_Startup.h

+/* This odd code is required if we're not ran from an app bundle.
+   Otherwise the window is not properly focused. And other nasty stuff
+   also happens. */
+
+#define USE_CPS 0
+
+#if USE_CPS
+typedef struct CPSProcessSerNum
+{
+    UInt32          lo;
+    UInt32          hi;
+} CPSProcessSerNum;
+
+extern OSErr    CPSGetCurrentProcess( CPSProcessSerNum *psn);
+extern OSErr    CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+extern OSErr    CPSSetFrontProcess( CPSProcessSerNum *psn);
+#else
+extern OSErr    CPSEnableForegroundOperation( ProcessSerialNumber *psn);
+#endif
+
+static void OSX_Startup_CPS()
+{
+    if (1) {
+#if USE_CPS
+        CPSProcessSerNum PSN;
+        /* Tell the dock about us */
+        if (!CPSGetCurrentProcess(&PSN))
+            if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
+                if (!CPSSetFrontProcess(&PSN))
+                    [NSApplication sharedApplication];
+#else
+        ProcessSerialNumber PSN;
+        if(!GetCurrentProcess(&PSN))
+            if(!CPSEnableForegroundOperation(&PSN))
+                if(!SetFrontProcess(&PSN))
+                    [NSApplication sharedApplication];
+#endif
+    }
+    
+}
+# HelloGNUstep
+
+This is a small collection of test programs and samples. It is intended
+to go from the simplest to the most difficult example, step by step.
+
+Locally, the author has additional, far more basic examples, but these
+have not been prepared for publication yet.
+
+Also included is Makefile.mac, a demonstration of a Cocoa application
+outside an application bundle. It includes an Info.plist and an icon
+inside the Mach-O headers. This seems supported by AppKit, but not by
+Finder; no Info.plist or icon data is used by Finder.
+
+- Ivan Vučica
+

File StandardMenus.h

+
+#if !GNUSTEP
+@interface NSMenu (Private)
+- (void) setAppleMenu: (NSMenu*)menu;
+@end
+#endif
+
+static void setApplicationMenu(void)
+{
+    NSMenu *appleMenu;
+    NSMenuItem *menuItem;
+    NSString *title;
+    NSString *appName;
+    
+    appName = APPNAME;
+    appleMenu = [[NSMenu alloc] initWithTitle:@""];
+    
+    /* Add menu items */
+    title = [@"About " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
+    
+    [appleMenu addItem:[NSMenuItem separatorItem]];
+    
+    title = [@"Hide " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
+    
+    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
+    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
+    
+    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
+    
+    [appleMenu addItem:[NSMenuItem separatorItem]];
+    
+    title = [@"Quit " stringByAppendingString:appName];
+    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];    
+    
+    /* Put menu into the menubar */
+    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
+    [menuItem setSubmenu:appleMenu];
+    [[NSApp mainMenu] addItem:menuItem];
+    
+    /* Tell the application object that this is now the application menu */
+    [NSApp setAppleMenu:appleMenu];
+    
+    /* Finally give up our references to the objects */
+    [appleMenu release];
+    [menuItem release];
+}
+
+static void setupWindowMenu(void)
+{
+    NSMenu      *windowMenu;
+    NSMenuItem  *windowMenuItem;
+    NSMenuItem  *menuItem;
+    
+    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+    
+    /* "Minimize" item */
+    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+    [windowMenu addItem:menuItem];
+    [menuItem release];
+    
+    /* Put menu into the menubar */
+    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
+    [windowMenuItem setSubmenu:windowMenu];
+    [[NSApp mainMenu] addItem:windowMenuItem];
+    
+    /* Tell the application object that this is now the window menu */
+    [NSApp setWindowsMenu:windowMenu];
+    
+    /* Finally give up our references to the objects */
+    [windowMenu release];
+    [windowMenuItem release];
+}
+