James51332
James51332

Reputation: 169

Create NSApplication in C++

I am working on trying to create a game engine from literal scratch (using only os's provided systems) and am trying to create it in c++. As a test, I wanted to create a c++ wrapper for a cocoa window. (Add Graphics Later) I found I needed to use the pimpl idiom. I have an App.cpp file (main method for testing), Device.h file and Device.cpp file. This code compiles using clang++ without any issues, so why doesn't it display a window to the screen.

App.cpp

#include "Device.h"

int main() {
  Outlaw::MacDevice* device = new Outlaw::MacDevice();
}

Device.h

namespace Outlaw {

    //C++ NSView Wrapper Class
    struct MacViewImpl;
    struct MacViewRect;
    class MacView {
    public:
      MacViewImpl* impl;
      MacViewRect* frame;
      MacView();
      ~MacView();
    };

    //C++ NSWindow Wrapper Class;
    struct MacWindowImpl;
    class MacWindow {
    public:
      MacWindowImpl* impl;
      MacWindow(MacView* view);
      ~MacWindow();
    };

    struct MacDeviceImpl;
    class MacDevice {
    public:
      MacDeviceImpl* impl;

      MacWindow* window;
      MacView* view;
      MacDevice();
      ~MacDevice();
      void Run();
    };
}

Device.mm

#include <Cocoa/Cocoa.h>

#include "Device.h"

@interface MacViewItfc : NSView
-(void)drawRect:(NSRect)rect;
@end

@implementation MacViewItfc
-(void) drawRect:(NSRect)rect {
  [[NSColor grayColor] set];
  NSRectFill([self bounds]);
}
@end

@interface MacWindowItfc : NSWindow <NSApplicationDelegate>
@end

@implementation MacWindowItfc
@end

namespace Outlaw {
  //C++ Wrapper for ViewItfc (NSView)
  struct MacViewImpl {
    MacViewItfc* pimpl;
  };
  struct MacViewRect {
    NSRect pimpl = NSMakeRect(100.0,100.0,300.0,300.0);
  };
  MacView::MacView() :
    impl(new MacViewImpl), frame(new MacViewRect) {
    impl->pimpl = [[MacViewItfc alloc] initWithFrame:frame->pimpl];
  }
  MacView::~MacView() {
    if (impl)
      [impl->pimpl release];
  }

  //C++ Wrapper for WindowItfc (NSWindow)
  struct MacWindowImpl {
    MacWindowItfc* pimpl;
  };
  MacWindow::MacWindow(MacView* view) :
    impl(new MacWindowImpl) {
    impl->pimpl = [[MacWindowItfc alloc] initWithContentRect:view->frame->pimpl
                                         styleMask:NSWindowStyleMaskTitled
                                                  |NSWindowStyleMaskClosable
                                                  |NSWindowStyleMaskResizable
                                         backing:NSBackingStoreBuffered
                                         defer:NO];

    [impl->pimpl setTitle:@"Outlaw Game"];
    [impl->pimpl setContentView:view->impl->pimpl];
    [impl->pimpl makeKeyAndOrderFront:nil];
  }
  MacWindow::~MacWindow() {
    if (impl)
      [impl->pimpl release];
  }

  //C++ Wrapper for NSApplication
  struct MacDeviceImpl {
    NSApplication* pimpl;
  };
  MacDevice::MacDevice()
    : impl(new MacDeviceImpl) {
      impl->pimpl = [NSApplication sharedApplication];
      view = new MacView();
      window = new MacWindow(view);
      [impl->pimpl setDelegate:window->impl->pimpl];
  }
  MacDevice::~MacDevice() {
    if (impl)
      [impl->pimpl release];
  }
  void MacDevice::Run() {
    [impl->pimpl run];
  }
}

So why doesn't the executable created create a window and what can I do to fix it?

Upvotes: 0

Views: 1191

Answers (1)

gavinb
gavinb

Reputation: 20028

Your main function is only creating the instance. You need to call Run to actually run the event loop:

#include "Device.h"

int main() {
    Outlaw::MacDevice* device = new Outlaw::MacDevice();
    device->Run();
    return 0;
}

Upvotes: 2

Related Questions