Immediate vs. Retained mode GUI

6yrop

Было приятно обнаружить, что оказывается есть тру другой путь для реализации GUI.
http://diamondtearz.org/immediate-mode-guis-a-different-way-...
Вот несколько интересных цитат:
“Immediate Mode Graphical User Interfaces are a renaissance movement to make people aware that when your abstraction breaks down, you have to take a step back and look at your problem with fresh eyes. If you’re no longer making a gui like every one else, then you don’t want to use the code that every one else is using.”- Immediate Mode Graphical User Interfaces from Smalltalk and My Misinterpretations of Life.
http://www.cincomsmalltalk.com/userblogs/mls/blogView?showCo...

The real savings is in the amount of effort required to implement bi-directional propagation of state between the application (the 'model' in MVC parlance and the GUI (or 'view').
Consider a fairly trivial example, of an application which maintains a list of items, and has a GUI to edit that list:
With an RMGUI, you iterate over the list of items at initialisation to build a list of items to display. When the user clicks the 'add' button, a message is sent to the application, which decides whether or not to add, an item is added to the list, and then a message must be sent back to the GUI to add the element to the list of displayed items. Want to edit an item? Message goes to application for validation, message goes back to the GUI to update the value. Want to delete an item? Same deal. Even when the application modifies an item internally, it has to send a message to the GUI to update the displayed item list.
If we go full-on Model-View-Controller, things just get even worse. Now the model doesn't know if/where it is being displayed, so it has to have an event system to notify the controller every time something changes. The view doesn't know what it is displaying, so it has to use events to notify the controller every time something changes. The controller needs buckets of glue code to connect the model and view together, and any change to model or view requires a matching change to the controller.
Apple solves this very elegantly through data binding, which effectively manages the controller layer for you through some library/language wizardry. However, it relies almost entirely on the highly dynamic nature of Objective-C, and isn't really reproducible in languages like C/C++.
An IMGUI allows you to implement a decent analogue of data binding in C/C++, and at the same time makes the whole concern fairly trivial. No need to propagate state in either direction, because the is only *one* set of state. No need to write buckets of glue code from controller to view, because the controller *is* the view.
http://www.gamedev.net/topic/574795-designing-a-gui-system-h...

As such I find some of the rhetoric about RMGUIs on the IMGUIs forums rather disturbing and annoying. They also have a thing against OO programming. It's an interesting read but it also ticks me off in unique and interesting ways. I should point out that coming from the Smalltalk world - we're less about being Object-Oriented-Programmers than Message-Oriented-Programmers.
http://www.cincomsmalltalk.com/userblogs/mls/blogView?showCo...

На текущий момент технологии делятся следующим образом:
Retained mode GUI: HTML/CSS, WPF, Silverlight, Flash.
Тормознутые Immediate mode GUI: WinForms, HTML5 Canvas.
Быстрые Immediate mode GUI: OpenGL, DirectX, XNA, Silverlight5 Immediate mode.
(список можно дополнять :) не дотнетом)

zorin29

Не знаю, чем интересны цитаты. Первая - ни о чем. Вторая - о том, что data binding - это круто. Третья - ни о чем.
Твоя классификация мне тоже не нравится. Из того, что я прочитал, retained mode - это event-driven GUI, а immediate-mode - это типа 'roll your own window cycle'.
Еще учти, что статья, на которую ты ссылаешься, датирована мартом 2009, а она, в свою очередь, ссылается на статьи 2007-го года.

6yrop

'roll your own window cycle'.
это ты про Win API что ли? Если, да, то immediate-mode это не то.

6yrop

Первая - ни о чем.
ну для кого как, если люди кроме виджитов (например, соседний тред) ничего представить не могут, то для них есть повод задуматься.
Вторая - о том, что data binding - это круто.

Как раз наоборот, говориться, что можно (и проще) без датабайдинга.
Третья - ни о чем.

Ну третья, да, обычная заметка про то, что задалбали везде думать через ООП.

zorin29

я про то, что стандартный "виндовый" оконный цикл

