Sciter for D

Dejan Lekic dejan.lekic at gmail.com
Mon May 25 19:55:56 UTC 2026


On Thursday, 14 May 2026 at 20:56:22 UTC, c-smile wrote:
> I've almost done with D version of [Sciter](https://sciter.com) 
> SDK.

HTML5, CSS3, DOM, JS for a GUI application is absolutely not 
necessary. However I do understand why people want to use them - 
these are anywhere. People are familiar with them, etc...

![Simiar application with giD, running on 
Linux](https://gcdnb.pbrd.co/images/UNoIFtgUT4QC.png)

To run, save to clock.d and then `dub run --single clock.d`, and 
soon you will get the application window similar to the 
screenshot above, assuming you have GTK4 installed.

PS. I could as easily embed entire WebKit into my giD-based 
application and have all the above, and more, so what do D 
developers get with sciter that separates it from the rest of the 
crowd?

Code:
```d
/+dub.sdl:
     name "gidex-clock"
     dependency "gid:gtk4" version="*"
     targetType "executable"
+/

/// Analog clock application using gid:gtk4 and Cairo.
/// Run with: dub run --single src/gidex/clock.d

module gidex.clock;

import std.datetime.systime;
import core.stdc.stdio : sprintf;

import gtk.application;
import gtk.application_window;
import gtk.box;
import gtk.label;
import gtk.types : Orientation;
import gio.types : ApplicationFlags;
import gio.application : GioApp = Application;
import gtk.drawing_area;

import cairo.context;

import glib.global : timeoutAdd;

enum PI = 3.1415926f;

class ClockWindow : ApplicationWindow {
     DrawingArea drawingArea;

     this(gtk.application.Application app) {
         super(app);
         setTitle("giD Clock");
         setDefaultSize(400, 450);

         auto box = new Box(Orientation.Vertical, 8);

         auto titleLbl = new Label("The D Clock");
         titleLbl.setMarginTop(8);
         box.append(titleLbl);

         drawingArea = new DrawingArea();
         drawingArea.setContentWidth(300);
         drawingArea.setContentHeight(300);
         drawingArea.setMarginStart(16);
         drawingArea.setMarginEnd(16);
         drawingArea.setVexpand(true);
         drawingArea.setHexpand(true);

         drawingArea.setDrawFunc(&drawClock);

         box.append(drawingArea);

         setChild(box);

         // Tick every second to keep the clock hands moving
         timeoutAdd(0, 1000, {
             drawingArea.queueDraw();
             return true;
         });
     }

     void drawClock(DrawingArea area, Context cr, int width, int 
height) {
         import std.math : cos, sin;
         import cairo.types;

         float cx = width / 2.0f;
         float cy = height / 2.0f;
         float radius = (cx < cy ? cx : cy) * 0.9f;

         // White clock face
         cr.setSourceRgba(1.0, 1.0, 1.0, 1.0);
         cr.arc(cx, cy, radius, 0, 2 * PI);
         cr.fill();

         // Clock border
         cr.setSourceRgba(0.2, 0.2, 0.2, 1.0);
         cr.setLineWidth(radius * 0.02);
         cr.arc(cx, cy, radius, 0, 2 * PI);
         cr.stroke();

         cr.setLineCap(LineCap.Round);

         // Hour marks
         cr.setSourceRgba(0.196, 0.373, 0.635, 1.0); // #325FA2
         cr.setLineWidth(radius * 0.04);
         foreach (i; 0 .. 12) {
             float angle = i * PI / 6.0f - PI / 2.0f;
             float inner = radius * 0.85f;
             float outer = radius * 0.92f;
             cr.moveTo(cx + inner * cos(angle), cy + inner * 
sin(angle));
             cr.lineTo(cx + outer * cos(angle), cy + outer * 
sin(angle));
             cr.stroke();
         }

         // Minute marks
         cr.setSourceRgba(0.647, 0.165, 0.165, 1.0); // #A52A2A
         cr.setLineWidth(radius * 0.015);
         foreach (i; 0 .. 60) {
             if (i % 5 != 0) {
                 float angle = i * PI / 30.0f - PI / 2.0f;
                 float inner = radius * 0.9f;
                 float outer = radius * 0.92f;
                 cr.moveTo(cx + inner * cos(angle), cy + inner * 
sin(angle));
                 cr.lineTo(cx + outer * cos(angle), cy + outer * 
sin(angle));
                 cr.stroke();
             }
         }

         // Current time
         SysTime now = Clock.currTime();
         uint sec = now.second;
         uint min = now.minute;
         uint hr = now.hour;
         hr = hr >= 12 ? hr - 12 : hr;

         // Date text
         {
             char[20] buf;
             int written = sprintf(buf.ptr, "%04d-%02d-%02d",
                 now.year, now.month, now.day);
             string dateStr = buf[0 .. written].idup;
             cr.setSourceRgba(0.647, 0.165, 0.165, 1.0); // brown
             cr.selectFontFace("Sans", FontSlant.Normal, 
FontWeight.Normal);
             cr.setFontSize(radius * 0.12);
             TextExtents te;
             cr.textExtents(dateStr, te);
             cr.moveTo(cx - te.width / 2.0, cy + radius * 0.35);
             cr.showText(dateStr);
         }

         // Hour hand
         {
             float angle = (hr * (PI / 6.0f) + (PI / 360.0f) * min 
+ (PI / 21600.0f) * sec) - PI / 2.0f;
             cr.setSourceRgba(0.196, 0.373, 0.635, 1.0);
             cr.setLineWidth(radius * 0.06);
             cr.setLineCap(LineCap.Round);
             cr.moveTo(cx - radius * 0.12 * cos(angle), cy - 
radius * 0.12 * sin(angle));
             cr.lineTo(cx + radius * 0.5 * cos(angle), cy + radius 
* 0.5 * sin(angle));
             cr.stroke();
         }

         // Minute hand
         {
             float angle = ((PI / 30.0f) * min + (PI / 1800.0f) * 
sec) - PI / 2.0f;
             cr.setSourceRgba(0.196, 0.373, 0.635, 1.0);
             cr.setLineWidth(radius * 0.04);
             cr.setLineCap(LineCap.Round);
             cr.moveTo(cx - radius * 0.15 * cos(angle), cy - 
radius * 0.15 * sin(angle));
             cr.lineTo(cx + radius * 0.7 * cos(angle), cy + radius 
* 0.7 * sin(angle));
             cr.stroke();
         }

         // Second hand
         {
             float angle = sec * PI / 30.0f - PI / 2.0f;
             cr.setSourceRgba(0.831, 0.0, 0.0, 1.0); // #D40000
             cr.setLineWidth(radius * 0.02);
             cr.setLineCap(LineCap.Round);
             cr.moveTo(cx - radius * 0.18 * cos(angle), cy - 
radius * 0.18 * sin(angle));
             cr.lineTo(cx + radius * 0.6 * cos(angle), cy + radius 
* 0.6 * sin(angle));
             cr.stroke();

             // Small circle at tip
             cr.arc(cx + radius * 0.6 * cos(angle), cy + radius * 
0.6 * sin(angle), radius * 0.03, 0, 2 * PI);
             cr.fill();

             // Center dot
             cr.arc(cx, cy, radius * 0.04, 0, 2 * PI);
             cr.fill();
         }
     }
}

class ClockApplication : gtk.application.Application {
     ClockWindow window;

     this() {
         super("org.example.gidex-clock", 
ApplicationFlags.DefaultFlags);
         connectActivate(&onActivate);
     }

     void onActivate(GioApp app) {
         if (!window)
             window = new ClockWindow(this);
         window.present();
     }
}

void main(string[] args) {
     auto app = new ClockApplication;
     app.run(args);
}
```


More information about the Digitalmars-d-announce mailing list