Pull to refresh

Comments 48

UFO just landed and posted this here
Могу добавить. Выглядит точно так же, только рамка окна другая и шрифты.
Добавил скриншот для Ubuntu.
На Маке проверить не могу — нет его у меня.
Жаль, что не мимикрирует под системные темы.
Можно сделать темы под каждую систему похожие на нативные.
Еще проблемы — меню на маке и Unity. Должно быть в системном меню, вместо этого — в верхней части окна. Смотрится чужеродно.

UFO just landed and posted this here
Под windows 32bit — 1.4Mb, linux 64bit — 4Mb
Почему под Linux больше — непонятно.
UFO just landed and posted this here
UFO just landed and posted this here
Обращаюсь. Давно хотел освоить D. Моя почта у Гугла совпадает с ником.
UFO just landed and posted this here
Для Qt 4 есть пара биндингов.

Не знаю, насколько эти проекты живые.
Это нормально, окно только маленькое. Надо вручную растянуть.
> Возможность отрисовки виджетов поверх OpenGL сцены (например, для UI в игре)

Хотелось бы туториала именно про этому пункту. Мы давно приглядываемся к DlangUI, чтобы не городить очередных велосипедов.

У нас используется DSFML для создания контекста, а внутрях репозитория находили только адаптеры для SDL. Насколько сложно реализовать обертку для DSFML?
Примера/туториала нет, но можно сделать.
Есть какой-нибудь DSFML проект, на котором можно поэкспериментировать?
Надо реализовать Platform и Window под DSFML.
На данный момент открытого проекта нет, основной, к сожалению, проприетарный и очень тяжеловесный.
Отличный повод начать изучать язык.
Возможно стоит продолжить по ходу появления вопросов у читателей и накопления критической массы материала для новой статьи.
Спасибо.
Да, следующая часть нужна, хотелось бы объяснения принципа работы, как определяете что надо перерисовывать а что нет, используются ли регионы отсечения.
Подумаю, что интересного можно рассказать.

А если коротко, используется двухфазная модель measure / layout как в Android.
Перерисовка всегда идет полностью.
При включенном OpenGL все равно только полностью можно перерисовывать.

Есть разделение на основную часть и backend — код для поддержки конкретной платформы (создание окон, отрисовка bitmap или создание OpenGL контекста, трансляция событий мыши и клавиатуры, ...).

Графика может рисоваться в bitmap буфер c помощью software renderer, или в OpenGL контекст. Общий интерфейс прячет реализацию.
UFO just landed and posted this here
Пока еще не догнал.
CTFE и метапрограммирование в D все еще на порядок лучше.
Чистый синтаксис.
Многое без garbage collector реализовать сложно или невозможно.
mixins — навряд ли когда-нибудь будут в C++.
LDC я попробовал — он тормозной. Один файл компилирует столько же времени, сколько DMD — проект из сотни файлов.
Для разработки не очень подходит из-за тормознутости.
Скорее для финального билда.
Да, это частая практика — использовать DMD для разработки, но собирать финальную версию с помощью GDC/LDC.
Для идиоматического кода в стиле Phobos LDC сейчас создаёт самые компактные бинарники с большим отрывом, т.к. по умолчанию включено --gc-sections для линкера.
По-моему, у проекта немалый потенциал. Развивайте!

