Document based app with Gorm and PC

From GNUstepWiki
Revision as of 21:00, 6 September 2024 by Buzzdee (talk | contribs) (Created page with "== About == This tutorial is going to show off how to create a Document based app, it'll cover the following: * simple overview about MVC and document based apps ** what cla...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

About

This tutorial is going to show off how to create a Document based app, it'll cover the following:

  • simple overview about MVC and document based apps
    • what classes to be used and how it fits into the MVC model
  • using ProjectCenter and Gorm
    • simple introduction into both tools, some tips 'n tricks
    • how to enable ARC in ProjectCenter
  • KVC/KVO to keep the UI in sync with the model
  • the App we're going to create will be localized
    • we'll switch the default language to something else than English ;)
  • the app will handle multiple documents

This tutorial is not meant for long time Mac Cocoa Objective-C developers. It's more for people like me, lacking a Mac, but want to give the Cocoa Framework a try. To be honest, I read through "Cocoa Programming Developer's Handbook" by David Chisnall, but still, afterward it took me a couple of weeks with the help of ChatGPT to get the test app we're going over here, to finally work and being well structured. Reading the book, is very helpful in the first place, and dramatically helps talking to ChatGPT. ChatGPT is actually not too bad, it's even aware of some differences between GNUstep and Cocoa, but sometimes hallucinates methods that don't exist, or it might guide you into the wrong direction.

Structure

  • first there will be an overview about MVC, and the classes we're going to use in the App, and how these fit into the paradigm
    • how things are wiring up
  • then continue with a quick introduction into PC and Gorm
    • some small tips 'n tricks to make using them a bit easier
  • then we'll start implementing the application
    • step by step, dealing with one type of document to be managed in the app
  • at the end, you should be able to implement handling of a second type of document

Code for the example application can be found here: https://github.com/buzzdeee/DocumentBasedAppTutorial

MVC and document based apps

Cocoa MVC (Model-View-Controller) is a design pattern used in Apple's Cocoa framework to separate concerns in an application. The Model represents the data and business logic, the View displays the data and handles user interface elements, and the Controller manages communication between the Model and View, updating the UI based on changes in the data. This separation promotes modularity, making the code more maintainable and reusable.

In a Cocoa (or GNUstep) document-based app that supports multiple documents, the classes involved can be mapped to the Model-View-Controller (MVC) pattern. Here’s how the various components like NSDocument, NSDocumentController, NSWindowController, document model classes, and UI built with Gorm fit into MVC:

  1. Model (M) The model represents the application's data and business logic. In a document-based app, the following components are part of the model:
    1. Plain classes for the document models: These are your custom classes that contain the data and logic specific to your document. These classes are independent of the UI and are responsible for holding the document's data, performing any processing, and managing state.
    2. For example, if you’re building a text editor, the model class might store the text, keep track of formatting, and manage metadata (like the document title or file path).
    3. NSDocument: While NSDocument primarily fits into the controller part of MVC, it also has some aspects of the model in Cocoa’s architecture. NSDocument handles saving, loading, and managing the undo functionality, so it acts as a mediator between the model data and persistence (reading/writing the file). It interacts closely with the document model classes to manage the actual content.
  2. View (V) The view is responsible for displaying the data and handling user input.
    1. UI built with Gorm: Gorm is used to build the UI components in the app, which form the view. These include:
      1. Windows, menus, buttons, text fields, etc. created in Gorm are part of the view layer. They display the content of your document and allow users to interact with it.
      2. For example, if you're using a text editor, the NSTextView or custom views to display text are part of the view layer.
    2. NSWindowController: The NSWindowController is responsible for managing the app’s windows and handling the interaction between the view and the document (controller). It loads the interface from a .gorm file (which contains the window and its views) and binds the UI elements to the document data. In strict MVC, it is part of the controller, but because it manages UI and views, it has aspects of both the controller and view layers.
  3. Controller (C) The controller manages the interactions between the model and the view, mediating user input, updating the view, and manipulating the model as needed.
    1. NSDocument: As mentioned, NSDocument serves as the document controller in this architecture. It communicates with the model (plain document classes) to retrieve and save the document data and updates the view when necessary. It also handles document-specific tasks like managing undo/redo, saving, and opening documents. It doesn't directly manage the UI but works closely with the NSWindowController to coordinate the display of the document.
    2. NSDocumentController: This class is responsible for managing all documents in the application. It keeps track of which documents are open, handles creating new documents, and ensures that the correct document is presented in the appropriate window. NSDocumentController also manages interactions like opening recent files, handling document lifecycle events (new, open, close), and interacting with NSDocument objects. It plays a key role in coordinating the flow between the user’s actions and the document management.
    3. NSWindowController: Though it has a close relationship with the view, NSWindowController also has controller responsibilities. It coordinates with NSDocument to ensure that the correct data is presented in the view. It manages the window’s lifecycle and keeps the UI in sync with the document data.

Breakdown of the MVC components

  • Model: Plain document classes (contain the data and business logic).
  • View: UI components built with Gorm, which display the document’s data.
  • Controller:
    • NSDocument: Bridges the model and the view, managing document-specific tasks (loading, saving, undo/redo).
    • NSWindowController: Manages windows and interfaces with NSDocument to update the views.
    • NSDocumentController: Oversees multiple documents, handles document creation, and ensures that the correct documents are open/active.

Workflow example in MVC context

  1. User Action: A user opens an existing document from the File menu (View).
  2. Controller Response: The NSDocumentController coordinates opening the file by creating or loading the corresponding NSDocument object (Controller).
  3. Model Interaction: The NSDocument interacts with the plain document model class to load the data from the file (Model).
  4. UI Update: The NSWindowController ensures that the document’s data is reflected in the views loaded from the Gorm interface file (View).
  5. User Edits: The user modifies the document content via the UI (View), and the NSDocument updates the document model class accordingly (Model).

In this way, each class in a Cocoa (GNUstep) document-based app has a clear responsibility within the MVC framework, ensuring separation of concerns and maintainability of the application’s architecture.

Development Environment

This tutorial was developed on OpenBSD, with just the main GNUstep packages installed. If you're up to it, and it's probably one of the easiest ways to get a a modern GNUstep development environment supporting libobjc2 and ARC up and running ;)

  1. Install OpenBSD on a spare machine or VM, enable xdm
  2. install GNUstep as easy as: pkg_add gnustep-desktop
  3. configure your .xsession alike:
