Getting Started
This guide takes you from a source checkout to a small Orion application that runs both as a standalone executable and as a loadable GEM.
Choose An Installation
For released SDK packages, install Orion with the package manager:
curl -fsSL https://raw.githubusercontent.com/corepunch/orion-ui/main/install.sh | sh
export PATH="/opt/orion/bin:$PATH"
For framework development or to build the bundled applications, use a checkout:
git clone https://github.com/corepunch/orion-ui.git
cd orion-ui
git submodule update --init --recursive
make library
Orion requires a C toolchain and Git. Its Platform layer provides native windowing, input, and rendering. Lua is optional and is needed only for scripting-enabled features.
Build And Explore
make apps # all standalone applications
make build/bin/helloworld # one application
make gems # loadable GEM modules
make tools # orionc and utility programs
make test # complete test suite
Start with the minimal app, then inspect the complete application gallery:
build/bin/helloworld
- Applications shows representative workflows and source patterns.
- Controls maps reusable controls to real application screens.
- Architecture explains ownership and message flow.
A Minimal Application
Orion applications expose gem_init and optionally gem_shutdown. The same source becomes a standalone executable through GEM_STANDALONE_MAIN and a loadable module through GEM_DEFINE.
#include <orion/ui.h>
#include <orion/gem.h>
#define ID_HELLO 100
static window_t *g_main_win;
static result_t main_proc(window_t *win, uint32_t msg,
uint32_t wparam, void *lparam) {
switch (msg) {
case evCreate: {
window_t *button = create_window(
"Hello", WINDOW_NOTITLE, MAKERECT(16, 16, 72, 19),
win, win_button, 0, NULL);
button->id = ID_HELLO;
return true;
}
case evCommand:
if (LOWORD(wparam) == ID_HELLO && HIWORD(wparam) == btnClicked) {
message_box(win, "Hello from Orion.", "My App", MB_OK);
return true;
}
return false;
case evPaint:
draw_text_small("My first Orion app", 16, 48,
get_sys_color(brTextNormal));
return true;
case evDestroy:
#ifndef BUILD_AS_GEM
ui_request_quit();
#endif
return true;
default:
return false;
}
}
bool gem_init(int argc, char *argv[], hinstance_t hinstance) {
(void)argc;
(void)argv;
register_commctl_classes();
g_main_win = create_window(
"My App", 0, MAKERECT(32, 32, 320, 200),
NULL, main_proc, hinstance, NULL);
if (!g_main_win) return false;
show_window(g_main_win, true);
return true;
}
void gem_shutdown(void) {
g_main_win = NULL;
}
GEM_DEFINE("My App", "1.0", gem_init, gem_shutdown, NULL)
GEM_STANDALONE_MAIN("My App", UI_INIT_DESKTOP, 640, 480, NULL, NULL)
The important contracts are:
- Window behavior lives in a
winproc_tand is driven by messages. create_windowreceives title, flags, frame, parent, class/proc, instance, and creation parameter.- Controls notify the root window with
evCommand; decode the control ID withLOWORDand the notification withHIWORD. - Drawing happens only during
evPaint. State changes callinvalidate_window(). - Standalone apps own the event loop; GEMs share the Shell event loop.
Prefer Declarative Forms
The hand-built window above teaches the lifecycle. For dialogs and panels with multiple standard controls, use a .orion resource instead of creating every child in evCreate:
<?xml version="1.0" encoding="UTF-8"?>
<orion version="1" name="myapp" title="My App" root="apps/myapp">
<forms>
<form name="main" title="My App" width="320" height="180"
spacing="8" padding="8">
<Label name="heading" text="My first Orion app" />
<StackView name="actions" orientation="horizontal" spacing="6">
<Space name="fill" />
<Button name="hello" value="100" text="Hello" />
</StackView>
</form>
</forms>
</orion>
orionc generates typed form, menu, toolbar, accelerator, and database metadata. Create the form with create_window_from_form() and continue to use evCommand for notifications. See Dialogs & DDX, Database Forms, and MDI Application Architecture.
Add A New Repository App
Use one directory per application:
apps/myapp/
├── dialogs/ Modal workflows when needed
├── components/ App-specific reusable controls when needed
├── share/ Icons, seed data, and other runtime assets
└── tests/ App-specific tests
Keep persistent models independent of windows and rendering. Put message procedures in views, application state and command dispatch in a controller, and static UI/resources in the .orion definition. The Application Presentation Guide explains how to document and capture the finished app.
Build Against An Installed SDK
CC = cc
CFLAGS = -Wall -Wextra -std=c11 -I/opt/orion/include
LIBS = -L/opt/orion/lib -lkernel -lcommctl -lcommdlg -luser -lplatform
myapp: main.c
$(CC) $(CFLAGS) -o $@ $< $(LIBS)
Use <orion/ui.h> for the framework and <orion/gem.h> for the dual standalone/GEM lifecycle. Add Lua flags only when the app uses Lua.
Where To Go Next
| Goal | Guide |
|---|---|
| Understand windows and client geometry | Window System |
| Handle commands, input, and custom messages | Messages & Events |
| Use standard controls and layouts | Controls |
| Build declarative dialogs | Dialogs & DDX |
| Bind forms to records | Database Forms |
| Build menus and icon toolbars | Toolbars |
| Build a multi-document application | MDI Architecture |
| Load applications into Orion Shell | GEM Plugin System |
| Understand framework ownership | Architecture |