Скажите, а декларативность описания UI, будет, как в Sciter? CSS или аналог обязателен. Хороший UI в наше время должны делать профессионалы с помощью профессиональных инструментов, а не кодом.
Скоро будет возможность загрузки layout из xml (как в Android) или чего-то похожего на QML. Выбираю формат. (Issue #58 в трекере)

Планируется автоматическая привязка загруженных виджетов к полям класса при совпадении ID виджета и названия переменной (например, в ресурсе есть Button с id=«button1», а в классе — переменная Button _button1 — после загрузки ссылка на созданный виджет будет сохранена в эту переменную), а так же автоматическое назначение обработчиков сигналов — по id виджета и названию (например, если есть виджет с id=«button1» а в классе — метод bool onButton1Click(Widget src) — этот метод будет назначен на onClickListener загруженного виджета.
А, понятно, VB-style. Иногда бывает нужно назначить один обработчик для многих однотипных контролов, предусмотрите это.

И подумайте об отделении стилей от layout-а, это очень важно.
Стили есть в теме.
Можно назначить Id стиля виджету. По умолчанию у стандартных виджетов уже выставлен id родного стиля.
Можно переопределить часть свойств стиля у конкретного виджета — остальные будут браться из стиля темы.
Если не переопределять никаких свойств стиля у виджета — будет напрямую использоваться стиль из темы.
При изменении таких свойств создается новый экземпляр стиля (copy-on-write) с указанием базового стиля — из темы.
Крайне не хватает реактивности.

Как реализована кроссплатформенность? Через какие-то кроссплатформенные графические библиотеки или кучей прагм под разные платформы? Интересуюсь, потому-что тоже хочу что-то такое замутить.
Есть слой абстракции от платформы.
Для конкретной платформы надо определить backend — наследников классов Platform и Window.
Для win32 это занимает 72Kb, для sdl — 54K.
Если есть возможность (и dlangui построен с USE_OPENGL), отрисовка идет через OpenGL.
Иначе платформа должна определить способ отрисовки ARGB битмапа в окно.
Отрисовка графики идет с использованием интерфейса DrawBuf — в котором реализованы примитивы рисования прямоугольника, битмапа, символа текста, и т.д.
Также backend должен обеспечить трансляцию событий от мыши и клавиатуры в события dlangui.
Ну, то есть эти бекенды — это ваш велосипед и нет уже чего-то готового?
win32 backend — это велосипед на базе win32 api
sld2 backend — адаптер между sdl2 и dlangui
Зачем тогда win32 если SDL «officially supports Windows, Mac OS X, Linux, iOS, and Android»?
чтобы необязательна DLL от SDL2 была.
и можно было более легковесное приложение сделать, вообще без внешних зависимостей.
около 900К
а так, под win32 dlangui тоже можно собрать с поддержкой SDL — работает нормально
Обработка сигналов (событий) от виджетов
На один «Listener» можно навесить только один обработчик? А если захочется парадигмы сигналов-слотов как в Qt «многие ко многим» и с передачей каких-либо аргументов? Придётся делать обработчик-прокси и пихать в него всю логику?

Наверное вопрос вкуса и может в D так заведено с именованием в API, но для чего все эти сложные Java-like имена, вроде button.onClickListener, разве не было бы проще и лаконичнее что-то вроде button.clicked?
UFO just landed and posted this here
Когда я говорил «Java-like», я имел в виду не стиль написания objectName/object_name/..., а именование атрибутов в принципе. В Qt тоже используется objectName конвенция, но имена там обычно проще и менее громоздкие.

Логическая переменная у меня ассоциируется с isClicked. :)
Никогда не работали с JavaScript?
Если сигнал объявлен как
Signal!OnClickHandler — то можно вешать несколько обработчиков, с помощью connect и отключать из с помощью disconnect. Присваивание отсоединяет все подключенные слоты и заменяет их одним новым. С помощью ~= новый слот добавляется к имеющимся (аналог connect), -= отключает (то же, что disconnect).
Если объявлен как
Listener!OnClickHandler — то возможено подключение только одного слота
Listener используется вместо Signal там, где хочется сэкономить память ценой урезания функциональности (Listener в два раза меньше занимает памяти, чем Signal).

import dlangui.core.signals;

interface SomeInterface {
    bool someMethod(string s, int n);
}
class Foo : SomeInterface {
	override bool someMethod(string s, int n) {
		writeln("someMethod called ", s, ", ", n);
		return n > 10; // can return value
	}
}

// Listener! can hold arbitrary number of connected slots

// declare using list of return value and parameter types
Listener!(bool, string, n) signal1;

Foo f = new Foo();
// when signal is defined as type list, you can use delegate
signal1 = bool delegate(string s, int n) { writeln("inside delegate - ", s, n); return false; }
// or method reference
signal1 = &f.someMethod;

// declare using interface with single method
Listener!SomeInterface signal2;
// you still can use any delegate
signal2 = bool delegate(string s, int n) { writeln("inside delegate - ", s, n); return false; }
// but for class method which overrides interface method, you can use simple syntax
signal2 = f; // it will automatically take &f.someMethod


// call listener(s) either by opcall or explicit emit
signal1("text", 1);
signal1.emit("text", 2);
signal2.emit("text", 3);

// check if any slit is connected
if (signal1.assigned)
	writeln("has listeners");

// Signal! can hold arbitrary number of connected slots

// declare using list of return value and parameter types
Signal!(bool, string, n) signal3;

// add listeners via connect call
signal3.connect(bool delegate(string, int) { return false; });
// or via ~= operator
signal3 ~= bool delegate(string, int) { return false; };

// declare using interface with single method
Signal!SomeInterface signal4;

// you can connect several slots to signal
signal4 ~= f;
signal4 ~= bool delegate(string, int) { return true; }

// calling of listeners of Signal! is similar to Listener!
// using opCall
bool res = signal4("blah", 5);
// call listeners using emit
bool res = signal4.emit("blah", 5);

// you can disconnect individual slots
// using disconnect()
signal4.disconnect(f);
// or -= operator
signal4 -= f;



Экономия памяти настолько критична и существенна, что потребовалось вводить две сущности? Мне это кажется немного «накрученным». Как же принцип «Бритвы Оккама»? Возможно, это имеет смысл при разработке GUI для встраиваемых систем, например, под QNX.

Например, если стандартный виджет кнопки из коробки имеет только сигнал типа «Listener», а пользователю нужен полноценный сигнал для этой кнопки, то ему придётся создавать собственный класс виджета, расширяющий стандартный. В итоге, по памяти выигрыша не будет, а сущностей добавится, что никак не упростит программу и нарушит принцип KISS.

Это только моё мнение, я не утверждаю, что оно верное. Я не критикую библиотеку, здорово, что вы это делаете. Просто мне интересны некоторые архитектурные моменты, и я сам пытаюсь понять как лучше проектировать подобные вещи.
Я подумаю, может быть и выкину лишнее, оставлю Signal

Надо подумать.
Пока еще не поздно поменять.
Из вашего ответного комментария стало понятно, зачем в имени сигнала нужно слово «Listener», так как у вас есть сигналы двух типов.
Экспериментирую с добавлением новой платформы — отображение DlangUI виджетов поверх OpenGL сцены, отрисованной другим движком — SFML.

<img src="" alt=«image»/>

Рожица отрисована SFML, а виджеты — DlangUI.

Исходники файла, добавленного в dlangui для поддержки новой платформы.

Для SFML пока сделал только рисование, надо еще добавить трансляцию событий мыши и клавиатуры.

GitHub репозиторий с примером
UPD: уже работает мышь и клавиатура
Выглядит очень интересно. Кажется пришло время реанимировать один мой проект на D.
Sign up to leave a comment.

Articles