if [ -f /usr/local/share/GNUstep/Makefiles/GNUstep.sh ];then
       . /usr/local/share/GNUstep/Makefiles/GNUstep.sh
fi
export GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding
export LC_ALL='en_EN.UTF-8'
export LC_CTYPE='en_US.UTF-8'
if [ -x /usr/local/bin/gpbs ];then
       /usr/local/bin/gpbs
fi
if [ -x /usr/local/bin/gdnc ];then
       /usr/local/bin/gdnc
fi
wmaker &
if [ -x /usr/local/bin/GWorkspace ];then
       /usr/local/bin/make_services
       /usr/local/bin/GWorkspace
fi

With these simple steps, you'll have a working GNUstep development environment.

Debugging

If you want to debug, you may want to install egdb from packages as well. To ease debugging, it might make sense to have the gnustep library sources around, and those build with debugging symbols, to do so:

  1. add the following to your /etc/doas.conf file:
          permit nopass keepenv :wsrc
          permit nopass keepenv :wheel
    1. NOTE: this allows passwordless root for the main user
  1. echo "echo 'DEBUG=-g -O0'" > /etc/mk.conf
  2. echo "echo 'SUDO=doas'" >> /etc/mk.conf
  3. doas pkg_delete gnustep-base gnustep-libobjc2 gnustep-make
  4. download and extract the ports.tar.gz to /usr/ports
  5. cd /usr/ports/x11/gnustep/
  6. make install
  7. make patch

just reboot, or relogin, then you should have your GNUstep packages around, built with debugging symbols, as well as the sources on disk. This will dramatically ease debugging using egdb.

ProjectCenter and Gorm

GNUstep ProjectCenter and Gorm are tools for developing applications using the GNUstep framework.

  • ProjectCenter is an integrated development environment (IDE) that helps developers manage their projects, providing tools to create, organize, and compile GNUstep applications. It simplifies the setup and management of project files, source code, and build configurations, making it easier to develop Objective-C applications.
  • Gorm: (GNUstep Object Relationship Modeler) is a visual interface builder similar to Apple's Interface Builder. It allows developers to design user interfaces by dragging and dropping UI components, connecting them to the application's code, and managing the relationships between UI elements and objects, without writing the UI code manually.

Together, these tools streamline the development of GNUstep-based applications by providing a cohesive environment for both project management and user interface design.

Creating your Project

With all that prepared, you're now ready to create the basic project:

ProjectCenter

With either just gnustep-desktop package(s) installed, or even built by yourself from ports, you should now be able to just start ProjectCenter from the command line, i.e. xterm window.

Once it's started, you want to configure it a bit, to ensure a smooth experience ;)

  • Open the Preferences Build menu
    • ensure External Build Tool points to /usr/local/bin/gmake or wherever your GNU Make is when you're not on OpenBSD. A BSD make just won't work.
  • Open the Preferences Miscellaneous menu
    • ensure Debugger points to /usr/local/bin/egdb or whatever is the right one for your platform
    • ensure Editor is ProjectCenter. That should be the default, you may use others, i.e. Gemas...


Now Open the Project -> New menu, select a suitable place where you want to have your project reside. Ensure Project Type is set to Application and give it a name. We'll name our project DocumentBasedApp as you can see in the screenshot below. (You may actually not want to choose /tmp as your destination folder ;)