while (PeekMessage
{
TranslateMessage;
DispatchMessage;
}

- это начало event-driven GUI, когда есть сообщения от устройств типа мыши и клавиатуры, и есть их обработчики.
А immediate mode GUI не имеет оконного цикла, а вместо него реализует свой собственный цикл. Например, 100 раз в секунду вызывается функция Render которая и проверяет, что и где поменялось в GUI. Нет event-ов и handler-ов.
Как я понимаю, в компьютерных играх, как правило, используется второй подход, и большинство game engine-ов его всячески упрощают.

6yrop

которая и проверяет, что и где поменялось в GUI
в immediate моде просто заново формируется новый кадр

6yrop

Нет event-ов и handler-ов.
ну наверное сложно представить код (решающий хоть сколько-нибудь сложную задачу) без колбеков.

zorin29

в immediate моде просто заново формируется новый кадр
похоже, ты сходил не по всем своим ссылкам и не почитал некоторые примеры кода.
Например, как ты в рамках "заново формирования кадра" реализуешь функциональность кнопки (когда действие следует произвести после того, как кнопка мышки отпущена)?

Dasar

почему opengl и directx вдруг стали Immediate?
там же сцена целиком создается, а потом отрисовывается по требованию

6yrop

почему opengl и directx вдруг стали Immediate?
в opengl и directx есть и immediate, и retained.

6yrop

Например, как ты в рамках "заново формирования кадра" реализуешь функциональность кнопки (когда действие следует произвести после того, как кнопка мышки отпущена)?
ровно так как ты описал в этом приложении, в чем проблема?

zorin29

, а вы писали компьютерную игру на DirectX, OpenGL, XNA и т.д.? У вас там в игре была GUI?
Ну или вообще, писали ли вы подобную immediate-mode GUI? А то у меня ощущение, что я попал в сообщество теоретиков.

zorin29

ровно так как ты описал в этом приложении, в чем проблема?
Блин, проблема:
Кадр номер 50: координаты мыши (305, 201 кнопки не нажаты. Ничего делать не надо.
Кадр номер 355: координаты мыши (305, 201 кнопки не нажаты. Нужно произвести действия, соответствующие кнопке "quicksave".
Если не учитывать предыдущее состояние GUI (а именно то, что в кадре 354 левая кнопка мыши была НАЖАТА то различить эти две ситуации нельзя.
Поэтому твое утверждение, что "каждый кадр GUI генерится заново" неверно.

6yrop

, , а вы писали компьютерную игру на DirectX, OpenGL, XNA и т.д.? У вас там в игре была GUI?
игр на DirectX, XNA я не писал. Но вот хочу попробовать на XNA написать некоторый GUI. Если ты рубишь в этом вопросе, то просвети :), буду благодарен.

Dasar

, , а вы писали компьютерную игру на DirectX, OpenGL, XNA и т.д.? У вас там в игре была GUI?
маленькое исследовательское писал, и на opengl, и на directx
Ну или вообще, писали ли вы подобную immediate-mode GUI? А то у меня ощущение, что я попал в сообщество теоретиков.
но это - сторонник immediate-mode. я считаю, что будущее за retained-mode (но при этом он станет более гибким)

6yrop

(но при этом он станет более гибким)
2: вот для таких и была первая цитата.

Dasar

кстати, тут еще может быть проблема в терминах.
будущее за системами, где у программы есть единая модель, описанная в стандартизованном виде и состояние хранится в единственном экземпляре.
при этом стоит отметить: что сейчас первая фича "единая стандартизованная модель" - это фича retained mode, а вот фича "состояние в единственном экземпляре" - это фича immediate mode.
соответственно, в retained mode - приходится дублировать состояние: состояние есть и в "бизнес"-модели, и в объектах-gui, а у immediate mode - нет стандартизованной модели

6yrop

Вот, вот, я тоже клоню к “состоянию в единственном экземпляре”.
А вот “стандартизация” это что-то странное. Имхо, это что-то нереальное и утопичное. Пока даже намека нет на идеи, которые привели бы к “стандартизованной модели”.

6yrop

Блин, проблема:
Кадр номер 50: координаты мыши (305, 201 кнопки не нажаты. Ничего делать не надо.
Кадр номер 355: координаты мыши (305, 201 кнопки не нажаты. Нужно произвести действия, соответствующие кнопке "quicksave".
Если не учитывать предыдущее состояние GUI (а именно то, что в кадре 354 левая кнопка мыши была НАЖАТА то различить эти две ситуации нельзя.
Поэтому твое утверждение, что "каждый кадр GUI генерится заново" неверно.
Всё же не видно в чем проблема, возможно, ты не указываешь какие-то важные детали. Естественно, что у системы присутствует где-то состояние, и кадры генерятся с использование этого состояния. Клик мышки меняет это состояние. Но это необязательно состояние виджета.

6yrop

соответственно, в retained mode - приходится дублировать состояние: состояние есть и в "бизнес"-модели, и в объекта-gui
Кстати, это и есть основная причина полного fail-а(*1) современных GUI библиотек.
(*1)fail заключается в том, что зажираются тонны человека-часов на довольно простые UI-сценарии.

Dasar

Пока даже намека нет на идеи, которые привели бы к “стандартизованной модели”.
например, sql(как модель данных) + html (как модель gui)

6yrop

например, sql(как модель данных) + html (как модель gui)
где состояние? опять в двух местах?

Dasar

где состояние? опять в двух местах?
проблема в том, что в клиент-сервере у тебя всегда состояние будет в двух местах.
можно лишь фиксировать - где и какое состояние первично, а где вторично.

6yrop

проблема в том, что в клиент-сервере у тебя всегда состояние будет в двух местах.
мы пока говорим только о клиенте. В скольких местах храниться состояние на клиенте?

Dasar

мы пока говорим только о клиенте. В скольких местах храниться состояние на клиенте?
в html-е без ajax-а обычно хранится в одном месте.
при появлении ajax-а приходится хранить в двух местах, потому что html не предоставляет возможности для описания бизнес-модели и маппинга его в gui.

6yrop

в html-е без ajax-а обычно хранится в одном месте.
да, и это классно

при появлении ajax-а приходится хранить в двух местах, потому что html не предоставляет возможности для описания бизнес-модели и маппинга его в gui.

а что нам мешает при ajax-е действовать также как выше, т.е. менять на каждый чих html всей страницы? правильно, у html engine-а не хватает быстродействия. А Immediate mode как раз предоставляет высокую производительность при отрисовки экрана целиком. Этого нам и надо :D .

Dasar

а что нам мешает при ajax-е действовать также как выше, т.е. менять на каждый чих html всей страницы?
правильно, у html engine-а не хватает быстродействия.
не правильно.
основная проблема: высокая сложность такого описания.
например, zruty пытался сказать именно про это.
А Immediate mode как раз предоставляет высокую производительность при отрисовки экрана целиком. Этого нам и надо :D .
и immediate mode ни как не помогает уменьшать эту сложность.
зы
ты хочешь в ручную хранить состояние отжатая, нажатая, сфокусированная, первый кадр нажатия, 35-ый кадр нажатия, и опять же в ручную отслеживать и отрисовывать все эти состояния?
опять же если нет абстракций кнопка, список, таблица, дерево и т.д., то как будет проводится унификация для пользователя внешнего вида и поведения этих элементов?

6yrop

не правильно.
ты, кажется, не внимательно прочитал мой пост.
основная проблема: высокая сложность такого описания.

Высокая по сравнению с чем? Ниже, чем с Retained.
например, zruty пытался сказать именно про это.

У него это вышло очень не убедительно.
и immediate mode ни как не помогает уменьшать эту сложность.

Опять же, уменьшает по сравнению с чем?
ты хочешь в ручную хранить состояние отжатая, нажатая, сфокусированная, первый кадр нажатия, 35-ый кадр нажатия, и опять же в ручную отслеживать и отрисовывать все эти состояния?

Нравиться мне это слово “в ручную”, это как понимать, пальцы на руке загибать, или в блокнотик записывать? Естественно, реюз кода подразумевается по умолчанию. Но из него никак не вытекает, что мы должны дублировать состояние.
опять же если нет абстракций кнопка, список, таблица, дерево и т.д., то как будет проводится унификация для пользователя внешнего вида и поведения этих элементов?

Внешний вид можно увидеть, поведение можно пронаблюдать, поэтому с этим всё просто: абстракции идут лесом :p .

Dasar

Внешний вид можно увидеть, поведение можно пронаблюдать, поэтому с этим всё просто: абстракции идут лесом :p .
какой будет механизм по обеспечению стандартизации?
пока ты утверждаешь, что даже нельзя будет слово кнопка произносить, поэтому как можно стандартизовать то, что не выделяется и не называется я пока не представляю.

6yrop

какой будет механизм по обеспечению стандартизации?
в мировом масштабе или в рамках продукта или линейки продуктов?

6yrop

пока ты утверждаешь, что даже нельзя будет слово кнопка произносить
эээ, я такого не утверждал, слово кнопка в разговоре с пользователями и ваши ООП-абстракции это сильно разные вещи :) .

Dasar

в мировом масштабе или в рамках продукта или линейки продуктов?
в рамках продукта и линейки продуктов

Dasar

эээ, я такого не утверждал, слово кнопка в разговоре с пользователями и ваши ООП-абстракции это сильно разные вещи
а программисты это слово между собой использовать могут, или запрещено под страхом увольнения?
раздел проекта в котором будет описана в основном эта сущность будет называться "кнопка", или "не-знамо-что-номер-137"?
ваши ООП-абстракции это сильно разные вещи
всегда утверждалось, что отношение абстракция<->класс в виде 1к1 встречается только у школьников, после первых лекций о ООП

Dasar

абстракции же фиксируют не от того, что все ССЗБ, а от того, что если хочется поработать с 1млн. строк кода, то их необходимо декомпозировать на какое-то малое кол-во абстракций. причем в свете пресловутых 7+-3, то миллион строк - это 7 уровней детализации, где на каждом уровне деталей в 7 раз больше, чем на предыдущем
и это все надо обозвать, удержать в голове и т.д.

Bibi

будущее за системами
будущее за системами, которые будут нахерачены

apl13

Будущее ваще за системами, например!

bleyman

Всё же не видно в чем проблема, возможно, ты не указываешь какие-то важные детали. Естественно, что у системы присутствует где-то состояние, и кадры генерятся с использование этого состояния. Клик мышки меняет это состояние. Но это необязательно состояние виджета.
Я чота ваще перестал понимать, что ты пытаешься задвинуть!
Чьё же это состояние тогда?
Ты хочешь мессаги в модель посылать каждый раз когда юзер нажимает (но ещё не успел отпустить) кнопку? Ты хочешь чтобы у тебя в модели было состояние кнопки "нажата но не отпущена"? Состояние "glowing at 74% right now, 147ms since the cursor began hovering over it" тоже в модели должно быть? Я вовсе не за тормознутость всего этого напрягаюсь, между прочим...
Либо я не понимаю, что ты имеешь в виду, либо ты не понимаешь, что захламление модели собственными свойствами виджетов, типа вот таких, ваще ничего не "упрощает". И что разделение состояния на свойства виджетов и свойства модели приятно не своей энтерпрайзностью, а именно тем что вот оно-то и упрощает логику.
Потому что тогда у тебя есть (ну или может быть) простой, чоткий, формальный, узкий канал датабиндингов, и твою модель не волнует, к листбоксу или к комбобоксу ты подсоединяешь некое проперти, где на экране этот листбокс или комбобокс находится, в какой стадии находится его анимация, и так далее.
А если этот канал не настолько простой и чоткий как тебе бы хотелось, то улучшать надо простоту и чоткость, а не пытаться от него избавиться вовсе, что только перенесёт всю сложность в модель with a vengeance.
Ну то есть я не знаю, в чём понт-то вообще? У тебя это разделение по-любому вылезет. Лучше чтобы оно было формализовано заранее, а не ad hoc.

6yrop

 
Чьё же это состояние тогда?
Пофигу чьё. Вот именно, в правильной технике программирования вопрос “чьё” если и задается, то в последнюю очередь. Главное что состояние есть. Лучше, конечно, когда его нет. Если от него не отвертишься, тогда осознаем, что вот, да, оно есть, и мы его для того-то и того-то ввели. И делаем так, чтобы нам было удобно за ним следить, с ним работать. А вопрос “чьё” нам в этом скорее мешает, чем помогает. Это люди с ООП головного мозга начинают с вопроса “чьё”.
Правильные техники программирования в сочетании с современными средствами рефакторинга позволяют перемещать куски кода без особых проблем. Поэтому разложить по “папочкам” кусочки кода (если уж очень хочется) можно в любой момент, и всегда можно поменять эти “папочки”. А вот начинать с этого, и потом стараться не нарушать выбранную (как правило, не оптимально) в начале систему “папочек”, вот это плохо. Предсказывать будущее уже не модно, надо уметь меняться вместе с миром :).
 
Ты хочешь мессаги в модель посылать каждый раз когда юзер нажимает (но ещё не успел отпустить) кнопку? Ты хочешь чтобы у тебя в модели было состояние кнопки "нажата но не отпущена"? Состояние "glowing at 74% right now, 147ms since the cursor began hovering over it" тоже в модели должно быть? Я вовсе не за тормознутость всего этого напрягаюсь, между прочим...
Разделение на модель/не модель я пока не провожу, пока в этом нет необходимости. Как только увижу реальные бенефиты такого разделения, тогда и будем говорить о моделях и т.д. Сейчас идет речь о более базовых вещах.
 
Либо я не понимаю, что ты имеешь в виду, либо ты не понимаешь, что захламление модели собственными свойствами виджетов, типа вот таких, ваще ничего не "упрощает". И что разделение состояния на свойства виджетов и свойства модели приятно не своей энтерпрайзностью, а именно тем что вот оно-то и упрощает логику.
Это к вопросу разделения по “папочкам”. Вопрос второго, точнее, десятого плана.
 
Потому что тогда у тебя есть (ну или может быть) простой, чоткий, формальный, узкий канал датабиндингов, и твою модель не волнует, к листбоксу или к комбобоксу ты подсоединяешь некое проперти, где на экране этот листбокс или комбобокс находится, в какой стадии находится его анимация, и так далее.
В контексте нашего разговора пока нет ни модели, ни листбоксов. Пока не было приведено обоснования для введения таких сущностей и терминов. Поэтому говорить об этом рано.
 
А если этот канал не настолько простой и чоткий как тебе бы хотелось, то улучшать надо простоту и чоткость, а не пытаться от него избавиться вовсе, что только перенесёт всю сложность в модель with a vengeance.
Об этом тоже рано говорить, но, замечу, что в первом посте указана цитата, в которой говорится, что в Immediate моде бадабиндинг выглядит как тривиальная задача, по сути, там нет такой проблемы.
 
Ну то есть я не знаю, в чём понт-то вообще? У тебя это разделение по-любому вылезет. Лучше чтобы оно было формализовано заранее, а не ad hoc.
О разделении говорить рано, а о предсказывании будущего я уже отписался.

bleyman

Пофигу чьё. Вот именно, в правильной технике программирования вопрос “чьё” если и задается, то в последнюю очередь. [...] А вопрос “чьё” нам в этом скорее мешает, чем помогает. Это люди с ООП головного мозга начинают с вопроса “чьё”.
Я, когда этот вопрос задавал, задавал его не как мальчик, неспособный начать думать о проблеме не определив априори надцать сущностей, но как муж, прикинувший как оно всё может выглядеть исходя из своего немалого опыта решения подобных проблем, и спрашивающий: вот, допустим наконец настала "последняя очередь", и кому же теперь принадлежат разные части твоего состояния? Чем результат отличается от полученного традиционным образом? Стоило ли оно того?
Если тебе не хочется обсуждать проблему в этом ключе, то я вообще не понимаю, что ты хочешь обсуждать. Стоит ли тебе попытаться сделать свою immediate mode систему не задумываясь о том, чем всё кончится, потому что это не аджильно? Ну, сделай, чо, флаг тебе в руки, барабан на шею и паровоз навстречу...
Алсо, я кстати вспомнил что я же совокуплялся с некоей простенькой микрософтовской шняжкой для ГУИ в ДиректХ. Ну, там конечно было полтора упрощения: во-первых, поскольку приложение как бы должно жрать всё процессорное время по задумке, виджеты типа кнопок перегенерят своё представление (цвет и прочее) на каждом кадре, даже если ничего не изменилось. Поэтому не нужно уведомлять их об изменениях. Во-вторых, по той же причине нет геморроя с InvalidateRect и отрисовкой только нужного в Invalidated Region.
Я не могу сказать, что эти упрощения решили какую-то важную проблему, которая меня ужасно заботила и мешала жить. И что они стоят того, чтобы жрать весь процессор. Мне как бы пофиг на эти небольшие сложности, например. Мне например мешает жить неустроенность с layout managers и различными размерами шрифтов, типа, как бы так всё организовать, чтобы текст всегда помещался в клиент ареа кнопки. Вот это например интересная проблема. А посылка кнопке сообщения что у неё текст изменился — неинтересная проблема.

6yrop

Мне например мешает жить неустроенность с layout managers и различными размерами шрифтов, типа, как бы так всё организовать, чтобы текст всегда помещался в клиент ареа кнопки. Вот это например интересная проблема.
Замечу, что в такой формулировке задача не имеет решения, Война и Мир по любому не поместится на кнопке. Но, кажется, что на интуитивном уровне твое желание понять можно.
С другой стороны, задача достаточно простая: разместить прямоугольники (пока для простоты) на плоскости. То есть выразить в коде некоторые требования и, исходя из этих требований, запрограммировать вычисления координат прямоугольников. На мой взгляд, язык C# и современные инструменты разработки позволяют получить решение указанной задачи через последовательность небольших шагов. То есть в результате ненапряжного процесса получить решение. C# код же настолько хорошо, что записываешь на нем кусочки требований, и шаг за шагом либо получаешь решение, либо доказываешь, что решения не существует, и тогда меняешь требования, и смотришь опять. Просто овладеваешь приемами работы с кодом, а не выдумываешь всяких менеджеров.
А вопрос этого треда в том, что хочется работать в коде напрямую с геометрией, а не с деривативами типа контролов.
Оставить комментарий
Имя или ник:
Комментарий: